mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-04 03:17:51 +00:00
Fix Clang-tidy modernize-use-bool-literals in generated Target code; other minor fixes; other minor fixes.
Make generated code more readable. Fix some Include What You Use warnings. Differential revision: http://reviews.llvm.org/D20317 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269783 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4a038a7aac
commit
d307f96d68
@ -16,22 +16,38 @@
|
||||
#include "CodeGenRegisters.h"
|
||||
#include "CodeGenTarget.h"
|
||||
#include "SequenceToOffsetTable.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SparseBitVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/CodeGen/MachineValueType.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/SetTheory.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class RegisterInfoEmitter {
|
||||
RecordKeeper &Records;
|
||||
|
||||
public:
|
||||
RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
|
||||
|
||||
@ -65,7 +81,8 @@ private:
|
||||
void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank,
|
||||
const std::string &ClassName);
|
||||
};
|
||||
} // End anonymous namespace
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// runEnums - Print out enum values for all of the registers.
|
||||
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
@ -81,7 +98,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
emitSourceFileHeader("Target Register Enum Values", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_ENUM\n";
|
||||
OS << "#undef GET_REGINFO_ENUM\n";
|
||||
OS << "#undef GET_REGINFO_ENUM\n\n";
|
||||
|
||||
OS << "namespace llvm {\n\n";
|
||||
|
||||
@ -100,7 +117,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
|
||||
OS << "};\n";
|
||||
if (!Namespace.empty())
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << Namespace << "\n";
|
||||
|
||||
const auto &RegisterClasses = Bank.getRegClasses();
|
||||
if (!RegisterClasses.empty()) {
|
||||
@ -109,7 +126,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
assert(RegisterClasses.size() <= 0xffff &&
|
||||
"Too many register classes to fit in tables");
|
||||
|
||||
OS << "\n// Register classes\n";
|
||||
OS << "\n// Register classes\n\n";
|
||||
if (!Namespace.empty())
|
||||
OS << "namespace " << Namespace << " {\n";
|
||||
OS << "enum {\n";
|
||||
@ -118,14 +135,14 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
<< " = " << RC.EnumValue << ",\n";
|
||||
OS << "\n };\n";
|
||||
if (!Namespace.empty())
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << Namespace << "\n\n";
|
||||
}
|
||||
|
||||
const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
|
||||
// If the only definition is the default NoRegAltName, we don't need to
|
||||
// emit anything.
|
||||
if (RegAltNameIndices.size() > 1) {
|
||||
OS << "\n// Register alternate name indices\n";
|
||||
OS << "\n// Register alternate name indices\n\n";
|
||||
if (!Namespace.empty())
|
||||
OS << "namespace " << Namespace << " {\n";
|
||||
OS << "enum {\n";
|
||||
@ -134,12 +151,12 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n";
|
||||
OS << "};\n";
|
||||
if (!Namespace.empty())
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << Namespace << "\n\n";
|
||||
}
|
||||
|
||||
auto &SubRegIndices = Bank.getSubRegIndices();
|
||||
if (!SubRegIndices.empty()) {
|
||||
OS << "\n// Subregister indices\n";
|
||||
OS << "\n// Subregister indices\n\n";
|
||||
std::string Namespace = SubRegIndices.front().getNamespace();
|
||||
if (!Namespace.empty())
|
||||
OS << "namespace " << Namespace << " {\n";
|
||||
@ -149,10 +166,10 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
|
||||
OS << " " << Idx.getName() << ",\t// " << ++i << "\n";
|
||||
OS << " NUM_TARGET_SUBREGS\n};\n";
|
||||
if (!Namespace.empty())
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << Namespace << "\n\n";
|
||||
}
|
||||
|
||||
OS << "} // End llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
OS << "#endif // GET_REGINFO_ENUM\n\n";
|
||||
}
|
||||
|
||||
@ -800,7 +817,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
emitSourceFileHeader("MC Register Information", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
|
||||
OS << "#undef GET_REGINFO_MC_DESC\n";
|
||||
OS << "#undef GET_REGINFO_MC_DESC\n\n";
|
||||
|
||||
const auto &Regs = RegBank.getRegisters();
|
||||
|
||||
@ -999,7 +1016,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
OS << "\n };\n\n";
|
||||
|
||||
}
|
||||
OS << "}\n\n";
|
||||
OS << "} // end anonymous namespace\n\n";
|
||||
|
||||
RegClassStrings.layout();
|
||||
OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
|
||||
@ -1023,7 +1040,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
<< RC.SpillSize/8 << ", "
|
||||
<< RC.SpillAlignment/8 << ", "
|
||||
<< RC.CopyCost << ", "
|
||||
<< RC.Allocatable << " },\n";
|
||||
<< ( RC.Allocatable ? "true" : "false" ) << " },\n";
|
||||
}
|
||||
|
||||
OS << "};\n\n";
|
||||
@ -1066,7 +1083,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "} // End llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
OS << "#endif // GET_REGINFO_MC_DESC\n\n";
|
||||
}
|
||||
|
||||
@ -1076,7 +1093,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
|
||||
emitSourceFileHeader("Register Information Header Fragment", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_HEADER\n";
|
||||
OS << "#undef GET_REGINFO_HEADER\n";
|
||||
OS << "#undef GET_REGINFO_HEADER\n\n";
|
||||
|
||||
const std::string &TargetName = Target.getName();
|
||||
std::string ClassName = TargetName + "GenRegisterInfo";
|
||||
@ -1130,9 +1147,9 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
|
||||
// Output the extern for the instance.
|
||||
OS << " extern const TargetRegisterClass " << Name << "RegClass;\n";
|
||||
}
|
||||
OS << "} // end of namespace " << TargetName << "\n\n";
|
||||
OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n";
|
||||
}
|
||||
OS << "} // End llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
OS << "#endif // GET_REGINFO_HEADER\n\n";
|
||||
}
|
||||
|
||||
@ -1145,7 +1162,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
emitSourceFileHeader("Target Register and Register Classes Information", OS);
|
||||
|
||||
OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
|
||||
OS << "#undef GET_REGINFO_TARGET_DESC\n";
|
||||
OS << "#undef GET_REGINFO_TARGET_DESC\n\n";
|
||||
|
||||
OS << "namespace llvm {\n\n";
|
||||
|
||||
@ -1325,7 +1342,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
OS << " };\n\n";
|
||||
}
|
||||
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n";
|
||||
}
|
||||
|
||||
OS << "\nnamespace {\n";
|
||||
@ -1333,19 +1350,20 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
for (const auto &RC : RegisterClasses)
|
||||
OS << " &" << RC.getQualifiedName() << "RegClass,\n";
|
||||
OS << " };\n";
|
||||
OS << "}\n"; // End of anonymous namespace...
|
||||
OS << "} // end anonymous namespace\n";
|
||||
|
||||
// Emit extra information about registers.
|
||||
const std::string &TargetName = Target.getName();
|
||||
OS << "\nstatic const TargetRegisterInfoDesc "
|
||||
<< TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
|
||||
OS << " { 0, 0 },\n";
|
||||
OS << " { 0, false },\n";
|
||||
|
||||
const auto &Regs = RegBank.getRegisters();
|
||||
for (const auto &Reg : Regs) {
|
||||
OS << " { ";
|
||||
OS << Reg.CostPerUse << ", "
|
||||
<< int(AllocatableRegs.count(Reg.TheDef)) << " },\n";
|
||||
<< ( AllocatableRegs.count(Reg.TheDef) != 0 ? "true" : "false" )
|
||||
<< " },\n";
|
||||
}
|
||||
OS << "};\n"; // End of register descriptors...
|
||||
|
||||
@ -1433,7 +1451,6 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
|
||||
OS << "}\n\n";
|
||||
|
||||
|
||||
// Emit CalleeSavedRegs information.
|
||||
std::vector<Record*> CSRSets =
|
||||
Records.getAllDerivedDefinitions("CalleeSavedRegs");
|
||||
@ -1501,7 +1518,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
|
||||
<< " MF.getSubtarget().getFrameLowering());\n"
|
||||
<< "}\n\n";
|
||||
|
||||
OS << "} // End llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
|
||||
}
|
||||
|
||||
@ -1522,4 +1539,4 @@ void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS) {
|
||||
RegisterInfoEmitter(RK).run(OS);
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
} // end namespace llvm
|
||||
|
@ -13,16 +13,20 @@
|
||||
|
||||
#include "CodeGenTarget.h"
|
||||
#include "CodeGenSchedule.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/MC/MCInstrItineraries.h"
|
||||
#include "llvm/MC/MCSchedule.h"
|
||||
#include "llvm/MC/SubtargetFeature.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/TableGen/Error.h"
|
||||
#include "llvm/TableGen/Record.h"
|
||||
#include "llvm/TableGen/TableGenBackend.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -32,6 +36,7 @@ using namespace llvm;
|
||||
#define DEBUG_TYPE "subtarget-emitter"
|
||||
|
||||
namespace {
|
||||
|
||||
class SubtargetEmitter {
|
||||
// Each processor has a SchedClassDesc table with an entry for each SchedClass.
|
||||
// The SchedClassDesc table indexes into a global write resource table, write
|
||||
@ -107,6 +112,7 @@ public:
|
||||
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
//
|
||||
@ -142,7 +148,8 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS) {
|
||||
}
|
||||
|
||||
// Close enumeration and namespace
|
||||
OS << "};\n}\n";
|
||||
OS << "};\n";
|
||||
OS << "} // end namespace " << Target << "\n";
|
||||
}
|
||||
|
||||
//
|
||||
@ -374,7 +381,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
|
||||
OS << " const unsigned " << FUs[j]->getName()
|
||||
<< " = 1 << " << j << ";\n";
|
||||
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << Name << "FU\n";
|
||||
|
||||
std::vector<Record*> BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
|
||||
if (!BPs.empty()) {
|
||||
@ -386,7 +393,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
|
||||
OS << " const unsigned " << BPs[j]->getName()
|
||||
<< " = 1 << " << j << ";\n";
|
||||
|
||||
OS << "}\n";
|
||||
OS << "} // end namespace " << Name << "Bypass\n";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1114,7 +1121,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
|
||||
&& "invalid class not first");
|
||||
OS << " {DBGFIELD(\"InvalidSchedClass\") "
|
||||
<< MCSchedClassDesc::InvalidNumMicroOps
|
||||
<< ", 0, 0, 0, 0, 0, 0, 0, 0},\n";
|
||||
<< ", false, false, 0, 0, 0, 0, 0, 0},\n";
|
||||
|
||||
for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
|
||||
MCSchedClassDesc &MCDesc = SCTab[SCIdx];
|
||||
@ -1123,7 +1130,8 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
|
||||
if (SchedClass.Name.size() < 18)
|
||||
OS.indent(18 - SchedClass.Name.size());
|
||||
OS << MCDesc.NumMicroOps
|
||||
<< ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
|
||||
<< ", " << ( MCDesc.BeginGroup ? "true" : "false" )
|
||||
<< ", " << ( MCDesc.EndGroup ? "true" : "false" )
|
||||
<< ", " << format("%2d", MCDesc.WriteProcResIdx)
|
||||
<< ", " << MCDesc.NumWriteProcResEntries
|
||||
<< ", " << format("%2d", MCDesc.WriteLatencyIdx)
|
||||
@ -1158,13 +1166,17 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
|
||||
EmitProcessorProp(OS, PM.ModelDef, "HighLatency", ',');
|
||||
EmitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ',');
|
||||
|
||||
OS << " " << (bool)(PM.ModelDef ?
|
||||
PM.ModelDef->getValueAsBit("PostRAScheduler") : 0)
|
||||
<< ", // " << "PostRAScheduler\n";
|
||||
bool PostRAScheduler =
|
||||
(PM.ModelDef ? PM.ModelDef->getValueAsBit("PostRAScheduler") : false);
|
||||
|
||||
OS << " " << (bool)(PM.ModelDef ?
|
||||
PM.ModelDef->getValueAsBit("CompleteModel") : 0)
|
||||
<< ", // " << "CompleteModel\n";
|
||||
OS << " " << (PostRAScheduler ? "true" : "false") << ", // "
|
||||
<< "PostRAScheduler\n";
|
||||
|
||||
bool CompleteModel =
|
||||
(PM.ModelDef ? PM.ModelDef->getValueAsBit("CompleteModel") : false);
|
||||
|
||||
OS << " " << (CompleteModel ? "true" : "false") << ", // "
|
||||
<< "CompleteModel\n";
|
||||
|
||||
OS << " " << PM.Index << ", // Processor ID\n";
|
||||
if (PM.hasInstrSchedModel())
|
||||
@ -1376,15 +1388,15 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
|
||||
|
||||
OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_ENUM\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
|
||||
|
||||
OS << "namespace llvm {\n";
|
||||
Enumeration(OS);
|
||||
OS << "} // end llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
|
||||
|
||||
OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
|
||||
|
||||
OS << "namespace llvm {\n";
|
||||
#if 0
|
||||
@ -1397,7 +1409,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
EmitSchedModel(OS);
|
||||
OS << "\n";
|
||||
#if 0
|
||||
OS << "}\n";
|
||||
OS << "} // end anonymous namespace\n\n";
|
||||
#endif
|
||||
|
||||
// MCInstrInfo initialization routine.
|
||||
@ -1427,22 +1439,22 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
OS << "0, 0, 0";
|
||||
OS << ");\n}\n\n";
|
||||
|
||||
OS << "} // end llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
|
||||
OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
|
||||
|
||||
OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n";
|
||||
|
||||
OS << "#include \"llvm/Support/Debug.h\"\n";
|
||||
OS << "#include \"llvm/Support/raw_ostream.h\"\n";
|
||||
OS << "#include \"llvm/Support/raw_ostream.h\"\n\n";
|
||||
ParseFeaturesFunction(OS, NumFeatures, NumProcs);
|
||||
|
||||
OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
|
||||
|
||||
// Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
|
||||
OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_HEADER\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_HEADER\n\n";
|
||||
|
||||
std::string ClassName = Target + "GenSubtargetInfo";
|
||||
OS << "namespace llvm {\n";
|
||||
@ -1457,14 +1469,14 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
<< " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
|
||||
<< " const;\n"
|
||||
<< "};\n";
|
||||
OS << "} // end llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
|
||||
OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
|
||||
|
||||
OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_CTOR\n";
|
||||
OS << "#undef GET_SUBTARGETINFO_CTOR\n\n";
|
||||
|
||||
OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
|
||||
OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n";
|
||||
OS << "namespace llvm {\n";
|
||||
OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
|
||||
OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
|
||||
@ -1509,7 +1521,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
|
||||
|
||||
EmitSchedModelHelpers(ClassName, OS);
|
||||
|
||||
OS << "} // end llvm namespace\n";
|
||||
OS << "} // end namespace llvm\n\n";
|
||||
|
||||
OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
|
||||
}
|
||||
@ -1521,4 +1533,4 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
|
||||
SubtargetEmitter(RK, CGTarget).run(OS);
|
||||
}
|
||||
|
||||
} // end llvm namespace
|
||||
} // end namespace llvm
|
||||
|
Loading…
x
Reference in New Issue
Block a user