mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 15:41:46 +00:00
[clang] Enable descriptions for --print-supported-extensions (#66715)
Enables summary descriptions along with the names of the feature. Descriptions here are simply looked up via the available llvm tablegen data.
This commit is contained in:
parent
4c14638b55
commit
73779bb209
@ -4,14 +4,20 @@
|
||||
// RUN: %if aarch64-registered-target %{ %clang --target=aarch64-linux-gnu \
|
||||
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix AARCH64 %}
|
||||
// AARCH64: All available -march extensions for AArch64
|
||||
// AARCH64: Name Description
|
||||
// AARCH64: aes Enable AES support (FEAT_AES, FEAT_PMULL)
|
||||
|
||||
// RUN: %if riscv-registered-target %{ %clang --target=riscv64-linux-gnu \
|
||||
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix RISCV %}
|
||||
// RISCV: All available -march extensions for RISC-V
|
||||
// RISCV: Name Version Description
|
||||
// RISCV: i 2.1
|
||||
|
||||
// RUN: %if arm-registered-target %{ %clang --target=arm-linux-gnu \
|
||||
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix ARM %}
|
||||
// ARM: All available -march extensions for ARM
|
||||
// ARM: Name Description
|
||||
// ARM: crc Enable support for CRC instructions
|
||||
|
||||
// RUN: %if x86-registered-target %{ not %clang --target=x86_64-linux-gnu \
|
||||
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix X86 %}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/LinkAllPasses.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Option/Arg.h"
|
||||
#include "llvm/Option/ArgList.h"
|
||||
@ -198,13 +199,20 @@ static int PrintSupportedExtensions(std::string TargetStr) {
|
||||
std::unique_ptr<llvm::TargetMachine> TheTargetMachine(
|
||||
TheTarget->createTargetMachine(TargetStr, "", "", Options, std::nullopt));
|
||||
const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple();
|
||||
const llvm::MCSubtargetInfo *MCInfo = TheTargetMachine->getMCSubtargetInfo();
|
||||
const llvm::ArrayRef<llvm::SubtargetFeatureKV> Features =
|
||||
MCInfo->getAllProcessorFeatures();
|
||||
|
||||
llvm::StringMap<llvm::StringRef> DescMap;
|
||||
for (const llvm::SubtargetFeatureKV &feature : Features)
|
||||
DescMap.insert({feature.Key, feature.Desc});
|
||||
|
||||
if (MachineTriple.isRISCV())
|
||||
llvm::riscvExtensionsHelp();
|
||||
llvm::riscvExtensionsHelp(DescMap);
|
||||
else if (MachineTriple.isAArch64())
|
||||
llvm::AArch64::PrintSupportedExtensions();
|
||||
llvm::AArch64::PrintSupportedExtensions(DescMap);
|
||||
else if (MachineTriple.isARM())
|
||||
llvm::ARM::PrintSupportedExtensions();
|
||||
llvm::ARM::PrintSupportedExtensions(DescMap);
|
||||
else {
|
||||
// The option was already checked in Driver::HandleImmediateArgs,
|
||||
// so we do not expect to get here if we are not a supported architecture.
|
||||
|
@ -230,10 +230,16 @@ public:
|
||||
return Found != ProcDesc.end() && StringRef(Found->Key) == CPU;
|
||||
}
|
||||
|
||||
/// Return processor descriptions.
|
||||
ArrayRef<SubtargetSubTypeKV> getAllProcessorDescriptions() const {
|
||||
return ProcDesc;
|
||||
}
|
||||
|
||||
/// Return processor features.
|
||||
ArrayRef<SubtargetFeatureKV> getAllProcessorFeatures() const {
|
||||
return ProcFeatures;
|
||||
}
|
||||
|
||||
virtual unsigned getHwMode() const { return 0; }
|
||||
|
||||
/// Return the cache size in bytes for the given level of cache.
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef LLVM_SUPPORT_RISCVISAINFO_H
|
||||
#define LLVM_SUPPORT_RISCVISAINFO_H
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
@ -22,7 +23,7 @@ struct RISCVExtensionInfo {
|
||||
unsigned MinorVersion;
|
||||
};
|
||||
|
||||
void riscvExtensionsHelp();
|
||||
void riscvExtensionsHelp(StringMap<StringRef> DescMap);
|
||||
|
||||
class RISCVISAInfo {
|
||||
public:
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Bitset.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/VersionTuple.h"
|
||||
#include <array>
|
||||
@ -663,7 +664,7 @@ bool isX18ReservedByDefault(const Triple &TT);
|
||||
// themselves, they are sequential (0, 1, 2, 3, ...).
|
||||
uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
|
||||
|
||||
void PrintSupportedExtensions();
|
||||
void PrintSupportedExtensions(StringMap<StringRef> DescMap);
|
||||
|
||||
} // namespace AArch64
|
||||
} // namespace llvm
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef LLVM_TARGETPARSER_ARMTARGETPARSER_H
|
||||
#define LLVM_TARGETPARSER_ARMTARGETPARSER_H
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/ARMBuildAttributes.h"
|
||||
#include "llvm/TargetParser/ARMTargetParserCommon.h"
|
||||
@ -259,7 +260,7 @@ StringRef computeDefaultTargetABI(const Triple &TT, StringRef CPU);
|
||||
/// string then the triple's arch name is used.
|
||||
StringRef getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch = {});
|
||||
|
||||
void PrintSupportedExtensions();
|
||||
void PrintSupportedExtensions(StringMap<StringRef> DescMap);
|
||||
|
||||
} // namespace ARM
|
||||
} // namespace llvm
|
||||
|
@ -210,24 +210,36 @@ static void verifyTables() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void llvm::riscvExtensionsHelp() {
|
||||
static void PrintExtension(const std::string Name, const std::string Version,
|
||||
const std::string Description) {
|
||||
outs() << " "
|
||||
<< format(Description.empty() ? "%-20s%s\n" : "%-20s%-10s%s\n",
|
||||
Name.c_str(), Version.c_str(), Description.c_str());
|
||||
}
|
||||
|
||||
void llvm::riscvExtensionsHelp(StringMap<StringRef> DescMap) {
|
||||
|
||||
outs() << "All available -march extensions for RISC-V\n\n";
|
||||
outs() << '\t' << left_justify("Name", 20) << "Version\n";
|
||||
PrintExtension("Name", "Version", (DescMap.empty() ? "" : "Description"));
|
||||
|
||||
RISCVISAInfo::OrderedExtensionMap ExtMap;
|
||||
for (const auto &E : SupportedExtensions)
|
||||
ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
|
||||
for (const auto &E : ExtMap)
|
||||
outs() << format("\t%-20s%d.%d\n", E.first.c_str(), E.second.MajorVersion,
|
||||
E.second.MinorVersion);
|
||||
for (const auto &E : ExtMap) {
|
||||
std::string Version = std::to_string(E.second.MajorVersion) + "." +
|
||||
std::to_string(E.second.MinorVersion);
|
||||
PrintExtension(E.first, Version, DescMap[E.first].str());
|
||||
}
|
||||
|
||||
outs() << "\nExperimental extensions\n";
|
||||
ExtMap.clear();
|
||||
for (const auto &E : SupportedExperimentalExtensions)
|
||||
ExtMap[E.Name] = {E.Version.Major, E.Version.Minor};
|
||||
for (const auto &E : ExtMap)
|
||||
outs() << format("\t%-20s%d.%d\n", E.first.c_str(), E.second.MajorVersion,
|
||||
E.second.MinorVersion);
|
||||
for (const auto &E : ExtMap) {
|
||||
std::string Version = std::to_string(E.second.MajorVersion) + "." +
|
||||
std::to_string(E.second.MinorVersion);
|
||||
PrintExtension(E.first, Version, DescMap["experimental-" + E.first].str());
|
||||
}
|
||||
|
||||
outs() << "\nUse -march to specify the target's extension.\n"
|
||||
"For example, clang -march=rv32i_v1p0\n";
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/TargetParser/AArch64TargetParser.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TargetParser/ARMTargetParserCommon.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
@ -135,11 +136,17 @@ std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void AArch64::PrintSupportedExtensions() {
|
||||
outs() << "All available -march extensions for AArch64\n\n";
|
||||
void AArch64::PrintSupportedExtensions(StringMap<StringRef> DescMap) {
|
||||
outs() << "All available -march extensions for AArch64\n\n"
|
||||
<< " " << left_justify("Name", 20)
|
||||
<< (DescMap.empty() ? "\n" : "Description\n");
|
||||
for (const auto &Ext : Extensions) {
|
||||
// Extensions without a feature cannot be used with -march.
|
||||
if (!Ext.Feature.empty())
|
||||
outs() << '\t' << Ext.Name << "\n";
|
||||
if (!Ext.Feature.empty()) {
|
||||
std::string Description = DescMap[Ext.Name].str();
|
||||
outs() << " "
|
||||
<< format(Description.empty() ? "%s\n" : "%-20s%s\n",
|
||||
Ext.Name.str().c_str(), Description.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "llvm/TargetParser/ARMTargetParser.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TargetParser/ARMTargetParserCommon.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
@ -600,11 +601,17 @@ StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) {
|
||||
llvm_unreachable("invalid arch name");
|
||||
}
|
||||
|
||||
void ARM::PrintSupportedExtensions() {
|
||||
outs() << "All available -march extensions for ARM\n\n";
|
||||
void ARM::PrintSupportedExtensions(StringMap<StringRef> DescMap) {
|
||||
outs() << "All available -march extensions for ARM\n\n"
|
||||
<< " " << left_justify("Name", 20)
|
||||
<< (DescMap.empty() ? "\n" : "Description\n");
|
||||
for (const auto &Ext : ARCHExtNames) {
|
||||
// Extensions without a feature cannot be used with -march.
|
||||
if (!Ext.Feature.empty())
|
||||
outs() << '\t' << Ext.Name << "\n";
|
||||
if (!Ext.Feature.empty()) {
|
||||
std::string Description = DescMap[Ext.Name].str();
|
||||
outs() << " "
|
||||
<< format(Description.empty() ? "%s\n" : "%-20s%s\n",
|
||||
Ext.Name.str().c_str(), Description.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/RISCVISAInfo.h"
|
||||
#include "llvm/Testing/Support/Error.h"
|
||||
#include "gtest/gtest.h"
|
||||
@ -631,134 +632,137 @@ TEST(RiscvExtensionsHelp, CheckExtensions) {
|
||||
std::string ExpectedOutput =
|
||||
R"(All available -march extensions for RISC-V
|
||||
|
||||
Name Version
|
||||
i 2.1
|
||||
e 2.0
|
||||
m 2.0
|
||||
a 2.1
|
||||
f 2.2
|
||||
d 2.2
|
||||
c 2.0
|
||||
v 1.0
|
||||
h 1.0
|
||||
zicbom 1.0
|
||||
zicbop 1.0
|
||||
zicboz 1.0
|
||||
zicntr 2.0
|
||||
zicsr 2.0
|
||||
zifencei 2.0
|
||||
zihintntl 1.0
|
||||
zihintpause 2.0
|
||||
zihpm 2.0
|
||||
zmmul 1.0
|
||||
zawrs 1.0
|
||||
zfh 1.0
|
||||
zfhmin 1.0
|
||||
zfinx 1.0
|
||||
zdinx 1.0
|
||||
zca 1.0
|
||||
zcb 1.0
|
||||
zcd 1.0
|
||||
zce 1.0
|
||||
zcf 1.0
|
||||
zcmp 1.0
|
||||
zcmt 1.0
|
||||
zba 1.0
|
||||
zbb 1.0
|
||||
zbc 1.0
|
||||
zbkb 1.0
|
||||
zbkc 1.0
|
||||
zbkx 1.0
|
||||
zbs 1.0
|
||||
zk 1.0
|
||||
zkn 1.0
|
||||
zknd 1.0
|
||||
zkne 1.0
|
||||
zknh 1.0
|
||||
zkr 1.0
|
||||
zks 1.0
|
||||
zksed 1.0
|
||||
zksh 1.0
|
||||
zkt 1.0
|
||||
zve32f 1.0
|
||||
zve32x 1.0
|
||||
zve64d 1.0
|
||||
zve64f 1.0
|
||||
zve64x 1.0
|
||||
zvfh 1.0
|
||||
zvfhmin 1.0
|
||||
zvl1024b 1.0
|
||||
zvl128b 1.0
|
||||
zvl16384b 1.0
|
||||
zvl2048b 1.0
|
||||
zvl256b 1.0
|
||||
zvl32768b 1.0
|
||||
zvl32b 1.0
|
||||
zvl4096b 1.0
|
||||
zvl512b 1.0
|
||||
zvl64b 1.0
|
||||
zvl65536b 1.0
|
||||
zvl8192b 1.0
|
||||
zhinx 1.0
|
||||
zhinxmin 1.0
|
||||
svinval 1.0
|
||||
svnapot 1.0
|
||||
svpbmt 1.0
|
||||
xcvalu 1.0
|
||||
xcvbi 1.0
|
||||
xcvbitmanip 1.0
|
||||
xcvmac 1.0
|
||||
xcvsimd 1.0
|
||||
xsfcie 1.0
|
||||
xsfvcp 1.0
|
||||
xtheadba 1.0
|
||||
xtheadbb 1.0
|
||||
xtheadbs 1.0
|
||||
xtheadcmo 1.0
|
||||
xtheadcondmov 1.0
|
||||
xtheadfmemidx 1.0
|
||||
xtheadmac 1.0
|
||||
xtheadmemidx 1.0
|
||||
xtheadmempair 1.0
|
||||
xtheadsync 1.0
|
||||
xtheadvdot 1.0
|
||||
xventanacondops 1.0
|
||||
Name Version Description
|
||||
i 2.1 This is a long dummy description
|
||||
e 2.0
|
||||
m 2.0
|
||||
a 2.1
|
||||
f 2.2
|
||||
d 2.2
|
||||
c 2.0
|
||||
v 1.0
|
||||
h 1.0
|
||||
zicbom 1.0
|
||||
zicbop 1.0
|
||||
zicboz 1.0
|
||||
zicntr 2.0
|
||||
zicsr 2.0
|
||||
zifencei 2.0
|
||||
zihintntl 1.0
|
||||
zihintpause 2.0
|
||||
zihpm 2.0
|
||||
zmmul 1.0
|
||||
zawrs 1.0
|
||||
zfh 1.0
|
||||
zfhmin 1.0
|
||||
zfinx 1.0
|
||||
zdinx 1.0
|
||||
zca 1.0
|
||||
zcb 1.0
|
||||
zcd 1.0
|
||||
zce 1.0
|
||||
zcf 1.0
|
||||
zcmp 1.0
|
||||
zcmt 1.0
|
||||
zba 1.0
|
||||
zbb 1.0
|
||||
zbc 1.0
|
||||
zbkb 1.0
|
||||
zbkc 1.0
|
||||
zbkx 1.0
|
||||
zbs 1.0
|
||||
zk 1.0
|
||||
zkn 1.0
|
||||
zknd 1.0
|
||||
zkne 1.0
|
||||
zknh 1.0
|
||||
zkr 1.0
|
||||
zks 1.0
|
||||
zksed 1.0
|
||||
zksh 1.0
|
||||
zkt 1.0
|
||||
zve32f 1.0
|
||||
zve32x 1.0
|
||||
zve64d 1.0
|
||||
zve64f 1.0
|
||||
zve64x 1.0
|
||||
zvfh 1.0
|
||||
zvfhmin 1.0
|
||||
zvl1024b 1.0
|
||||
zvl128b 1.0
|
||||
zvl16384b 1.0
|
||||
zvl2048b 1.0
|
||||
zvl256b 1.0
|
||||
zvl32768b 1.0
|
||||
zvl32b 1.0
|
||||
zvl4096b 1.0
|
||||
zvl512b 1.0
|
||||
zvl64b 1.0
|
||||
zvl65536b 1.0
|
||||
zvl8192b 1.0
|
||||
zhinx 1.0
|
||||
zhinxmin 1.0
|
||||
svinval 1.0
|
||||
svnapot 1.0
|
||||
svpbmt 1.0
|
||||
xcvalu 1.0
|
||||
xcvbi 1.0
|
||||
xcvbitmanip 1.0
|
||||
xcvmac 1.0
|
||||
xcvsimd 1.0
|
||||
xsfcie 1.0
|
||||
xsfvcp 1.0
|
||||
xtheadba 1.0
|
||||
xtheadbb 1.0
|
||||
xtheadbs 1.0
|
||||
xtheadcmo 1.0
|
||||
xtheadcondmov 1.0
|
||||
xtheadfmemidx 1.0
|
||||
xtheadmac 1.0
|
||||
xtheadmemidx 1.0
|
||||
xtheadmempair 1.0
|
||||
xtheadsync 1.0
|
||||
xtheadvdot 1.0
|
||||
xventanacondops 1.0
|
||||
|
||||
Experimental extensions
|
||||
zicfilp 0.2
|
||||
zicond 1.0
|
||||
zacas 1.0
|
||||
zfa 0.2
|
||||
zfbfmin 0.8
|
||||
ztso 0.1
|
||||
zvbb 1.0
|
||||
zvbc 1.0
|
||||
zvfbfmin 0.8
|
||||
zvfbfwma 0.8
|
||||
zvkb 1.0
|
||||
zvkg 1.0
|
||||
zvkn 1.0
|
||||
zvknc 1.0
|
||||
zvkned 1.0
|
||||
zvkng 1.0
|
||||
zvknha 1.0
|
||||
zvknhb 1.0
|
||||
zvks 1.0
|
||||
zvksc 1.0
|
||||
zvksed 1.0
|
||||
zvksg 1.0
|
||||
zvksh 1.0
|
||||
zvkt 1.0
|
||||
smaia 1.0
|
||||
ssaia 1.0
|
||||
zicfilp 0.2 This is a long dummy description
|
||||
zicond 1.0
|
||||
zacas 1.0
|
||||
zfa 0.2
|
||||
zfbfmin 0.8
|
||||
ztso 0.1
|
||||
zvbb 1.0
|
||||
zvbc 1.0
|
||||
zvfbfmin 0.8
|
||||
zvfbfwma 0.8
|
||||
zvkb 1.0
|
||||
zvkg 1.0
|
||||
zvkn 1.0
|
||||
zvknc 1.0
|
||||
zvkned 1.0
|
||||
zvkng 1.0
|
||||
zvknha 1.0
|
||||
zvknhb 1.0
|
||||
zvks 1.0
|
||||
zvksc 1.0
|
||||
zvksed 1.0
|
||||
zvksg 1.0
|
||||
zvksh 1.0
|
||||
zvkt 1.0
|
||||
smaia 1.0
|
||||
ssaia 1.0
|
||||
|
||||
Use -march to specify the target's extension.
|
||||
For example, clang -march=rv32i_v1p0)";
|
||||
|
||||
StringMap<StringRef> DummyMap;
|
||||
DummyMap["i"] = "This is a long dummy description";
|
||||
DummyMap["experimental-zicfilp"] = "This is a long dummy description";
|
||||
|
||||
outs().flush();
|
||||
testing::internal::CaptureStdout();
|
||||
|
||||
llvm::riscvExtensionsHelp();
|
||||
riscvExtensionsHelp(DummyMap);
|
||||
outs().flush();
|
||||
|
||||
std::string CapturedOutput = testing::internal::GetCapturedStdout();
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "llvm/TargetParser/TargetParser.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/ARMBuildAttributes.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
@ -1012,11 +1013,17 @@ TEST(TargetParserTest, getARMCPUForArch) {
|
||||
|
||||
TEST(TargetParserTest, ARMPrintSupportedExtensions) {
|
||||
std::string expected = "All available -march extensions for ARM\n\n"
|
||||
"\tcrc\n\tcrypto\n\tsha2";
|
||||
" Name Description\n"
|
||||
" crc This is a long dummy description\n"
|
||||
" crypto\n"
|
||||
" sha2\n";
|
||||
|
||||
StringMap<StringRef> DummyMap;
|
||||
DummyMap["crc"] = "This is a long dummy description";
|
||||
|
||||
outs().flush();
|
||||
testing::internal::CaptureStdout();
|
||||
ARM::PrintSupportedExtensions();
|
||||
ARM::PrintSupportedExtensions(DummyMap);
|
||||
outs().flush();
|
||||
std::string captured = testing::internal::GetCapturedStdout();
|
||||
|
||||
@ -1932,11 +1939,17 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {
|
||||
|
||||
TEST(TargetParserTest, AArch64PrintSupportedExtensions) {
|
||||
std::string expected = "All available -march extensions for AArch64\n\n"
|
||||
"\taes\n\tb16b16\n\tbf16";
|
||||
" Name Description\n"
|
||||
" aes This is a long dummy description\n"
|
||||
" b16b16\n"
|
||||
" bf16\n";
|
||||
|
||||
StringMap<StringRef> DummyMap;
|
||||
DummyMap["aes"] = "This is a long dummy description";
|
||||
|
||||
outs().flush();
|
||||
testing::internal::CaptureStdout();
|
||||
AArch64::PrintSupportedExtensions();
|
||||
AArch64::PrintSupportedExtensions(DummyMap);
|
||||
outs().flush();
|
||||
std::string captured = testing::internal::GetCapturedStdout();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user