aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/utils/TableGen
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
downloadsrc-cfca06d7963fa0909f90483b42a6d7d194d01e08.tar.gz
src-cfca06d7963fa0909f90483b42a6d7d194d01e08.zip
Vendor import of llvm-project master 2e10b7a39b9, the last commit beforevendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9vendor/llvm-project/master
the llvmorg-12-init tag, from which release/11.x was branched.
Notes
Notes: svn path=/vendor/llvm-project/master/; revision=363578 svn path=/vendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9/; revision=363579; tag=vendor/llvm-project/llvmorg-11-init-20887-g2e10b7a39b9
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/AsmMatcherEmitter.cpp41
-rw-r--r--llvm/utils/TableGen/AsmWriterEmitter.cpp123
-rw-r--r--llvm/utils/TableGen/AsmWriterInst.cpp6
-rw-r--r--llvm/utils/TableGen/AsmWriterInst.h10
-rw-r--r--llvm/utils/TableGen/Attributes.cpp124
-rw-r--r--llvm/utils/TableGen/CallingConvEmitter.cpp15
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp4
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp45
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.h7
-rw-r--r--llvm/utils/TableGen/CodeGenHwModes.cpp2
-rw-r--r--llvm/utils/TableGen/CodeGenHwModes.h1
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.cpp62
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.h1
-rw-r--r--llvm/utils/TableGen/CodeGenIntrinsics.h27
-rw-r--r--llvm/utils/TableGen/CodeGenMapTable.cpp2
-rw-r--r--llvm/utils/TableGen/CodeGenRegisters.cpp68
-rw-r--r--llvm/utils/TableGen/CodeGenRegisters.h17
-rw-r--r--llvm/utils/TableGen/CodeGenSchedule.cpp40
-rw-r--r--llvm/utils/TableGen/CodeGenSchedule.h2
-rw-r--r--llvm/utils/TableGen/CodeGenTarget.cpp70
-rw-r--r--llvm/utils/TableGen/DAGISelMatcherEmitter.cpp35
-rw-r--r--llvm/utils/TableGen/DAGISelMatcherGen.cpp30
-rw-r--r--llvm/utils/TableGen/DFAEmitter.cpp21
-rw-r--r--llvm/utils/TableGen/DFAEmitter.h10
-rw-r--r--llvm/utils/TableGen/DFAPacketizerEmitter.cpp17
-rw-r--r--llvm/utils/TableGen/DirectiveEmitter.cpp524
-rw-r--r--llvm/utils/TableGen/DisassemblerEmitter.cpp8
-rw-r--r--llvm/utils/TableGen/ExegesisEmitter.cpp2
-rw-r--r--llvm/utils/TableGen/FastISelEmitter.cpp28
-rw-r--r--llvm/utils/TableGen/FixedLenDecoderEmitter.cpp101
-rw-r--r--llvm/utils/TableGen/GICombinerEmitter.cpp124
-rw-r--r--llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp29
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp250
-rw-r--r--llvm/utils/TableGen/InstrDocsEmitter.cpp2
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.cpp108
-rw-r--r--llvm/utils/TableGen/IntrinsicEmitter.cpp70
-rw-r--r--llvm/utils/TableGen/OptParserEmitter.cpp269
-rw-r--r--llvm/utils/TableGen/OptRSTEmitter.cpp1
-rw-r--r--llvm/utils/TableGen/RISCVCompressInstEmitter.cpp87
-rw-r--r--llvm/utils/TableGen/RegisterBankEmitter.cpp31
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.cpp42
-rw-r--r--llvm/utils/TableGen/SearchableTableEmitter.cpp39
-rw-r--r--llvm/utils/TableGen/SequenceToOffsetTable.h100
-rw-r--r--llvm/utils/TableGen/SubtargetEmitter.cpp13
-rw-r--r--llvm/utils/TableGen/SubtargetFeatureInfo.cpp54
-rw-r--r--llvm/utils/TableGen/TableGen.cpp26
-rw-r--r--llvm/utils/TableGen/TableGenBackends.h3
-rw-r--r--llvm/utils/TableGen/X86DisassemblerTables.cpp33
-rw-r--r--llvm/utils/TableGen/X86ModRMFilters.cpp2
-rw-r--r--llvm/utils/TableGen/X86ModRMFilters.h23
-rw-r--r--llvm/utils/TableGen/X86RecognizableInstr.cpp50
-rw-r--r--llvm/utils/TableGen/X86RecognizableInstr.h38
52 files changed, 2139 insertions, 698 deletions
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index ccf0959389ba..3d63059dcb8b 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1085,7 +1085,7 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool IsAlias) const {
// Verify that any operand is only mentioned once.
// We reject aliases and ignore instructions for now.
if (!IsAlias && TheDef->getValueAsString("AsmMatchConverter").empty() &&
- Tok[0] == '$' && !OperandNames.insert(Tok).second) {
+ Tok[0] == '$' && !OperandNames.insert(std::string(Tok)).second) {
LLVM_DEBUG({
errs() << "warning: '" << TheDef->getName() << "': "
<< "ignoring instruction with tied operand '"
@@ -1126,7 +1126,7 @@ static std::string getEnumNameForToken(StringRef Str) {
}
ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
- ClassInfo *&Entry = TokenClasses[Token];
+ ClassInfo *&Entry = TokenClasses[std::string(Token)];
if (!Entry) {
Classes.emplace_front();
@@ -1134,7 +1134,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
Entry->Kind = ClassInfo::Token;
Entry->ClassName = "Token";
Entry->Name = "MCK_" + getEnumNameForToken(Token);
- Entry->ValueName = Token;
+ Entry->ValueName = std::string(Token);
Entry->PredicateMethod = "<invalid>";
Entry->RenderMethod = "<invalid>";
Entry->ParserMethod = "";
@@ -1310,11 +1310,11 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
Init *DiagnosticType = Def->getValueInit("DiagnosticType");
if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))
- CI->DiagnosticType = SI->getValue();
+ CI->DiagnosticType = std::string(SI->getValue());
Init *DiagnosticString = Def->getValueInit("DiagnosticString");
if (StringInit *SI = dyn_cast<StringInit>(DiagnosticString))
- CI->DiagnosticString = SI->getValue();
+ CI->DiagnosticString = std::string(SI->getValue());
// If we have a diagnostic string but the diagnostic type is not specified
// explicitly, create an anonymous diagnostic type.
@@ -1335,9 +1335,9 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
assert(CI && "Missing singleton register class info!");
if (CI->ValueName.empty()) {
- CI->ClassName = Rec->getName();
+ CI->ClassName = std::string(Rec->getName());
CI->Name = "MCK_" + Rec->getName().str();
- CI->ValueName = Rec->getName();
+ CI->ValueName = std::string(Rec->getName());
} else
CI->ValueName = CI->ValueName + "," + Rec->getName().str();
}
@@ -1372,14 +1372,14 @@ void AsmMatcherInfo::buildOperandClasses() {
else
CI->SuperClasses.push_back(SC);
}
- CI->ClassName = Rec->getValueAsString("Name");
+ CI->ClassName = std::string(Rec->getValueAsString("Name"));
CI->Name = "MCK_" + CI->ClassName;
- CI->ValueName = Rec->getName();
+ CI->ValueName = std::string(Rec->getName());
// Get or construct the predicate method name.
Init *PMName = Rec->getValueInit("PredicateMethod");
if (StringInit *SI = dyn_cast<StringInit>(PMName)) {
- CI->PredicateMethod = SI->getValue();
+ CI->PredicateMethod = std::string(SI->getValue());
} else {
assert(isa<UnsetInit>(PMName) && "Unexpected PredicateMethod field!");
CI->PredicateMethod = "is" + CI->ClassName;
@@ -1388,7 +1388,7 @@ void AsmMatcherInfo::buildOperandClasses() {
// Get or construct the render method name.
Init *RMName = Rec->getValueInit("RenderMethod");
if (StringInit *SI = dyn_cast<StringInit>(RMName)) {
- CI->RenderMethod = SI->getValue();
+ CI->RenderMethod = std::string(SI->getValue());
} else {
assert(isa<UnsetInit>(RMName) && "Unexpected RenderMethod field!");
CI->RenderMethod = "add" + CI->ClassName + "Operands";
@@ -1397,15 +1397,15 @@ void AsmMatcherInfo::buildOperandClasses() {
// Get the parse method name or leave it as empty.
Init *PRMName = Rec->getValueInit("ParserMethod");
if (StringInit *SI = dyn_cast<StringInit>(PRMName))
- CI->ParserMethod = SI->getValue();
+ CI->ParserMethod = std::string(SI->getValue());
// Get the diagnostic type and string or leave them as empty.
Init *DiagnosticType = Rec->getValueInit("DiagnosticType");
if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))
- CI->DiagnosticType = SI->getValue();
+ CI->DiagnosticType = std::string(SI->getValue());
Init *DiagnosticString = Rec->getValueInit("DiagnosticString");
if (StringInit *SI = dyn_cast<StringInit>(DiagnosticString))
- CI->DiagnosticString = SI->getValue();
+ CI->DiagnosticString = std::string(SI->getValue());
// If we have a DiagnosticString, we need a DiagnosticType for use within
// the matcher.
if (!CI->DiagnosticString.empty() && CI->DiagnosticType.empty())
@@ -1418,7 +1418,7 @@ void AsmMatcherInfo::buildOperandClasses() {
// Get or construct the default method name.
Init *DMName = Rec->getValueInit("DefaultMethod");
if (StringInit *SI = dyn_cast<StringInit>(DMName)) {
- CI->DefaultMethod = SI->getValue();
+ CI->DefaultMethod = std::string(SI->getValue());
} else {
assert(isa<UnsetInit>(DMName) && "Unexpected DefaultMethod field!");
CI->DefaultMethod = "default" + CI->ClassName + "Operands";
@@ -2601,7 +2601,7 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
if (Reg.TheDef->getValueAsString("AsmName").empty())
continue;
- Matches.emplace_back(Reg.TheDef->getValueAsString("AsmName"),
+ Matches.emplace_back(std::string(Reg.TheDef->getValueAsString("AsmName")),
"return " + utostr(Reg.EnumValue) + ";");
}
@@ -2633,7 +2633,7 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
if (AltName.empty())
continue;
- Matches.emplace_back(AltName,
+ Matches.emplace_back(std::string(AltName),
"return " + utostr(Reg.EnumValue) + ";");
}
}
@@ -2729,7 +2729,8 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
StringRef AsmVariantName = R->getValueAsString("AsmVariantName");
if (AsmVariantName != AsmParserVariantName)
continue;
- AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R);
+ AliasesFromMnemonic[std::string(R->getValueAsString("FromMnemonic"))]
+ .push_back(R);
}
if (AliasesFromMnemonic.empty())
return;
@@ -3001,7 +3002,7 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
AsmMatcherInfo &Info,
raw_ostream &OS) {
std::string AsmParserName =
- Info.AsmParser->getValueAsString("AsmParserClassName");
+ std::string(Info.AsmParser->getValueAsString("AsmParserClassName"));
OS << "static bool ";
OS << "checkAsmTiedOperandConstraints(const " << Target.getName()
<< AsmParserName << "&AsmParser,\n";
@@ -3862,7 +3863,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " std::string Info;\n";
OS << " if (!getParser().getTargetParser().\n";
OS << " getTargetOptions().MCNoDeprecatedWarn &&\n";
- OS << " MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
+ OS << " MII.getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
OS << " SMLoc Loc = ((" << Target.getName()
<< "Operand&)*Operands[0]).getStartLoc();\n";
OS << " getParser().Warning(Loc, Info, None);\n";
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 58c0d32d44eb..d10ea71e97e3 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -185,7 +185,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
InstIdxs[idx].push_back(i);
} else {
UniqueOperandCommands.push_back(std::move(Command));
- InstrsForCase.push_back(Inst.CGI->TheDef->getName());
+ InstrsForCase.push_back(std::string(Inst.CGI->TheDef->getName()));
InstIdxs.emplace_back();
InstIdxs.back().push_back(i);
@@ -267,6 +267,27 @@ static void UnescapeString(std::string &Str) {
}
}
+/// UnescapeAliasString - Supports literal braces in InstAlias asm string which
+/// are escaped with '\\' to avoid being interpreted as variants. Braces must
+/// be unescaped before c++ code is generated as (e.g.):
+///
+/// AsmString = "foo \{$\x01\}";
+///
+/// causes non-standard escape character warnings.
+static void UnescapeAliasString(std::string &Str) {
+ for (unsigned i = 0; i != Str.size(); ++i) {
+ if (Str[i] == '\\' && i != Str.size()-1) {
+ switch (Str[i+1]) {
+ default: continue; // Don't execute the code after the switch.
+ case '{': Str[i] = '{'; break;
+ case '}': Str[i] = '}'; break;
+ }
+ // Nuke the second character.
+ Str.erase(Str.begin()+i+1);
+ }
+ }
+}
+
/// EmitPrintInstruction - Generate the code for the "printInstruction" method
/// implementation. Destroys all instances of AsmWriterInst information, by
/// clearing the Instructions vector.
@@ -380,9 +401,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Emit the string table itself.
- O << " static const char AsmStrs[] = {\n";
- StringTable.emit(O, printChar);
- O << " };\n\n";
+ StringTable.emitStringLiteralDef(O, " static const char AsmStrs[]");
// Emit the lookup tables in pieces to minimize wasted bytes.
unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
@@ -509,9 +528,9 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
// "NoRegAltName" is special. We don't need to do a lookup for that,
// as it's just a reference to the default register name.
if (AltName == "" || AltName == "NoRegAltName") {
- AsmName = Reg.TheDef->getValueAsString("AsmName");
+ AsmName = std::string(Reg.TheDef->getValueAsString("AsmName"));
if (AsmName.empty())
- AsmName = Reg.getName();
+ AsmName = std::string(Reg.getName());
} else {
// Make sure the register has an alternate name for this index.
std::vector<Record*> AltNameList =
@@ -530,16 +549,15 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
PrintFatalError(Reg.TheDef->getLoc(),
"Register definition missing alt name for '" +
AltName + "'.");
- AsmName = AltNames[Idx];
+ AsmName = std::string(AltNames[Idx]);
}
}
StringTable.add(AsmName);
}
StringTable.layout();
- O << " static const char AsmStrs" << AltName << "[] = {\n";
- StringTable.emit(O, printChar);
- O << " };\n\n";
+ StringTable.emitStringLiteralDef(O, Twine(" static const char AsmStrs") +
+ AltName + "[]");
O << " static const " << getMinimalTypeForRange(StringTable.size() - 1, 32)
<< " RegAsmOffset" << AltName << "[] = {";
@@ -786,7 +804,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// before it can be matched to the mnemonic.
std::map<std::string, std::vector<IAPrinter>> IAPrinterMap;
- std::vector<std::string> PrintMethods;
+ std::vector<std::pair<std::string, bool>> PrintMethods;
// A list of MCOperandPredicates for all operands in use, and the reverse map
std::vector<const Record*> MCOpPredicates;
@@ -806,6 +824,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
std::string FlatAliasAsmString =
CodeGenInstruction::FlattenAsmStringVariants(CGA.AsmString, Variant);
+ UnescapeAliasString(FlatAliasAsmString);
// Don't emit the alias if it has more operands than what it's aliasing.
if (NumResultOps < CountNumOperands(FlatAliasAsmString, Variant))
@@ -858,11 +877,16 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (Rec->isSubClassOf("RegisterOperand") ||
Rec->isSubClassOf("Operand")) {
StringRef PrintMethod = Rec->getValueAsString("PrintMethod");
+ bool IsPCRel =
+ Rec->getValueAsString("OperandType") == "OPERAND_PCREL";
if (PrintMethod != "" && PrintMethod != "printOperand") {
- PrintMethodIdx =
- llvm::find(PrintMethods, PrintMethod) - PrintMethods.begin();
+ PrintMethodIdx = llvm::find_if(PrintMethods,
+ [&](auto &X) {
+ return X.first == PrintMethod;
+ }) -
+ PrintMethods.begin();
if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
- PrintMethods.push_back(PrintMethod);
+ PrintMethods.emplace_back(std::string(PrintMethod), IsPCRel);
}
}
@@ -874,12 +898,12 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Record *R = CGA.ResultOperands[i].getRecord();
if (R->isSubClassOf("RegisterOperand"))
R = R->getValueAsDef("RegClass");
- IAP.addCond(formatv(
- "AliasPatternCond::K_RegClass, {0}::{1}RegClassID", Namespace,
- R->getName()));
+ IAP.addCond(std::string(
+ formatv("AliasPatternCond::K_RegClass, {0}::{1}RegClassID",
+ Namespace, R->getName())));
} else {
- IAP.addCond(formatv("AliasPatternCond::K_TiedReg, {0}",
- IAP.getOpIndex(ROName)));
+ IAP.addCond(std::string(formatv(
+ "AliasPatternCond::K_TiedReg, {0}", IAP.getOpIndex(ROName))));
}
} else {
// Assume all printable operands are desired for now. This can be
@@ -896,7 +920,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
} else
break; // No conditions on this operand at all
}
- IAP.addCond(formatv("AliasPatternCond::K_Custom, {0}", Entry));
+ IAP.addCond(
+ std::string(formatv("AliasPatternCond::K_Custom, {0}", Entry)));
}
break;
}
@@ -908,7 +933,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (Imm != Imm32)
PrintFatalError("Matching an alias with an immediate out of the "
"range of int32_t is not supported");
- IAP.addCond(formatv("AliasPatternCond::K_Imm, uint32_t({0})", Imm32));
+ IAP.addCond(std::string(
+ formatv("AliasPatternCond::K_Imm, uint32_t({0})", Imm32)));
break;
}
case CodeGenInstAlias::ResultOperand::K_Reg:
@@ -920,8 +946,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
}
StringRef Reg = CGA.ResultOperands[i].getRegister()->getName();
- IAP.addCond(
- formatv("AliasPatternCond::K_Reg, {0}::{1}", Namespace, Reg));
+ IAP.addCond(std::string(
+ formatv("AliasPatternCond::K_Reg, {0}::{1}", Namespace, Reg)));
break;
}
@@ -942,20 +968,35 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (auto I = ReqFeatures.cbegin(); I != ReqFeatures.cend(); I++) {
Record *R = *I;
- StringRef AsmCondString = R->getValueAsString("AssemblerCondString");
-
- // AsmCondString has syntax [!]F(,[!]F)*
- SmallVector<StringRef, 4> Ops;
- SplitString(AsmCondString, Ops, ",");
- assert(!Ops.empty() && "AssemblerCondString cannot be empty");
-
- for (StringRef Op : Ops) {
- assert(!Op.empty() && "Empty operator");
- bool IsNeg = Op[0] == '!';
- StringRef Feature = Op.drop_front(IsNeg ? 1 : 0);
- IAP.addCond(formatv("AliasPatternCond::K_{0}Feature, {1}::{2}",
- IsNeg ? "Neg" : "", Namespace, Feature));
+ const DagInit *D = R->getValueAsDag("AssemblerCondDag");
+ std::string CombineType = D->getOperator()->getAsString();
+ if (CombineType != "any_of" && CombineType != "all_of")
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ if (D->getNumArgs() == 0)
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ bool IsOr = CombineType == "any_of";
+
+ for (auto *Arg : D->getArgs()) {
+ bool IsNeg = false;
+ if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
+ if (NotArg->getOperator()->getAsString() != "not" ||
+ NotArg->getNumArgs() != 1)
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ Arg = NotArg->getArg(0);
+ IsNeg = true;
+ }
+ if (!isa<DefInit>(Arg) ||
+ !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+
+ IAP.addCond(std::string(formatv(
+ "AliasPatternCond::K_{0}{1}Feature, {2}::{3}", IsOr ? "Or" : "",
+ IsNeg ? "Neg" : "", Namespace, Arg->getAsString())));
}
+ // If an AssemblerPredicate with ors is used, note end of list should
+ // these be combined.
+ if (IsOr)
+ IAP.addCond("AliasPatternCond::K_EndOrFeatures, 0");
}
IAPrinterMap[Aliases.first].push_back(std::move(IAP));
@@ -971,7 +1012,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
HeaderO << "bool " << Target.getName() << ClassName
<< "::printAliasInstr(const MCInst"
- << " *MI, " << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
+ << " *MI, uint64_t Address, "
+ << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
<< "raw_ostream &OS) {\n";
std::string PatternsForOpcode;
@@ -1134,7 +1176,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << " ++I;\n";
O << " int OpIdx = AsmString[I++] - 1;\n";
O << " int PrintMethodIdx = AsmString[I++] - 1;\n";
- O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, ";
+ O << " printCustomAliasOperand(MI, Address, OpIdx, PrintMethodIdx, ";
O << (PassSubtarget ? "STI, " : "");
O << "OS);\n";
O << " } else\n";
@@ -1156,7 +1198,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << "void " << Target.getName() << ClassName << "::"
<< "printCustomAliasOperand(\n"
- << " const MCInst *MI, unsigned OpIdx,\n"
+ << " const MCInst *MI, uint64_t Address, unsigned OpIdx,\n"
<< " unsigned PrintMethodIdx,\n"
<< (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "")
<< " raw_ostream &OS) {\n";
@@ -1170,7 +1212,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (unsigned i = 0; i < PrintMethods.size(); ++i) {
O << " case " << i << ":\n"
- << " " << PrintMethods[i] << "(MI, OpIdx, "
+ << " " << PrintMethods[i].first << "(MI, "
+ << (PrintMethods[i].second ? "Address, " : "") << "OpIdx, "
<< (PassSubtarget ? "STI, " : "") << "OS);\n"
<< " break;\n";
}
diff --git a/llvm/utils/TableGen/AsmWriterInst.cpp b/llvm/utils/TableGen/AsmWriterInst.cpp
index c26e0e421183..24d29ffc28e5 100644
--- a/llvm/utils/TableGen/AsmWriterInst.cpp
+++ b/llvm/utils/TableGen/AsmWriterInst.cpp
@@ -36,6 +36,8 @@ std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
return Str;
std::string Result = Str + "(MI";
+ if (PCRel)
+ Result += ", Address";
if (MIOpNo != ~0U)
Result += ", " + utostr(MIOpNo);
if (PassSubtarget)
@@ -179,7 +181,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo];
unsigned MIOp = OpInfo.MIOperandNo;
- Operands.emplace_back(OpInfo.PrinterMethodName, MIOp, Modifier);
+ Operands.emplace_back(OpInfo.PrinterMethodName, MIOp, Modifier,
+ AsmWriterOperand::isMachineInstrOperand,
+ OpInfo.OperandType == "MCOI::OPERAND_PCREL");
}
LastEmitted = VarEnd;
}
diff --git a/llvm/utils/TableGen/AsmWriterInst.h b/llvm/utils/TableGen/AsmWriterInst.h
index a59112efea44..366c9eca664f 100644
--- a/llvm/utils/TableGen/AsmWriterInst.h
+++ b/llvm/utils/TableGen/AsmWriterInst.h
@@ -48,6 +48,8 @@ namespace llvm {
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
+ bool PCRel = false;
+
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
@@ -55,11 +57,11 @@ namespace llvm {
OpType op = isLiteralTextOperand)
: OperandType(op), Str(LitStr) {}
- AsmWriterOperand(const std::string &Printer,
- unsigned _MIOpNo,
+ AsmWriterOperand(const std::string &Printer, unsigned _MIOpNo,
const std::string &Modifier,
- OpType op = isMachineInstrOperand)
- : OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier) {}
+ OpType op = isMachineInstrOperand, bool PCRel = false)
+ : OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier),
+ PCRel(PCRel) {}
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
diff --git a/llvm/utils/TableGen/Attributes.cpp b/llvm/utils/TableGen/Attributes.cpp
index 6fbc595d7300..f3f875e8ce0b 100644
--- a/llvm/utils/TableGen/Attributes.cpp
+++ b/llvm/utils/TableGen/Attributes.cpp
@@ -23,51 +23,41 @@ public:
void emit(raw_ostream &OS);
private:
- void emitTargetIndependentEnums(raw_ostream &OS);
- void emitConversionFn(raw_ostream &OS);
+ void emitTargetIndependentNames(raw_ostream &OS);
void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
- void printEnumAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records);
- void printStrBoolAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records);
-
RecordKeeper &Records;
};
} // End anonymous namespace.
-void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
- OS << "#ifdef GET_ATTR_ENUM\n";
- OS << "#undef GET_ATTR_ENUM\n";
-
- std::vector<Record*> Attrs =
- Records.getAllDerivedDefinitions("EnumAttr");
-
- for (auto A : Attrs)
- OS << A->getName() << ",\n";
-
- OS << "#endif\n";
-}
-
-void Attributes::emitConversionFn(raw_ostream &OS) {
- OS << "#ifdef GET_ATTR_KIND_FROM_NAME\n";
- OS << "#undef GET_ATTR_KIND_FROM_NAME\n";
-
- std::vector<Record*> Attrs =
- Records.getAllDerivedDefinitions("EnumAttr");
-
- OS << "static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {\n";
- OS << " return StringSwitch<Attribute::AttrKind>(AttrName)\n";
-
- for (auto A : Attrs) {
- OS << " .Case(\"" << A->getValueAsString("AttrString");
- OS << "\", Attribute::" << A->getName() << ")\n";
- }
-
- OS << " .Default(Attribute::None);\n";
- OS << "}\n\n";
-
+void Attributes::emitTargetIndependentNames(raw_ostream &OS) {
+ OS << "#ifdef GET_ATTR_NAMES\n";
+ OS << "#undef GET_ATTR_NAMES\n";
+
+ OS << "#ifndef ATTRIBUTE_ALL\n";
+ OS << "#define ATTRIBUTE_ALL(FIRST, SECOND)\n";
+ OS << "#endif\n\n";
+
+ auto Emit = [&](ArrayRef<StringRef> KindNames, StringRef MacroName) {
+ OS << "#ifndef " << MacroName << "\n";
+ OS << "#define " << MacroName
+ << "(FIRST, SECOND) ATTRIBUTE_ALL(FIRST, SECOND)\n";
+ OS << "#endif\n\n";
+ for (StringRef KindName : KindNames) {
+ for (auto A : Records.getAllDerivedDefinitions(KindName)) {
+ OS << MacroName << "(" << A->getName() << ","
+ << A->getValueAsString("AttrString") << ")\n";
+ }
+ }
+ OS << "#undef " << MacroName << "\n\n";
+ };
+
+ // Emit attribute enums in the same order llvm::Attribute::operator< expects.
+ Emit({"EnumAttr", "TypeAttr", "IntAttr"}, "ATTRIBUTE_ENUM");
+ Emit({"StrBoolAttr"}, "ATTRIBUTE_STRBOOL");
+
+ OS << "#undef ATTRIBUTE_ALL\n";
OS << "#endif\n";
}
@@ -75,35 +65,6 @@ void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
OS << "#undef GET_ATTR_COMPAT_FUNC\n";
- OS << "struct EnumAttr {\n";
- OS << " static bool isSet(const Function &Fn,\n";
- OS << " Attribute::AttrKind Kind) {\n";
- OS << " return Fn.hasFnAttribute(Kind);\n";
- OS << " }\n\n";
- OS << " static void set(Function &Fn,\n";
- OS << " Attribute::AttrKind Kind, bool Val) {\n";
- OS << " if (Val)\n";
- OS << " Fn.addFnAttr(Kind);\n";
- OS << " else\n";
- OS << " Fn.removeFnAttr(Kind);\n";
- OS << " }\n";
- OS << "};\n\n";
-
- OS << "struct StrBoolAttr {\n";
- OS << " static bool isSet(const Function &Fn,\n";
- OS << " StringRef Kind) {\n";
- OS << " auto A = Fn.getFnAttribute(Kind);\n";
- OS << " return A.getValueAsString().equals(\"true\");\n";
- OS << " }\n\n";
- OS << " static void set(Function &Fn,\n";
- OS << " StringRef Kind, bool Val) {\n";
- OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
- OS << " }\n";
- OS << "};\n\n";
-
- printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
- printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
-
OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
<< " const Function &Callee) {\n";
OS << " bool Ret = true;\n\n";
@@ -135,35 +96,8 @@ void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
OS << "#endif\n";
}
-void Attributes::printEnumAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records) {
- OS << "// EnumAttr classes\n";
- for (const auto *R : Records) {
- OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
- OS << " static enum Attribute::AttrKind getKind() {\n";
- OS << " return llvm::Attribute::" << R->getName() << ";\n";
- OS << " }\n";
- OS << "};\n";
- }
- OS << "\n";
-}
-
-void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records) {
- OS << "// StrBoolAttr classes\n";
- for (const auto *R : Records) {
- OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
- OS << " static StringRef getKind() {\n";
- OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
- OS << " }\n";
- OS << "};\n";
- }
- OS << "\n";
-}
-
void Attributes::emit(raw_ostream &OS) {
- emitTargetIndependentEnums(OS);
- emitConversionFn(OS);
+ emitTargetIndependentNames(OS);
emitFnAttrCompatCheck(OS, false);
}
diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp
index 9eabb44d9004..a4e993f80ec9 100644
--- a/llvm/utils/TableGen/CallingConvEmitter.cpp
+++ b/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -197,11 +197,12 @@ void CallingConvEmitter::EmitAction(Record *Action,
"getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
" ";
if (Align)
- O << Align;
+ O << "Align(" << Align << ")";
else
- O << "\n" << IndentStr
+ O << "\n"
+ << IndentStr
<< " State.getMachineFunction().getDataLayout()."
- "getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
+ "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
"))";
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
@@ -224,8 +225,7 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << "\n" << IndentStr << "};\n";
O << IndentStr << "unsigned Offset" << ++Counter
- << " = State.AllocateStack("
- << Size << ", " << Align << ", "
+ << " = State.AllocateStack(" << Size << ", Align(" << Align << "), "
<< "ShadowRegList" << ShadowRegListNumber << ");\n";
O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
@@ -275,9 +275,8 @@ void CallingConvEmitter::EmitAction(Record *Action,
} else if (Action->isSubClassOf("CCPassByVal")) {
int Size = Action->getValueAsInt("Size");
int Align = Action->getValueAsInt("Align");
- O << IndentStr
- << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
- << Size << ", " << Align << ", ArgFlags);\n";
+ O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
+ << Size << ", Align(" << Align << "), ArgFlags);\n";
O << IndentStr << "return false;\n";
} else if (Action->isSubClassOf("CCCustom")) {
O << IndentStr
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp
index 68cb8f181e62..6338d44fb2a7 100644
--- a/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -313,8 +313,8 @@ std::string CodeEmitterGen::getInstructionCaseForEncoding(Record *R, Record *Enc
// bits<5> RST = { ?, ?, ?, ?, ? };
if (RV.getPrefix() || RV.getValue()->isComplete())
continue;
-
- AddCodeToMergeInOperand(R, BI, RV.getName(), NumberedOp,
+
+ AddCodeToMergeInOperand(R, BI, std::string(RV.getName()), NumberedOp,
NamedOpIndices, Case, Target);
}
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 7e0ba98da94a..6fdc116721f3 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -277,7 +277,7 @@ bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) {
// Compute the intersection of scalars separately to account for only
// one set containing iPTR.
- // The itersection of iPTR with a set of integer scalar types that does not
+ // The intersection of iPTR with a set of integer scalar types that does not
// include iPTR will result in the most specific scalar type:
// - iPTR is more specific than any set with two elements or more
// - iPTR is less specific than any single integer scalar type.
@@ -999,9 +999,9 @@ std::string TreePredicateFn::getPredCode() const {
int64_t MinAlign = getMinAlignment();
if (MinAlign > 0) {
- Code += "if (cast<MemSDNode>(N)->getAlignment() < ";
+ Code += "if (cast<MemSDNode>(N)->getAlign() < Align(";
Code += utostr(MinAlign);
- Code += ")\nreturn false;\n";
+ Code += "))\nreturn false;\n";
}
Record *MemoryVT = getMemoryVT();
@@ -1091,7 +1091,8 @@ std::string TreePredicateFn::getPredCode() const {
.str();
}
- std::string PredicateCode = PatFragRec->getRecord()->getValueAsString("PredicateCode");
+ std::string PredicateCode =
+ std::string(PatFragRec->getRecord()->getValueAsString("PredicateCode"));
Code += PredicateCode;
@@ -1106,7 +1107,8 @@ bool TreePredicateFn::hasImmCode() const {
}
std::string TreePredicateFn::getImmCode() const {
- return PatFragRec->getRecord()->getValueAsString("ImmediateCode");
+ return std::string(
+ PatFragRec->getRecord()->getValueAsString("ImmediateCode"));
}
bool TreePredicateFn::immCodeUsesAPInt() const {
@@ -1223,7 +1225,8 @@ bool TreePredicateFn::hasGISelPredicateCode() const {
.empty();
}
std::string TreePredicateFn::getGISelPredicateCode() const {
- return PatFragRec->getRecord()->getValueAsString("GISelPredicateCode");
+ return std::string(
+ PatFragRec->getRecord()->getValueAsString("GISelPredicateCode"));
}
StringRef TreePredicateFn::getImmType() const {
@@ -2517,6 +2520,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
}
}
+ unsigned NumResults = Inst.getNumResults();
+ unsigned NumFixedOperands = InstInfo.Operands.size();
+
// If one or more operands with a default value appear at the end of the
// formal operand list for an instruction, we allow them to be overridden
// by optional operands provided in the pattern.
@@ -2525,14 +2531,15 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
// operand A with a default, then we don't allow A to be overridden,
// because there would be no way to specify whether the next operand in
// the pattern was intended to override A or skip it.
- unsigned NonOverridableOperands = Inst.getNumOperands();
- while (NonOverridableOperands > 0 &&
- CDP.operandHasDefault(Inst.getOperand(NonOverridableOperands-1)))
+ unsigned NonOverridableOperands = NumFixedOperands;
+ while (NonOverridableOperands > NumResults &&
+ CDP.operandHasDefault(InstInfo.Operands[NonOverridableOperands-1].Rec))
--NonOverridableOperands;
unsigned ChildNo = 0;
- for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
- Record *OperandNode = Inst.getOperand(i);
+ assert(NumResults <= NumFixedOperands);
+ for (unsigned i = NumResults, e = NumFixedOperands; i != e; ++i) {
+ Record *OperandNode = InstInfo.Operands[i].Rec;
// If the operand has a default value, do we use it? We must use the
// default if we've run out of children of the pattern DAG to consume,
@@ -2741,7 +2748,7 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
if (R->getName() == "node" && !OpName.empty()) {
if (OpName.empty())
error("'node' argument requires a name to match with operand list");
- Args.push_back(OpName);
+ Args.push_back(std::string(OpName));
}
Res->setName(OpName);
@@ -2753,7 +2760,7 @@ TreePatternNodePtr TreePattern::ParseTreePattern(Init *TheInit,
if (OpName.empty())
error("'?' argument requires a name to match with operand list");
TreePatternNodePtr Res = std::make_shared<TreePatternNode>(TheInit, 1);
- Args.push_back(OpName);
+ Args.push_back(std::string(OpName));
Res->setName(OpName);
return Res;
}
@@ -2915,8 +2922,15 @@ static bool SimplifyTree(TreePatternNodePtr &N) {
// If we have a bitconvert with a resolved type and if the source and
// destination types are the same, then the bitconvert is useless, remove it.
+ //
+ // We make an exception if the types are completely empty. This can come up
+ // when the pattern being simplified is in the Fragments list of a PatFrags,
+ // so that the operand is just an untyped "node". In that situation we leave
+ // bitconverts unsimplified, and simplify them later once the fragment is
+ // expanded into its true context.
if (N->getOperator()->getName() == "bitconvert" &&
N->getExtType(0).isValueTypeByHwMode(false) &&
+ !N->getExtType(0).empty() &&
N->getExtType(0) == N->getChild(0)->getExtType(0) &&
N->getName().empty()) {
N = N->getChildShared(0);
@@ -3105,7 +3119,8 @@ void CodeGenDAGPatterns::ParseNodeTransforms() {
Record *XFormNode = Xforms.back();
Record *SDNode = XFormNode->getValueAsDef("Opcode");
StringRef Code = XFormNode->getValueAsString("XFormFunction");
- SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code)));
+ SDNodeXForms.insert(
+ std::make_pair(XFormNode, NodeXForm(SDNode, std::string(Code))));
Xforms.pop_back();
}
@@ -3173,7 +3188,7 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
P->error("'" + ArgNameStr +
"' does not occur in pattern or was multiply specified!");
OperandsSet.erase(ArgNameStr);
- Args.push_back(ArgNameStr);
+ Args.push_back(std::string(ArgNameStr));
}
if (!OperandsSet.empty())
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.h b/llvm/utils/TableGen/CodeGenDAGPatterns.h
index 2c081b670609..a3b84d76fde9 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.h
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -430,7 +430,7 @@ class ScopedName {
std::string Identifier;
public:
ScopedName(unsigned Scope, StringRef Identifier)
- : Scope(Scope), Identifier(Identifier) {
+ : Scope(Scope), Identifier(std::string(Identifier)) {
assert(Scope != 0 &&
"Scope == 0 is used to indicate predicates without arguments");
}
@@ -1075,8 +1075,9 @@ public:
// The string will excute in a subclass of SelectionDAGISel.
// Cast to std::string explicitly to avoid ambiguity with StringRef.
std::string C = IsHwMode
- ? std::string("MF->getSubtarget().checkFeatures(\"" + Features + "\")")
- : std::string(Def->getValueAsString("CondString"));
+ ? std::string("MF->getSubtarget().checkFeatures(\"" +
+ Features + "\")")
+ : std::string(Def->getValueAsString("CondString"));
if (C.empty())
return "";
return IfCond ? C : "!("+C+')';
diff --git a/llvm/utils/TableGen/CodeGenHwModes.cpp b/llvm/utils/TableGen/CodeGenHwModes.cpp
index 9052cdd2bd3e..2fec46c44100 100644
--- a/llvm/utils/TableGen/CodeGenHwModes.cpp
+++ b/llvm/utils/TableGen/CodeGenHwModes.cpp
@@ -20,7 +20,7 @@ StringRef CodeGenHwModes::DefaultModeName = "DefaultMode";
HwMode::HwMode(Record *R) {
Name = R->getName();
- Features = R->getValueAsString("Features");
+ Features = std::string(R->getValueAsString("Features"));
}
LLVM_DUMP_METHOD
diff --git a/llvm/utils/TableGen/CodeGenHwModes.h b/llvm/utils/TableGen/CodeGenHwModes.h
index 1ff2faaa0e52..55507cbca37d 100644
--- a/llvm/utils/TableGen/CodeGenHwModes.h
+++ b/llvm/utils/TableGen/CodeGenHwModes.h
@@ -12,6 +12,7 @@
#define LLVM_UTILS_TABLEGEN_CODEGENHWMODES_H
#include "llvm/ADT/StringMap.h"
+#include <cassert>
#include <map>
#include <string>
#include <vector>
diff --git a/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index 6bb4dbb511b6..1df5902b081e 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -56,6 +56,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
std::set<std::string> OperandNames;
unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
OperandList.reserve(e);
+ bool VariadicOuts = false;
for (unsigned i = 0; i != e; ++i){
Init *ArgInit;
StringRef ArgName;
@@ -80,16 +81,16 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
unsigned NumOps = 1;
DagInit *MIOpInfo = nullptr;
if (Rec->isSubClassOf("RegisterOperand")) {
- PrintMethod = Rec->getValueAsString("PrintMethod");
- OperandType = Rec->getValueAsString("OperandType");
- OperandNamespace = Rec->getValueAsString("OperandNamespace");
- EncoderMethod = Rec->getValueAsString("EncoderMethod");
+ PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
+ OperandType = std::string(Rec->getValueAsString("OperandType"));
+ OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
+ EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod"));
} else if (Rec->isSubClassOf("Operand")) {
- PrintMethod = Rec->getValueAsString("PrintMethod");
- OperandType = Rec->getValueAsString("OperandType");
- OperandNamespace = Rec->getValueAsString("OperandNamespace");
+ PrintMethod = std::string(Rec->getValueAsString("PrintMethod"));
+ OperandType = std::string(Rec->getValueAsString("OperandType"));
+ OperandNamespace = std::string(Rec->getValueAsString("OperandNamespace"));
// If there is an explicit encoder method, use it.
- EncoderMethod = Rec->getValueAsString("EncoderMethod");
+ EncoderMethod = std::string(Rec->getValueAsString("EncoderMethod"));
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
// Verify that MIOpInfo has an 'ops' root value.
@@ -109,6 +110,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
else if (Rec->isSubClassOf("OptionalDefOperand"))
hasOptionalDef = true;
} else if (Rec->getName() == "variable_ops") {
+ if (i < NumDefs)
+ VariadicOuts = true;
isVariadic = true;
continue;
} else if (Rec->isSubClassOf("RegisterClass")) {
@@ -124,18 +127,21 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
PrintFatalError(R->getLoc(), "In instruction '" + R->getName() +
"', operand #" + Twine(i) +
" has no name!");
- if (!OperandNames.insert(ArgName).second)
+ if (!OperandNames.insert(std::string(ArgName)).second)
PrintFatalError(R->getLoc(),
"In instruction '" + R->getName() + "', operand #" +
Twine(i) +
" has the same name as a previous operand!");
- OperandList.emplace_back(Rec, ArgName, PrintMethod, EncoderMethod,
- OperandNamespace + "::" + OperandType, MIOperandNo,
- NumOps, MIOpInfo);
+ OperandList.emplace_back(
+ Rec, std::string(ArgName), std::string(PrintMethod),
+ std::string(EncoderMethod), OperandNamespace + "::" + OperandType,
+ MIOperandNo, NumOps, MIOpInfo);
MIOperandNo += NumOps;
}
+ if (VariadicOuts)
+ --NumDefs;
// Make sure the constraints list for each operand is large enough to hold
// constraint info, even if none is present.
@@ -265,7 +271,8 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
PrintFatalError(
Rec->getLoc(), "Illegal format for tied-to constraint in '" +
Rec->getName() + "': '" + CStr + "'");
- std::string LHSOpName = StringRef(CStr).substr(start, wpos - start);
+ std::string LHSOpName =
+ std::string(StringRef(CStr).substr(start, wpos - start));
std::pair<unsigned,unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false);
wpos = CStr.find_first_not_of(" \t", pos + 1);
@@ -273,7 +280,7 @@ static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
PrintFatalError(
Rec->getLoc(), "Illegal format for tied-to constraint: '" + CStr + "'");
- std::string RHSOpName = StringRef(CStr).substr(wpos);
+ std::string RHSOpName = std::string(StringRef(CStr).substr(wpos));
std::pair<unsigned,unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false);
// Sort the operands into order, which should put the output one
@@ -339,8 +346,8 @@ static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops,
void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
while (1) {
std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
- std::string OpName = P.first;
- DisableEncoding = P.second;
+ std::string OpName = std::string(P.first);
+ DisableEncoding = std::string(P.second);
if (OpName.empty()) break;
// Figure out which operand this is.
@@ -361,7 +368,7 @@ void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
CodeGenInstruction::CodeGenInstruction(Record *R)
: TheDef(R), Operands(R), InferredFrom(nullptr) {
Namespace = R->getValueAsString("Namespace");
- AsmString = R->getValueAsString("AsmString");
+ AsmString = std::string(R->getValueAsString("AsmString"));
isPreISelOpcode = R->getValueAsBit("isPreISelOpcode");
isReturn = R->getValueAsBit("isReturn");
@@ -420,15 +427,18 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
hasChain_Inferred = false;
// Parse Constraints.
- ParseConstraints(R->getValueAsString("Constraints"), Operands, R);
+ ParseConstraints(std::string(R->getValueAsString("Constraints")), Operands,
+ R);
// Parse the DisableEncoding field.
- Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
+ Operands.ProcessDisableEncoding(
+ std::string(R->getValueAsString("DisableEncoding")));
// First check for a ComplexDeprecationPredicate.
if (R->getValue("ComplexDeprecationPredicate")) {
HasComplexDeprecationPredicate = true;
- DeprecatedReason = R->getValueAsString("ComplexDeprecationPredicate");
+ DeprecatedReason =
+ std::string(R->getValueAsString("ComplexDeprecationPredicate"));
} else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) {
// Check if we have a Subtarget feature mask.
HasComplexDeprecationPredicate = false;
@@ -541,7 +551,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (!Result->getArgName(AliasOpNo))
PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
" must have a name!");
- ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
+ ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
+ ResultRecord);
return true;
}
@@ -559,7 +570,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
if (!T.getRegisterClass(InstOpRec)
.hasSubClass(&T.getRegisterClass(ADI->getDef())))
return false;
- ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
+ ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
+ ResultRecord);
return true;
}
@@ -641,7 +653,8 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
// MIOperandInfo perhaps?
if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
return false;
- ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ADI->getDef());
+ ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
+ ADI->getDef());
return true;
}
@@ -668,8 +681,7 @@ unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T)
: TheDef(R) {
Result = R->getValueAsDag("ResultInst");
- AsmString = R->getValueAsString("AsmString");
-
+ AsmString = std::string(R->getValueAsString("AsmString"));
// Verify that the root of the result is an instruction.
DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
diff --git a/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h
index 1f08ce481a89..af851a11676b 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/llvm/utils/TableGen/CodeGenInstruction.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MachineValueType.h"
#include "llvm/Support/SMLoc.h"
+#include <cassert>
#include <string>
#include <utility>
#include <vector>
diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/CodeGenIntrinsics.h
index 723bbe0cc23d..af59c1f3d833 100644
--- a/llvm/utils/TableGen/CodeGenIntrinsics.h
+++ b/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -123,6 +123,12 @@ struct CodeGenIntrinsic {
/// True if the intrinsic is no-return.
bool isNoReturn;
+ /// True if the intrinsic is no-sync.
+ bool isNoSync;
+
+ /// True if the intrinsic is no-free.
+ bool isNoFree;
+
/// True if the intrinsic is will-return.
bool isWillReturn;
@@ -139,17 +145,32 @@ struct CodeGenIntrinsic {
// True if the intrinsic is marked as speculatable.
bool isSpeculatable;
- enum ArgAttribute {
+ enum ArgAttrKind {
NoCapture,
NoAlias,
Returned,
ReadOnly,
WriteOnly,
ReadNone,
- ImmArg
+ ImmArg,
+ Alignment
+ };
+
+ struct ArgAttribute {
+ unsigned Index;
+ ArgAttrKind Kind;
+ uint64_t Value;
+
+ ArgAttribute(unsigned Idx, ArgAttrKind K, uint64_t V)
+ : Index(Idx), Kind(K), Value(V) {}
+
+ bool operator<(const ArgAttribute &Other) const {
+ return std::tie(Index, Kind, Value) <
+ std::tie(Other.Index, Other.Kind, Other.Value);
+ }
};
- std::vector<std::pair<unsigned, ArgAttribute>> ArgumentAttributes;
+ std::vector<ArgAttribute> ArgumentAttributes;
bool hasProperty(enum SDNP Prop) const {
return Properties & (1 << Prop);
diff --git a/llvm/utils/TableGen/CodeGenMapTable.cpp b/llvm/utils/TableGen/CodeGenMapTable.cpp
index 793bb61481e7..baca0768b26b 100644
--- a/llvm/utils/TableGen/CodeGenMapTable.cpp
+++ b/llvm/utils/TableGen/CodeGenMapTable.cpp
@@ -98,7 +98,7 @@ private:
public:
InstrMap(Record* MapRec) {
- Name = MapRec->getName();
+ Name = std::string(MapRec->getName());
// FilterClass - It's used to reduce the search space only to the
// instructions that define the kind of relationship modeled by
diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp
index 6153c759b123..4584bc7cfae3 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -52,18 +52,18 @@ using namespace llvm;
CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
: TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
- Name = R->getName();
+ Name = std::string(R->getName());
if (R->getValue("Namespace"))
- Namespace = R->getValueAsString("Namespace");
+ Namespace = std::string(R->getValueAsString("Namespace"));
Size = R->getValueAsInt("Size");
Offset = R->getValueAsInt("Offset");
}
CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
unsigned Enum)
- : TheDef(nullptr), Name(N), Namespace(Nspace), Size(-1), Offset(-1),
- EnumValue(Enum), AllSuperRegsCovered(true), Artificial(true) {
-}
+ : TheDef(nullptr), Name(std::string(N)), Namespace(std::string(Nspace)),
+ Size(-1), Offset(-1), EnumValue(Enum), AllSuperRegsCovered(true),
+ Artificial(true) {}
std::string CodeGenSubRegIndex::getQualifiedName() const {
std::string N = getNamespace();
@@ -739,11 +739,9 @@ static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
}
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
- : TheDef(R),
- Name(R->getName()),
- TopoSigs(RegBank.getNumTopoSigs()),
- EnumValue(-1) {
-
+ : TheDef(R), Name(std::string(R->getName())),
+ TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1) {
+ GeneratePressureSet = R->getValueAsBit("GeneratePressureSet");
std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
Record *Type = TypeList[i];
@@ -816,16 +814,11 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
// class structure has been computed.
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
StringRef Name, Key Props)
- : Members(*Props.Members),
- TheDef(nullptr),
- Name(Name),
- TopoSigs(RegBank.getNumTopoSigs()),
- EnumValue(-1),
- RSI(Props.RSI),
- CopyCost(0),
- Allocatable(true),
- AllocationPriority(0) {
+ : Members(*Props.Members), TheDef(nullptr), Name(std::string(Name)),
+ TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), RSI(Props.RSI),
+ CopyCost(0), Allocatable(true), AllocationPriority(0) {
Artificial = true;
+ GeneratePressureSet = false;
for (const auto R : Members) {
TopoSigs.set(R->getTopoSig());
Artificial &= R->Artificial;
@@ -848,6 +841,7 @@ void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
Allocatable = Super.Allocatable;
AltOrderSelect = Super.AltOrderSelect;
AllocationPriority = Super.AllocationPriority;
+ GeneratePressureSet |= Super.GeneratePressureSet;
// Copy all allocation orders, filter out foreign registers from the larger
// super-class.
@@ -863,6 +857,16 @@ bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
deref<std::less<>>());
}
+unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank& RegBank) const {
+ if (TheDef && !TheDef->isValueUnset("Weight"))
+ return TheDef->getValueAsInt("Weight");
+
+ if (Members.empty() || Artificial)
+ return 0;
+
+ return (*Members.begin())->getWeight(RegBank);
+}
+
namespace llvm {
raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
@@ -990,8 +994,12 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
Optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>>
CodeGenRegisterClass::getMatchingSubClassWithSubRegs(
CodeGenRegBank &RegBank, const CodeGenSubRegIndex *SubIdx) const {
- auto SizeOrder = [](const CodeGenRegisterClass *A,
+ auto SizeOrder = [this](const CodeGenRegisterClass *A,
const CodeGenRegisterClass *B) {
+ // If there are multiple, identical register classes, prefer the original
+ // register class.
+ if (A->getMembers().size() == B->getMembers().size())
+ return A == this;
return A->getMembers().size() > B->getMembers().size();
};
@@ -1007,8 +1015,10 @@ CodeGenRegisterClass::getMatchingSubClassWithSubRegs(
for (auto &RC : RegClasses)
if (SuperRegRCsBV[RC.EnumValue])
SuperRegRCs.emplace_back(&RC);
- llvm::sort(SuperRegRCs, SizeOrder);
- assert(SuperRegRCs.front() == BiggestSuperRegRC && "Biggest class wasn't first");
+ llvm::stable_sort(SuperRegRCs, SizeOrder);
+
+ assert(SuperRegRCs.front() == BiggestSuperRegRC &&
+ "Biggest class wasn't first");
// Find all the subreg classes and order them by size too.
std::vector<std::pair<CodeGenRegisterClass *, BitVector>> SuperRegClasses;
@@ -1223,6 +1233,12 @@ CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
return Idx;
}
+const CodeGenSubRegIndex *
+CodeGenRegBank::findSubRegIdx(const Record* Def) const {
+ auto I = Def2SubRegIdx.find(Def);
+ return (I == Def2SubRegIdx.end()) ? nullptr : I->second;
+}
+
CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
CodeGenRegister *&Reg = Def2Reg[Def];
if (Reg)
@@ -1259,8 +1275,8 @@ CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
return &RegClasses.back();
}
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
- if (CodeGenRegisterClass *RC = Def2RC[Def])
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def) const {
+ if (CodeGenRegisterClass *RC = Def2RC.lookup(Def))
return RC;
PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
@@ -1879,7 +1895,7 @@ void CodeGenRegBank::computeRegUnitSets() {
// Compute a unique RegUnitSet for each RegClass.
auto &RegClasses = getRegClasses();
for (auto &RC : RegClasses) {
- if (!RC.Allocatable || RC.Artificial)
+ if (!RC.Allocatable || RC.Artificial || !RC.GeneratePressureSet)
continue;
// Speculatively grow the RegUnitSets to hold the new set.
@@ -1940,7 +1956,7 @@ void CodeGenRegBank::computeRegUnitSets() {
// Speculatively grow the RegUnitSets to hold the new set.
RegUnitSets.resize(RegUnitSets.size() + 1);
RegUnitSets.back().Name =
- RegUnitSets[Idx].Name + "+" + RegUnitSets[SearchIdx].Name;
+ RegUnitSets[Idx].Name + "_with_" + RegUnitSets[SearchIdx].Name;
std::set_union(RegUnitSets[Idx].Units.begin(),
RegUnitSets[Idx].Units.end(),
diff --git a/llvm/utils/TableGen/CodeGenRegisters.h b/llvm/utils/TableGen/CodeGenRegisters.h
index a8e9e0fbccbe..2b200adef312 100644
--- a/llvm/utils/TableGen/CodeGenRegisters.h
+++ b/llvm/utils/TableGen/CodeGenRegisters.h
@@ -86,6 +86,7 @@ namespace llvm {
CodeGenSubRegIndex(Record *R, unsigned Enum);
CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
+ CodeGenSubRegIndex(CodeGenSubRegIndex&) = delete;
const std::string &getName() const { return Name; }
const std::string &getNamespace() const { return Namespace; }
@@ -338,6 +339,9 @@ namespace llvm {
bool CoveredBySubRegs;
/// A register class is artificial if all its members are artificial.
bool Artificial;
+ /// Generate register pressure set for this register class and any class
+ /// synthesized from it.
+ bool GeneratePressureSet;
// Return the Record that defined this class, or NULL if the class was
// created by TableGen.
@@ -437,11 +441,15 @@ namespace llvm {
// Get a bit vector of TopoSigs present in this register class.
const BitVector &getTopoSigs() const { return TopoSigs; }
+ // Get a weight of this register class.
+ unsigned getWeight(const CodeGenRegBank&) const;
+
// Populate a unique sorted list of units from a register set.
void buildRegUnitSet(const CodeGenRegBank &RegBank,
std::vector<unsigned> &RegUnits) const;
CodeGenRegisterClass(CodeGenRegBank&, Record *R);
+ CodeGenRegisterClass(CodeGenRegisterClass&) = delete;
// A key representing the parts of a register class used for forming
// sub-classes. Note the ordering provided by this key is not the same as
@@ -611,6 +619,7 @@ namespace llvm {
public:
CodeGenRegBank(RecordKeeper&, const CodeGenHwModes&);
+ CodeGenRegBank(CodeGenRegBank&) = delete;
SetTheory &getSets() { return Sets; }
@@ -623,9 +632,13 @@ namespace llvm {
return SubRegIndices;
}
- // Find a SubRegIndex form its Record def.
+ // Find a SubRegIndex from its Record def or add to the list if it does
+ // not exist there yet.
CodeGenSubRegIndex *getSubRegIdx(Record*);
+ // Find a SubRegIndex from its Record def.
+ const CodeGenSubRegIndex *findSubRegIdx(const Record* Def) const;
+
// Find or create a sub-register index representing the A+B composition.
CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A,
CodeGenSubRegIndex *B);
@@ -706,7 +719,7 @@ namespace llvm {
}
// Find a register class from its def.
- CodeGenRegisterClass *getRegClass(Record*);
+ CodeGenRegisterClass *getRegClass(const Record *) const;
/// getRegisterClassForRegister - Find the register class that contains the
/// specified physical register. If the register is not in a register
diff --git a/llvm/utils/TableGen/CodeGenSchedule.cpp b/llvm/utils/TableGen/CodeGenSchedule.cpp
index f12d7d484a8e..67583c736cd2 100644
--- a/llvm/utils/TableGen/CodeGenSchedule.cpp
+++ b/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -106,7 +106,7 @@ struct InstRegexOp : public SetTheory::Operator {
StringRef PatStr = Original.substr(FirstMeta);
if (!PatStr.empty()) {
// For the rest use a python-style prefix match.
- std::string pat = PatStr;
+ std::string pat = std::string(PatStr);
if (pat[0] != '^') {
pat.insert(0, "^(");
pat.insert(pat.end(), ')');
@@ -546,7 +546,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) {
if (!ProcModelMap.insert(std::make_pair(ModelKey, ProcModels.size())).second)
return;
- std::string Name = ModelKey->getName();
+ std::string Name = std::string(ModelKey->getName());
if (ModelKey->isSubClassOf("SchedMachineModel")) {
Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");
ProcModels.emplace_back(ProcModels.size(), Name, ModelKey, ItinsDef);
@@ -977,7 +977,7 @@ CodeGenSchedModels::createSchedClassName(Record *ItinClassDef,
std::string Name;
if (ItinClassDef && ItinClassDef->getName() != "NoItinerary")
- Name = ItinClassDef->getName();
+ Name = std::string(ItinClassDef->getName());
for (unsigned Idx : OperWrites) {
if (!Name.empty())
Name += '_';
@@ -1082,15 +1082,14 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
for (Record *RWD : RWDefs) {
if (RWD->getValueAsDef("SchedModel") == RWModelDef &&
RWModelDef->getValueAsBit("FullInstRWOverlapCheck")) {
- for (Record *Inst : InstDefs) {
- PrintFatalError
- (InstRWDef->getLoc(),
- "Overlapping InstRW definition for \"" +
- Inst->getName() +
- "\" also matches previous \"" +
- RWD->getValue("Instrs")->getValue()->getAsString() +
- "\".");
- }
+ assert(!InstDefs.empty()); // Checked at function start.
+ PrintFatalError
+ (InstRWDef->getLoc(),
+ "Overlapping InstRW definition for \"" +
+ InstDefs.front()->getName() +
+ "\" also matches previous \"" +
+ RWD->getValue("Instrs")->getValue()->getAsString() +
+ "\".");
}
}
LLVM_DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx << ":"
@@ -1118,15 +1117,14 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel");
for (Record *OldRWDef : SchedClasses[OldSCIdx].InstRWs) {
if (OldRWDef->getValueAsDef("SchedModel") == RWModelDef) {
- for (Record *InstDef : InstDefs) {
- PrintFatalError
- (InstRWDef->getLoc(),
- "Overlapping InstRW definition for \"" +
- InstDef->getName() +
- "\" also matches previous \"" +
- OldRWDef->getValue("Instrs")->getValue()->getAsString() +
- "\".");
- }
+ assert(!InstDefs.empty()); // Checked at function start.
+ PrintFatalError
+ (InstRWDef->getLoc(),
+ "Overlapping InstRW definition for \"" +
+ InstDefs.front()->getName() +
+ "\" also matches previous \"" +
+ OldRWDef->getValue("Instrs")->getValue()->getAsString() +
+ "\".");
}
assert(OldRWDef != InstRWDef &&
"SchedClass has duplicate InstRW def");
diff --git a/llvm/utils/TableGen/CodeGenSchedule.h b/llvm/utils/TableGen/CodeGenSchedule.h
index c26fb1f97807..c487d142d46c 100644
--- a/llvm/utils/TableGen/CodeGenSchedule.h
+++ b/llvm/utils/TableGen/CodeGenSchedule.h
@@ -58,7 +58,7 @@ struct CodeGenSchedRW {
HasVariants(false), IsVariadic(false), IsSequence(false) {}
CodeGenSchedRW(unsigned Idx, Record *Def)
: Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) {
- Name = Def->getName();
+ Name = std::string(Def->getName());
IsRead = Def->isSubClassOf("SchedRead");
HasVariants = Def->isSubClassOf("SchedVariant");
if (HasVariants)
diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp
index acfb143120af..891a08ea590e 100644
--- a/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -69,6 +69,7 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::fAny: return "MVT::fAny";
case MVT::vAny: return "MVT::vAny";
case MVT::f16: return "MVT::f16";
+ case MVT::bf16: return "MVT::bf16";
case MVT::f32: return "MVT::f32";
case MVT::f64: return "MVT::f64";
case MVT::f80: return "MVT::f80";
@@ -132,6 +133,16 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v8f16: return "MVT::v8f16";
case MVT::v16f16: return "MVT::v16f16";
case MVT::v32f16: return "MVT::v32f16";
+ case MVT::v64f16: return "MVT::v64f16";
+ case MVT::v128f16: return "MVT::v128f16";
+ case MVT::v2bf16: return "MVT::v2bf16";
+ case MVT::v3bf16: return "MVT::v3bf16";
+ case MVT::v4bf16: return "MVT::v4bf16";
+ case MVT::v8bf16: return "MVT::v8bf16";
+ case MVT::v16bf16: return "MVT::v16bf16";
+ case MVT::v32bf16: return "MVT::v32bf16";
+ case MVT::v64bf16: return "MVT::v64bf16";
+ case MVT::v128bf16: return "MVT::v128bf16";
case MVT::v1f32: return "MVT::v1f32";
case MVT::v2f32: return "MVT::v2f32";
case MVT::v3f32: return "MVT::v3f32";
@@ -150,18 +161,22 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v2f64: return "MVT::v2f64";
case MVT::v4f64: return "MVT::v4f64";
case MVT::v8f64: return "MVT::v8f64";
+ case MVT::v16f64: return "MVT::v16f64";
+ case MVT::v32f64: return "MVT::v32f64";
case MVT::nxv1i1: return "MVT::nxv1i1";
case MVT::nxv2i1: return "MVT::nxv2i1";
case MVT::nxv4i1: return "MVT::nxv4i1";
case MVT::nxv8i1: return "MVT::nxv8i1";
case MVT::nxv16i1: return "MVT::nxv16i1";
case MVT::nxv32i1: return "MVT::nxv32i1";
+ case MVT::nxv64i1: return "MVT::nxv64i1";
case MVT::nxv1i8: return "MVT::nxv1i8";
case MVT::nxv2i8: return "MVT::nxv2i8";
case MVT::nxv4i8: return "MVT::nxv4i8";
case MVT::nxv8i8: return "MVT::nxv8i8";
case MVT::nxv16i8: return "MVT::nxv16i8";
case MVT::nxv32i8: return "MVT::nxv32i8";
+ case MVT::nxv64i8: return "MVT::nxv64i8";
case MVT::nxv1i16: return "MVT::nxv1i16";
case MVT::nxv2i16: return "MVT::nxv2i16";
case MVT::nxv4i16: return "MVT::nxv4i16";
@@ -173,14 +188,22 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::nxv4i32: return "MVT::nxv4i32";
case MVT::nxv8i32: return "MVT::nxv8i32";
case MVT::nxv16i32: return "MVT::nxv16i32";
+ case MVT::nxv32i32: return "MVT::nxv32i32";
case MVT::nxv1i64: return "MVT::nxv1i64";
case MVT::nxv2i64: return "MVT::nxv2i64";
case MVT::nxv4i64: return "MVT::nxv4i64";
case MVT::nxv8i64: return "MVT::nxv8i64";
case MVT::nxv16i64: return "MVT::nxv16i64";
+ case MVT::nxv32i64: return "MVT::nxv32i64";
+ case MVT::nxv1f16: return "MVT::nxv1f16";
case MVT::nxv2f16: return "MVT::nxv2f16";
case MVT::nxv4f16: return "MVT::nxv4f16";
case MVT::nxv8f16: return "MVT::nxv8f16";
+ case MVT::nxv16f16: return "MVT::nxv16f16";
+ case MVT::nxv32f16: return "MVT::nxv32f16";
+ case MVT::nxv2bf16: return "MVT::nxv2bf16";
+ case MVT::nxv4bf16: return "MVT::nxv4bf16";
+ case MVT::nxv8bf16: return "MVT::nxv8bf16";
case MVT::nxv1f32: return "MVT::nxv1f32";
case MVT::nxv2f32: return "MVT::nxv2f32";
case MVT::nxv4f32: return "MVT::nxv4f32";
@@ -206,8 +229,9 @@ StringRef llvm::getEnumName(MVT::SimpleValueType T) {
std::string llvm::getQualifiedName(const Record *R) {
std::string Namespace;
if (R->getValue("Namespace"))
- Namespace = R->getValueAsString("Namespace");
- if (Namespace.empty()) return R->getName();
+ Namespace = std::string(R->getValueAsString("Namespace"));
+ if (Namespace.empty())
+ return std::string(R->getName());
return Namespace + "::" + R->getName().str();
}
@@ -526,7 +550,7 @@ bool CodeGenTarget::guessInstructionProperties() const {
ComplexPattern::ComplexPattern(Record *R) {
Ty = ::getValueType(R->getValueAsDef("Ty"));
NumOperands = R->getValueAsInt("NumOperands");
- SelectFunc = R->getValueAsString("SelectFunc");
+ SelectFunc = std::string(R->getValueAsString("SelectFunc"));
RootNodes = R->getValueAsListOfDefs("RootNodes");
// FIXME: This is a hack to statically increase the priority of patterns which
@@ -598,7 +622,7 @@ CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC) {
CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
TheDef = R;
- std::string DefName = R->getName();
+ std::string DefName = std::string(R->getName());
ArrayRef<SMLoc> DefLoc = R->getLoc();
ModRef = ReadWriteMem;
Properties = 0;
@@ -606,6 +630,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isCommutative = false;
canThrow = false;
isNoReturn = false;
+ isNoSync = false;
+ isNoFree = false;
isWillReturn = false;
isCold = false;
isNoDuplicate = false;
@@ -621,12 +647,12 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
EnumName = std::string(DefName.begin()+4, DefName.end());
if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field.
- GCCBuiltinName = R->getValueAsString("GCCBuiltinName");
+ GCCBuiltinName = std::string(R->getValueAsString("GCCBuiltinName"));
if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
- MSBuiltinName = R->getValueAsString("MSBuiltinName");
+ MSBuiltinName = std::string(R->getValueAsString("MSBuiltinName"));
- TargetPrefix = R->getValueAsString("TargetPrefix");
- Name = R->getValueAsString("LLVMName");
+ TargetPrefix = std::string(R->getValueAsString("TargetPrefix"));
+ Name = std::string(R->getValueAsString("LLVMName"));
if (Name == "") {
// If an explicit name isn't specified, derive one from the DefName.
@@ -725,8 +751,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// variants with iAny types; otherwise, if the intrinsic is not
// overloaded, all the types can be specified directly.
assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
- !TyEl->isSubClassOf("LLVMTruncatedType") &&
- !TyEl->isSubClassOf("LLVMScalarOrSameVectorWidth")) ||
+ !TyEl->isSubClassOf("LLVMTruncatedType")) ||
VT == MVT::iAny || VT == MVT::vAny) &&
"Expected iAny or vAny type");
} else
@@ -771,6 +796,10 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isConvergent = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
+ else if (Property->getName() == "IntrNoSync")
+ isNoSync = true;
+ else if (Property->getName() == "IntrNoFree")
+ isNoFree = true;
else if (Property->getName() == "IntrWillReturn")
isWillReturn = true;
else if (Property->getName() == "IntrCold")
@@ -781,25 +810,29 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
hasSideEffects = true;
else if (Property->isSubClassOf("NoCapture")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
+ ArgumentAttributes.emplace_back(ArgNo, NoCapture, 0);
} else if (Property->isSubClassOf("NoAlias")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, NoAlias));
+ ArgumentAttributes.emplace_back(ArgNo, NoAlias, 0);
} else if (Property->isSubClassOf("Returned")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, Returned));
+ ArgumentAttributes.emplace_back(ArgNo, Returned, 0);
} else if (Property->isSubClassOf("ReadOnly")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly));
+ ArgumentAttributes.emplace_back(ArgNo, ReadOnly, 0);
} else if (Property->isSubClassOf("WriteOnly")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, WriteOnly));
+ ArgumentAttributes.emplace_back(ArgNo, WriteOnly, 0);
} else if (Property->isSubClassOf("ReadNone")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
+ ArgumentAttributes.emplace_back(ArgNo, ReadNone, 0);
} else if (Property->isSubClassOf("ImmArg")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
- ArgumentAttributes.push_back(std::make_pair(ArgNo, ImmArg));
+ ArgumentAttributes.emplace_back(ArgNo, ImmArg, 0);
+ } else if (Property->isSubClassOf("Align")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ uint64_t Align = Property->getValueAsInt("Align");
+ ArgumentAttributes.emplace_back(ArgNo, Alignment, Align);
} else
llvm_unreachable("Unknown property!");
}
@@ -819,7 +852,8 @@ bool CodeGenIntrinsic::isParamAPointer(unsigned ParamIdx) const {
}
bool CodeGenIntrinsic::isParamImmArg(unsigned ParamIdx) const {
- std::pair<unsigned, ArgAttribute> Val = {ParamIdx, ImmArg};
+ // Convert argument index to attribute index starting from `FirstArgIndex`.
+ ArgAttribute Val{ParamIdx + 1, ImmArg, 0};
return std::binary_search(ArgumentAttributes.begin(),
ArgumentAttributes.end(), Val);
}
diff --git a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index e9f1fb93d516..d9ec14aab8a8 100644
--- a/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -281,7 +281,7 @@ void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
unsigned MatcherTableEmitter::
EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
raw_ostream &OS) {
- OS.indent(Indent*2);
+ OS.indent(Indent);
switch (N->getKind()) {
case Matcher::Scope: {
@@ -291,6 +291,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
unsigned StartIdx = CurrentIdx;
// Emit all of the children.
+ SmallString<128> TmpBuf;
for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
if (i == 0) {
OS << "OPC_Scope, ";
@@ -298,9 +299,9 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
} else {
if (!OmitComments) {
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
- OS.indent(Indent*2) << "/*Scope*/ ";
+ OS.indent(Indent) << "/*Scope*/ ";
} else
- OS.indent(Indent*2);
+ OS.indent(Indent);
}
// We need to encode the child and the offset of the failure code before
@@ -308,7 +309,6 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
// string while we get the size. Unfortunately, the offset of the
// children depends on the VBR size of the child, so for large children we
// have to iterate a bit.
- SmallString<128> TmpBuf;
unsigned ChildSize = 0;
unsigned VBRSize = 0;
do {
@@ -337,7 +337,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
// Emit a zero as a sentinel indicating end of 'Scope'.
if (!OmitComments)
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
- OS.indent(Indent*2) << "0, ";
+ OS.indent(Indent) << "0, ";
if (!OmitComments)
OS << "/*End of Scope*/";
OS << '\n';
@@ -450,6 +450,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
++CurrentIdx;
// For each case we emit the size, then the opcode, then the matcher.
+ SmallString<128> TmpBuf;
for (unsigned i = 0, e = NumCases; i != e; ++i) {
const Matcher *Child;
unsigned IdxSize;
@@ -466,7 +467,6 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
// string while we get the size. Unfortunately, the offset of the
// children depends on the VBR size of the child, so for large children we
// have to iterate a bit.
- SmallString<128> TmpBuf;
unsigned ChildSize = 0;
unsigned VBRSize = 0;
do {
@@ -483,7 +483,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
if (i != 0) {
if (!OmitComments)
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
- OS.indent(Indent*2);
+ OS.indent(Indent);
if (!OmitComments)
OS << (isa<SwitchOpcodeMatcher>(N) ?
"/*SwitchOpcode*/ " : "/*SwitchType*/ ");
@@ -509,7 +509,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
// Emit the final zero to terminate the switch.
if (!OmitComments)
OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/";
- OS.indent(Indent*2) << "0,";
+ OS.indent(Indent) << "0,";
if (!OmitComments)
OS << (isa<SwitchOpcodeMatcher>(N) ?
" // EndSwitchOpcode" : " // EndSwitchType");
@@ -619,7 +619,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
}
case Matcher::EmitStringInteger: {
const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
- // These should always fit into one byte.
+ // These should always fit into 7 bits.
OS << "OPC_EmitInteger, "
<< getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
<< Val << ",\n";
@@ -712,7 +712,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
unsigned Offset =
getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));
OS << "TARGET_VAL(" << Offset << "),\n";
- OS.indent(FullIndexWidth + Indent * 2);
+ OS.indent(FullIndexWidth + Indent);
}
}
const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
@@ -731,7 +731,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
OS << ",\n";
- OS.indent(FullIndexWidth + Indent*2+4);
+ OS.indent(FullIndexWidth + Indent+4);
if (!CompressVTs) {
OS << EN->getNumVTs();
if (!OmitComments)
@@ -762,10 +762,10 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << '\n';
if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
- OS.indent(FullIndexWidth + Indent*2) << "// Src: "
+ OS.indent(FullIndexWidth + Indent) << "// Src: "
<< *SNT->getPattern().getSrcPattern() << " - Complexity = "
<< SNT->getPattern().getPatternComplexity(CGP) << '\n';
- OS.indent(FullIndexWidth + Indent*2) << "// Dst: "
+ OS.indent(FullIndexWidth + Indent) << "// Dst: "
<< *SNT->getPattern().getDstPattern() << '\n';
}
} else
@@ -789,7 +789,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
unsigned Offset =
getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));
OS << "TARGET_VAL(" << Offset << "),\n";
- OS.indent(FullIndexWidth + Indent * 2);
+ OS.indent(FullIndexWidth + Indent);
}
OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
unsigned NumResultBytes = 0;
@@ -797,10 +797,10 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
OS << '\n';
if (!OmitComments) {
- OS.indent(FullIndexWidth + Indent*2) << " // Src: "
+ OS.indent(FullIndexWidth + Indent) << " // Src: "
<< *CM->getPattern().getSrcPattern() << " - Complexity = "
<< CM->getPattern().getPatternComplexity(CGP) << '\n';
- OS.indent(FullIndexWidth + Indent*2) << " // Dst: "
+ OS.indent(FullIndexWidth + Indent) << " // Dst: "
<< *CM->getPattern().getDstPattern();
}
OS << '\n';
@@ -960,7 +960,8 @@ void MatcherTableEmitter::EmitPredicateFunctions(raw_ostream &OS) {
OS << "// " << NodeXForms[i]->getName();
OS << '\n';
- std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
+ std::string ClassName =
+ std::string(CGP.getSDNodeInfo(SDNode).getSDClassName());
if (ClassName == "SDNode")
OS << " SDNode *N = V.getNode();\n";
else
diff --git a/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index 6a86868a9bcd..123ea3374c74 100644
--- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -311,7 +311,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
// The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is
// "MY_PAT:op1:op2". We should already have validated that the uses are
// consistent.
- std::string PatternName = N->getOperator()->getName();
+ std::string PatternName = std::string(N->getOperator()->getName());
for (unsigned i = 0; i < N->getNumChildren(); ++i) {
PatternName += ":";
PatternName += N->getChild(i)->getName();
@@ -707,14 +707,36 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
if (Def->isSubClassOf("RegisterOperand"))
Def = Def->getValueAsDef("RegClass");
if (Def->isSubClassOf("RegisterClass")) {
- std::string Value = getQualifiedName(Def) + "RegClassID";
- AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
- ResultOps.push_back(NextRecordedOperandNo++);
+ // If the register class has an enum integer value greater than 127, the
+ // encoding overflows the limit of 7 bits, which precludes the use of
+ // StringIntegerMatcher. In this case, fallback to using IntegerMatcher.
+ const CodeGenRegisterClass &RC =
+ CGP.getTargetInfo().getRegisterClass(Def);
+ if (RC.EnumValue <= 127) {
+ std::string Value = getQualifiedName(Def) + "RegClassID";
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ } else {
+ AddMatcher(new EmitIntegerMatcher(RC.EnumValue, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ }
return;
}
// Handle a subregister index. This is used for INSERT_SUBREG etc.
if (Def->isSubClassOf("SubRegIndex")) {
+ const CodeGenRegBank &RB = CGP.getTargetInfo().getRegBank();
+ // If we have more than 127 subreg indices the encoding can overflow
+ // 7 bit and we cannot use StringInteger.
+ if (RB.getSubRegIndices().size() > 127) {
+ const CodeGenSubRegIndex *I = RB.findSubRegIdx(Def);
+ assert(I && "Cannot find subreg index by name!");
+ if (I->EnumValue > 127) {
+ AddMatcher(new EmitIntegerMatcher(I->EnumValue, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
std::string Value = getQualifiedName(Def);
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
ResultOps.push_back(NextRecordedOperandNo++);
diff --git a/llvm/utils/TableGen/DFAEmitter.cpp b/llvm/utils/TableGen/DFAEmitter.cpp
index dd3db7c150ba..7391f6845a4b 100644
--- a/llvm/utils/TableGen/DFAEmitter.cpp
+++ b/llvm/utils/TableGen/DFAEmitter.cpp
@@ -53,14 +53,14 @@ void DfaEmitter::addTransition(state_type From, state_type To, action_type A) {
++NumNfaTransitions;
}
-void DfaEmitter::visitDfaState(DfaState DS) {
+void DfaEmitter::visitDfaState(const DfaState &DS) {
// For every possible action...
auto FromId = DfaStates.idFor(DS);
for (action_type A : Actions) {
DfaState NewStates;
DfaTransitionInfo TI;
// For every represented state, word pair in the original NFA...
- for (state_type &FromState : DS) {
+ for (state_type FromState : DS) {
// If this action is possible from this state add the transitioned-to
// states to NewStates.
auto I = NfaTransitions.find({FromState, A});
@@ -90,8 +90,11 @@ void DfaEmitter::constructDfa() {
// Note that UniqueVector starts indices at 1, not zero.
unsigned DfaStateId = 1;
- while (DfaStateId <= DfaStates.size())
- visitDfaState(DfaStates[DfaStateId++]);
+ while (DfaStateId <= DfaStates.size()) {
+ DfaState S = DfaStates[DfaStateId];
+ visitDfaState(S);
+ DfaStateId++;
+ }
}
void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
@@ -119,7 +122,7 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
for (auto &T : DfaTransitions)
Table.add(T.second.second);
Table.layout();
- OS << "std::array<NfaStatePair, " << Table.size() << "> " << Name
+ OS << "const std::array<NfaStatePair, " << Table.size() << "> " << Name
<< "TransitionInfo = {{\n";
Table.emit(
OS,
@@ -143,8 +146,8 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
OS << "// A table of DFA transitions, ordered by {FromDfaState, Action}.\n";
OS << "// The initial state is 1, not zero.\n";
- OS << "std::array<" << Name << "Transition, " << DfaTransitions.size() << "> "
- << Name << "Transitions = {{\n";
+ OS << "const std::array<" << Name << "Transition, "
+ << DfaTransitions.size() << "> " << Name << "Transitions = {{\n";
for (auto &KV : DfaTransitions) {
dfa_state_type From = KV.first.first;
dfa_state_type To = KV.second.first;
@@ -345,7 +348,7 @@ Transition::Transition(Record *R, Automaton *Parent) {
Types.emplace_back("unsigned");
} else if (isa<StringRecTy>(SymbolV->getType()) ||
isa<CodeRecTy>(SymbolV->getType())) {
- Actions.emplace_back(nullptr, 0, R->getValueAsString(A));
+ Actions.emplace_back(nullptr, 0, std::string(R->getValueAsString(A)));
Types.emplace_back("std::string");
} else {
report_fatal_error("Unhandled symbol type!");
@@ -353,7 +356,7 @@ Transition::Transition(Record *R, Automaton *Parent) {
StringRef TypeOverride = Parent->getActionSymbolType(A);
if (!TypeOverride.empty())
- Types.back() = TypeOverride;
+ Types.back() = std::string(TypeOverride);
}
}
diff --git a/llvm/utils/TableGen/DFAEmitter.h b/llvm/utils/TableGen/DFAEmitter.h
index 76de8f72cd88..44e5d97d544f 100644
--- a/llvm/utils/TableGen/DFAEmitter.h
+++ b/llvm/utils/TableGen/DFAEmitter.h
@@ -17,16 +17,16 @@
#ifndef LLVM_UTILS_TABLEGEN_DFAEMITTER_H
#define LLVM_UTILS_TABLEGEN_DFAEMITTER_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/UniqueVector.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/TableGen/Record.h"
+#include <map>
#include <set>
-#include <unordered_map>
namespace llvm {
class raw_ostream;
+class StringRef;
+
/// Construct a deterministic finite state automaton from possible
/// nondeterministic state and transition data.
///
@@ -99,7 +99,7 @@ private:
void constructDfa();
/// Visit a single DFA state and construct all possible transitions to new DFA
/// states.
- void visitDfaState(DfaState DS);
+ void visitDfaState(const DfaState &DS);
};
} // namespace llvm
diff --git a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
index 018bda1b6090..bc4a084b3224 100644
--- a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -93,7 +93,7 @@ public:
} // end anonymous namespace
DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R)
- : TargetName(CodeGenTarget(R).getName()), Records(R) {}
+ : TargetName(std::string(CodeGenTarget(R).getName())), Records(R) {}
int DFAPacketizerEmitter::collectAllFuncUnits(
ArrayRef<const CodeGenProcModel *> ProcModels) {
@@ -120,7 +120,7 @@ int DFAPacketizerEmitter::collectAllFuncUnits(
assert((j < DFA_MAX_RESOURCES) &&
"Exceeded maximum number of representable resources");
uint64_t FuncResources = 1ULL << j;
- FUNameToBitsMap[FUs[j]->getName()] = FuncResources;
+ FUNameToBitsMap[std::string(FUs[j]->getName())] = FuncResources;
LLVM_DEBUG(dbgs() << " " << FUs[j]->getName() << ":0x"
<< Twine::utohexstr(FuncResources));
}
@@ -152,13 +152,13 @@ int DFAPacketizerEmitter::collectAllComboFuncs(ArrayRef<Record *> ComboFuncList)
Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
const std::vector<Record *> &FuncList =
FuncData->getValueAsListOfDefs("FuncList");
- const std::string &ComboFuncName = ComboFunc->getName();
+ const std::string &ComboFuncName = std::string(ComboFunc->getName());
uint64_t ComboBit = FUNameToBitsMap[ComboFuncName];
uint64_t ComboResources = ComboBit;
LLVM_DEBUG(dbgs() << " combo: " << ComboFuncName << ":0x"
<< Twine::utohexstr(ComboResources) << "\n");
for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
- std::string FuncName = FuncList[k]->getName();
+ std::string FuncName = std::string(FuncList[k]->getName());
uint64_t FuncResources = FUNameToBitsMap[FuncName];
LLVM_DEBUG(dbgs() << " " << FuncName << ":0x"
<< Twine::utohexstr(FuncResources) << "\n");
@@ -181,7 +181,7 @@ DFAPacketizerEmitter::getResourcesForItinerary(Record *Itinerary) {
for (Record *StageDef : Itinerary->getValueAsListOfDefs("Stages")) {
uint64_t StageResources = 0;
for (Record *Unit : StageDef->getValueAsListOfDefs("Units")) {
- StageResources |= FUNameToBitsMap[Unit->getName()];
+ StageResources |= FUNameToBitsMap[std::string(Unit->getName())];
}
if (StageResources != 0)
Resources.push_back(StageResources);
@@ -219,7 +219,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
for (const CodeGenProcModel &ProcModel : CGS.procModels()) {
if (ProcModel.hasItineraries()) {
auto NS = ProcModel.ItinsDef->getValueAsString("PacketizerNamespace");
- ItinsByNamespace[NS].push_back(&ProcModel);
+ ItinsByNamespace[std::string(NS)].push_back(&ProcModel);
}
}
@@ -246,7 +246,8 @@ void DFAPacketizerEmitter::emitForItineraries(
// Output the mapping from ScheduleClass to ResourcesIdx.
unsigned Idx = 0;
- OS << "unsigned " << TargetName << DFAName << "ResourceIndices[] = {";
+ OS << "constexpr unsigned " << TargetName << DFAName
+ << "ResourceIndices[] = {";
for (const ScheduleClass &SC : ScheduleClasses) {
if (Idx++ % 32 == 0)
OS << "\n ";
@@ -255,7 +256,7 @@ void DFAPacketizerEmitter::emitForItineraries(
OS << "\n};\n\n";
// And the mapping from Itinerary index into the previous table.
- OS << "unsigned " << TargetName << DFAName
+ OS << "constexpr unsigned " << TargetName << DFAName
<< "ProcResourceIndexStart[] = {\n";
OS << " 0, // NoSchedModel\n";
for (const CodeGenProcModel *Model : ProcModels) {
diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp
new file mode 100644
index 000000000000..2061ff1fdd1a
--- /dev/null
+++ b/llvm/utils/TableGen/DirectiveEmitter.cpp
@@ -0,0 +1,524 @@
+//===- DirectiveEmitter.cpp - Directive Language Emitter ------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// DirectiveEmitter uses the descriptions of directives and clauses to construct
+// common code declarations to be used in Frontends.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+
+namespace {
+// Simple RAII helper for defining ifdef-undef-endif scopes.
+class IfDefScope {
+public:
+ IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) {
+ OS << "#ifdef " << Name << "\n"
+ << "#undef " << Name << "\n";
+ }
+
+ ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; }
+
+private:
+ StringRef Name;
+ raw_ostream &OS;
+};
+} // end anonymous namespace
+
+namespace llvm {
+
+// Get Directive or Clause name formatted by replacing whitespaces with
+// underscores.
+std::string getFormattedName(StringRef Name) {
+ std::string N = Name.str();
+ std::replace(N.begin(), N.end(), ' ', '_');
+ return N;
+}
+
+// Generate enum class
+void GenerateEnumClass(const std::vector<Record *> &Records, raw_ostream &OS,
+ StringRef Enum, StringRef Prefix, StringRef CppNamespace,
+ bool MakeEnumAvailableInNamespace) {
+ OS << "\n";
+ OS << "enum class " << Enum << " {\n";
+ for (const auto &R : Records) {
+ const auto Name = R->getValueAsString("name");
+ OS << " " << Prefix << getFormattedName(Name) << ",\n";
+ }
+ OS << "};\n";
+ OS << "\n";
+ OS << "static constexpr std::size_t " << Enum
+ << "_enumSize = " << Records.size() << ";\n";
+
+ // Make the enum values available in the defined namespace. This allows us to
+ // write something like Enum_X if we have a `using namespace <CppNamespace>`.
+ // At the same time we do not loose the strong type guarantees of the enum
+ // class, that is we cannot pass an unsigned as Directive without an explicit
+ // cast.
+ if (MakeEnumAvailableInNamespace) {
+ OS << "\n";
+ for (const auto &R : Records) {
+ const auto FormattedName = getFormattedName(R->getValueAsString("name"));
+ OS << "constexpr auto " << Prefix << FormattedName << " = "
+ << "llvm::" << CppNamespace << "::" << Enum << "::" << Prefix
+ << FormattedName << ";\n";
+ }
+ }
+}
+
+// Generate the declaration section for the enumeration in the directive
+// language
+void EmitDirectivesDecl(RecordKeeper &Records, raw_ostream &OS) {
+
+ const auto &DirectiveLanguages =
+ Records.getAllDerivedDefinitions("DirectiveLanguage");
+
+ if (DirectiveLanguages.size() != 1) {
+ PrintError("A single definition of DirectiveLanguage is needed.");
+ return;
+ }
+
+ const auto &DirectiveLanguage = DirectiveLanguages[0];
+ StringRef LanguageName = DirectiveLanguage->getValueAsString("name");
+ StringRef DirectivePrefix =
+ DirectiveLanguage->getValueAsString("directivePrefix");
+ StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix");
+ StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace");
+ bool MakeEnumAvailableInNamespace =
+ DirectiveLanguage->getValueAsBit("makeEnumAvailableInNamespace");
+ bool EnableBitmaskEnumInNamespace =
+ DirectiveLanguage->getValueAsBit("enableBitmaskEnumInNamespace");
+
+ OS << "#ifndef LLVM_" << LanguageName << "_INC\n";
+ OS << "#define LLVM_" << LanguageName << "_INC\n";
+
+ if (EnableBitmaskEnumInNamespace)
+ OS << "\n#include \"llvm/ADT/BitmaskEnum.h\"\n";
+
+ OS << "\n";
+ OS << "namespace llvm {\n";
+ OS << "class StringRef;\n";
+
+ // Open namespaces defined in the directive language
+ llvm::SmallVector<StringRef, 2> Namespaces;
+ llvm::SplitString(CppNamespace, Namespaces, "::");
+ for (auto Ns : Namespaces)
+ OS << "namespace " << Ns << " {\n";
+
+ if (EnableBitmaskEnumInNamespace)
+ OS << "\nLLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();\n";
+
+ // Emit Directive enumeration
+ const auto &Directives = Records.getAllDerivedDefinitions("Directive");
+ GenerateEnumClass(Directives, OS, "Directive", DirectivePrefix, CppNamespace,
+ MakeEnumAvailableInNamespace);
+
+ // Emit Clause enumeration
+ const auto &Clauses = Records.getAllDerivedDefinitions("Clause");
+ GenerateEnumClass(Clauses, OS, "Clause", ClausePrefix, CppNamespace,
+ MakeEnumAvailableInNamespace);
+
+ // Generic function signatures
+ OS << "\n";
+ OS << "// Enumeration helper functions\n";
+ OS << "Directive get" << LanguageName
+ << "DirectiveKind(llvm::StringRef Str);\n";
+ OS << "\n";
+ OS << "llvm::StringRef get" << LanguageName
+ << "DirectiveName(Directive D);\n";
+ OS << "\n";
+ OS << "Clause get" << LanguageName << "ClauseKind(llvm::StringRef Str);\n";
+ OS << "\n";
+ OS << "llvm::StringRef get" << LanguageName << "ClauseName(Clause C);\n";
+ OS << "\n";
+ OS << "/// Return true if \\p C is a valid clause for \\p D in version \\p "
+ << "Version.\n";
+ OS << "bool isAllowedClauseForDirective(Directive D, "
+ << "Clause C, unsigned Version);\n";
+ OS << "\n";
+
+ // Closing namespaces
+ for (auto Ns : llvm::reverse(Namespaces))
+ OS << "} // namespace " << Ns << "\n";
+
+ OS << "} // namespace llvm\n";
+
+ OS << "#endif // LLVM_" << LanguageName << "_INC\n";
+}
+
+// Generate function implementation for get<Enum>Name(StringRef Str)
+void GenerateGetName(const std::vector<Record *> &Records, raw_ostream &OS,
+ StringRef Enum, StringRef Prefix, StringRef LanguageName,
+ StringRef Namespace) {
+ OS << "\n";
+ OS << "llvm::StringRef llvm::" << Namespace << "::get" << LanguageName << Enum
+ << "Name(" << Enum << " Kind) {\n";
+ OS << " switch (Kind) {\n";
+ for (const auto &R : Records) {
+ const auto Name = R->getValueAsString("name");
+ const auto AlternativeName = R->getValueAsString("alternativeName");
+ OS << " case " << Prefix << getFormattedName(Name) << ":\n";
+ OS << " return \"";
+ if (AlternativeName.empty())
+ OS << Name;
+ else
+ OS << AlternativeName;
+ OS << "\";\n";
+ }
+ OS << " }\n"; // switch
+ OS << " llvm_unreachable(\"Invalid " << LanguageName << " " << Enum
+ << " kind\");\n";
+ OS << "}\n";
+}
+
+// Generate function implementation for get<Enum>Kind(StringRef Str)
+void GenerateGetKind(const std::vector<Record *> &Records, raw_ostream &OS,
+ StringRef Enum, StringRef Prefix, StringRef LanguageName,
+ StringRef Namespace, bool ImplicitAsUnknown) {
+
+ auto DefaultIt = std::find_if(Records.begin(), Records.end(), [](Record *R) {
+ return R->getValueAsBit("isDefault") == true;
+ });
+
+ if (DefaultIt == Records.end()) {
+ PrintError("A least one " + Enum + " must be defined as default.");
+ return;
+ }
+
+ const auto FormattedDefaultName =
+ getFormattedName((*DefaultIt)->getValueAsString("name"));
+
+ OS << "\n";
+ OS << Enum << " llvm::" << Namespace << "::get" << LanguageName << Enum
+ << "Kind(llvm::StringRef Str) {\n";
+ OS << " return llvm::StringSwitch<" << Enum << ">(Str)\n";
+
+ for (const auto &R : Records) {
+ const auto Name = R->getValueAsString("name");
+ if (ImplicitAsUnknown && R->getValueAsBit("isImplicit")) {
+ OS << " .Case(\"" << Name << "\"," << Prefix << FormattedDefaultName
+ << ")\n";
+ } else {
+ OS << " .Case(\"" << Name << "\"," << Prefix << getFormattedName(Name)
+ << ")\n";
+ }
+ }
+ OS << " .Default(" << Prefix << FormattedDefaultName << ");\n";
+ OS << "}\n";
+}
+
+void GenerateCaseForVersionedClauses(const std::vector<Record *> &Clauses,
+ raw_ostream &OS, StringRef DirectiveName,
+ StringRef DirectivePrefix,
+ StringRef ClausePrefix,
+ llvm::StringSet<> &Cases) {
+ for (const auto &C : Clauses) {
+ const auto MinVersion = C->getValueAsInt("minVersion");
+ const auto MaxVersion = C->getValueAsInt("maxVersion");
+ const auto SpecificClause = C->getValueAsDef("clause");
+ const auto ClauseName =
+ getFormattedName(SpecificClause->getValueAsString("name"));
+
+ if (Cases.find(ClauseName) == Cases.end()) {
+ Cases.insert(ClauseName);
+ OS << " case " << ClausePrefix << ClauseName << ":\n";
+ OS << " return " << MinVersion << " <= Version && " << MaxVersion
+ << " >= Version;\n";
+ }
+ }
+}
+
+// Generate the isAllowedClauseForDirective function implementation.
+void GenerateIsAllowedClause(const std::vector<Record *> &Directives,
+ raw_ostream &OS, StringRef LanguageName,
+ StringRef DirectivePrefix, StringRef ClausePrefix,
+ StringRef CppNamespace) {
+ OS << "\n";
+ OS << "bool llvm::" << CppNamespace << "::isAllowedClauseForDirective("
+ << "Directive D, Clause C, unsigned Version) {\n";
+ OS << " assert(unsigned(D) <= llvm::" << CppNamespace
+ << "::Directive_enumSize);\n";
+ OS << " assert(unsigned(C) <= llvm::" << CppNamespace
+ << "::Clause_enumSize);\n";
+
+ OS << " switch (D) {\n";
+
+ for (const auto &D : Directives) {
+
+ const auto DirectiveName = D->getValueAsString("name");
+ const auto &AllowedClauses = D->getValueAsListOfDefs("allowedClauses");
+ const auto &AllowedOnceClauses =
+ D->getValueAsListOfDefs("allowedOnceClauses");
+ const auto &AllowedExclusiveClauses =
+ D->getValueAsListOfDefs("allowedExclusiveClauses");
+ const auto &RequiredClauses = D->getValueAsListOfDefs("requiredClauses");
+
+ OS << " case " << DirectivePrefix << getFormattedName(DirectiveName)
+ << ":\n";
+ if (AllowedClauses.size() == 0 && AllowedOnceClauses.size() == 0 &&
+ AllowedExclusiveClauses.size() == 0 && RequiredClauses.size() == 0) {
+ OS << " return false;\n";
+ } else {
+ OS << " switch (C) {\n";
+
+ llvm::StringSet<> Cases;
+
+ GenerateCaseForVersionedClauses(AllowedClauses, OS, DirectiveName,
+ DirectivePrefix, ClausePrefix, Cases);
+
+ GenerateCaseForVersionedClauses(AllowedOnceClauses, OS, DirectiveName,
+ DirectivePrefix, ClausePrefix, Cases);
+
+ GenerateCaseForVersionedClauses(AllowedExclusiveClauses, OS,
+ DirectiveName, DirectivePrefix,
+ ClausePrefix, Cases);
+
+ GenerateCaseForVersionedClauses(RequiredClauses, OS, DirectiveName,
+ DirectivePrefix, ClausePrefix, Cases);
+
+ OS << " default:\n";
+ OS << " return false;\n";
+ OS << " }\n"; // End of clauses switch
+ }
+ OS << " break;\n";
+ }
+
+ OS << " }\n"; // End of directives switch
+ OS << " llvm_unreachable(\"Invalid " << LanguageName
+ << " Directive kind\");\n";
+ OS << "}\n"; // End of function isAllowedClauseForDirective
+}
+
+// Generate a simple enum set with the give clauses.
+void GenerateClauseSet(const std::vector<Record *> &Clauses, raw_ostream &OS,
+ StringRef ClauseEnumSetClass, StringRef ClauseSetPrefix,
+ StringRef DirectiveName, StringRef DirectivePrefix,
+ StringRef ClausePrefix, StringRef CppNamespace) {
+
+ OS << "\n";
+ OS << " static " << ClauseEnumSetClass << " " << ClauseSetPrefix
+ << DirectivePrefix << getFormattedName(DirectiveName) << " {\n";
+
+ for (const auto &C : Clauses) {
+ const auto SpecificClause = C->getValueAsDef("clause");
+ const auto ClauseName = SpecificClause->getValueAsString("name");
+ OS << " llvm::" << CppNamespace << "::Clause::" << ClausePrefix
+ << getFormattedName(ClauseName) << ",\n";
+ }
+ OS << " };\n";
+}
+
+// Generate an enum set for the 4 kinds of clauses linked to a directive.
+void GenerateDirectiveClauseSets(const std::vector<Record *> &Directives,
+ raw_ostream &OS, StringRef LanguageName,
+ StringRef ClauseEnumSetClass,
+ StringRef DirectivePrefix,
+ StringRef ClausePrefix,
+ StringRef CppNamespace) {
+
+ IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS);
+
+ OS << "\n";
+ OS << "namespace llvm {\n";
+
+ // Open namespaces defined in the directive language.
+ llvm::SmallVector<StringRef, 2> Namespaces;
+ llvm::SplitString(CppNamespace, Namespaces, "::");
+ for (auto Ns : Namespaces)
+ OS << "namespace " << Ns << " {\n";
+
+ for (const auto &D : Directives) {
+ const auto DirectiveName = D->getValueAsString("name");
+
+ const auto &AllowedClauses = D->getValueAsListOfDefs("allowedClauses");
+ const auto &AllowedOnceClauses =
+ D->getValueAsListOfDefs("allowedOnceClauses");
+ const auto &AllowedExclusiveClauses =
+ D->getValueAsListOfDefs("allowedExclusiveClauses");
+ const auto &RequiredClauses = D->getValueAsListOfDefs("requiredClauses");
+
+ OS << "\n";
+ OS << " // Sets for " << DirectiveName << "\n";
+
+ GenerateClauseSet(AllowedClauses, OS, ClauseEnumSetClass, "allowedClauses_",
+ DirectiveName, DirectivePrefix, ClausePrefix,
+ CppNamespace);
+ GenerateClauseSet(AllowedOnceClauses, OS, ClauseEnumSetClass,
+ "allowedOnceClauses_", DirectiveName, DirectivePrefix,
+ ClausePrefix, CppNamespace);
+ GenerateClauseSet(AllowedExclusiveClauses, OS, ClauseEnumSetClass,
+ "allowedExclusiveClauses_", DirectiveName,
+ DirectivePrefix, ClausePrefix, CppNamespace);
+ GenerateClauseSet(RequiredClauses, OS, ClauseEnumSetClass,
+ "requiredClauses_", DirectiveName, DirectivePrefix,
+ ClausePrefix, CppNamespace);
+ }
+
+ // Closing namespaces
+ for (auto Ns : llvm::reverse(Namespaces))
+ OS << "} // namespace " << Ns << "\n";
+
+ OS << "} // namespace llvm\n";
+}
+
+// Generate a map of directive (key) with DirectiveClauses struct as values.
+// The struct holds the 4 sets of enumeration for the 4 kinds of clauses
+// allowances (allowed, allowed once, allowed exclusive and required).
+void GenerateDirectiveClauseMap(const std::vector<Record *> &Directives,
+ raw_ostream &OS, StringRef LanguageName,
+ StringRef ClauseEnumSetClass,
+ StringRef DirectivePrefix,
+ StringRef ClausePrefix,
+ StringRef CppNamespace) {
+
+ IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS);
+
+ OS << "\n";
+ OS << "struct " << LanguageName << "DirectiveClauses {\n";
+ OS << " const " << ClauseEnumSetClass << " allowed;\n";
+ OS << " const " << ClauseEnumSetClass << " allowedOnce;\n";
+ OS << " const " << ClauseEnumSetClass << " allowedExclusive;\n";
+ OS << " const " << ClauseEnumSetClass << " requiredOneOf;\n";
+ OS << "};\n";
+
+ OS << "\n";
+
+ OS << "std::unordered_map<llvm::" << CppNamespace << "::Directive, "
+ << LanguageName << "DirectiveClauses>\n";
+ OS << " directiveClausesTable = {\n";
+
+ for (const auto &D : Directives) {
+ const auto FormattedDirectiveName =
+ getFormattedName(D->getValueAsString("name"));
+ OS << " {llvm::" << CppNamespace << "::Directive::" << DirectivePrefix
+ << FormattedDirectiveName << ",\n";
+ OS << " {\n";
+ OS << " llvm::" << CppNamespace << "::allowedClauses_"
+ << DirectivePrefix << FormattedDirectiveName << ",\n";
+ OS << " llvm::" << CppNamespace << "::allowedOnceClauses_"
+ << DirectivePrefix << FormattedDirectiveName << ",\n";
+ OS << " llvm::" << CppNamespace << "::allowedExclusiveClauses_"
+ << DirectivePrefix << FormattedDirectiveName << ",\n";
+ OS << " llvm::" << CppNamespace << "::requiredClauses_"
+ << DirectivePrefix << FormattedDirectiveName << ",\n";
+ OS << " }\n";
+ OS << " },\n";
+ }
+
+ OS << "};\n";
+}
+
+// Generate the implemenation section for the enumeration in the directive
+// language
+void EmitDirectivesFlangImpl(const std::vector<Record *> &Directives,
+ raw_ostream &OS, StringRef LanguageName,
+ StringRef ClauseEnumSetClass,
+ StringRef DirectivePrefix, StringRef ClausePrefix,
+ StringRef CppNamespace) {
+
+ GenerateDirectiveClauseSets(Directives, OS, LanguageName, ClauseEnumSetClass,
+ DirectivePrefix, ClausePrefix, CppNamespace);
+
+ GenerateDirectiveClauseMap(Directives, OS, LanguageName, ClauseEnumSetClass,
+ DirectivePrefix, ClausePrefix, CppNamespace);
+}
+
+// Generate the implemenation section for the enumeration in the directive
+// language.
+void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) {
+
+ const auto &DirectiveLanguages =
+ Records.getAllDerivedDefinitions("DirectiveLanguage");
+
+ if (DirectiveLanguages.size() != 1) {
+ PrintError("A single definition of DirectiveLanguage is needed.");
+ return;
+ }
+
+ const auto &DirectiveLanguage = DirectiveLanguages[0];
+ StringRef DirectivePrefix =
+ DirectiveLanguage->getValueAsString("directivePrefix");
+ StringRef LanguageName = DirectiveLanguage->getValueAsString("name");
+ StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix");
+ StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace");
+ StringRef ClauseEnumSetClass =
+ DirectiveLanguage->getValueAsString("clauseEnumSetClass");
+
+ const auto &Directives = Records.getAllDerivedDefinitions("Directive");
+
+ EmitDirectivesFlangImpl(Directives, OS, LanguageName, ClauseEnumSetClass,
+ DirectivePrefix, ClausePrefix, CppNamespace);
+}
+
+// Generate the implemenation for the enumeration in the directive
+// language. This code can be included in library.
+void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) {
+
+ const auto &DirectiveLanguages =
+ Records.getAllDerivedDefinitions("DirectiveLanguage");
+
+ if (DirectiveLanguages.size() != 1) {
+ PrintError("A single definition of DirectiveLanguage is needed.");
+ return;
+ }
+
+ const auto &DirectiveLanguage = DirectiveLanguages[0];
+ StringRef DirectivePrefix =
+ DirectiveLanguage->getValueAsString("directivePrefix");
+ StringRef LanguageName = DirectiveLanguage->getValueAsString("name");
+ StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix");
+ StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace");
+ const auto &Directives = Records.getAllDerivedDefinitions("Directive");
+ const auto &Clauses = Records.getAllDerivedDefinitions("Clause");
+
+ StringRef IncludeHeader =
+ DirectiveLanguage->getValueAsString("includeHeader");
+
+ if (!IncludeHeader.empty())
+ OS << "#include \"" << IncludeHeader << "\"\n\n";
+
+ OS << "#include \"llvm/ADT/StringRef.h\"\n";
+ OS << "#include \"llvm/ADT/StringSwitch.h\"\n";
+ OS << "#include \"llvm/Support/ErrorHandling.h\"\n";
+ OS << "\n";
+ OS << "using namespace llvm;\n";
+ llvm::SmallVector<StringRef, 2> Namespaces;
+ llvm::SplitString(CppNamespace, Namespaces, "::");
+ for (auto Ns : Namespaces)
+ OS << "using namespace " << Ns << ";\n";
+
+ // getDirectiveKind(StringRef Str)
+ GenerateGetKind(Directives, OS, "Directive", DirectivePrefix, LanguageName,
+ CppNamespace, /*ImplicitAsUnknown=*/false);
+
+ // getDirectiveName(Directive Kind)
+ GenerateGetName(Directives, OS, "Directive", DirectivePrefix, LanguageName,
+ CppNamespace);
+
+ // getClauseKind(StringRef Str)
+ GenerateGetKind(Clauses, OS, "Clause", ClausePrefix, LanguageName,
+ CppNamespace, /*ImplicitAsUnknown=*/true);
+
+ // getClauseName(Clause Kind)
+ GenerateGetName(Clauses, OS, "Clause", ClausePrefix, LanguageName,
+ CppNamespace);
+
+ // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version)
+ GenerateIsAllowedClause(Directives, OS, LanguageName, DirectivePrefix,
+ ClausePrefix, CppNamespace);
+}
+
+} // namespace llvm
diff --git a/llvm/utils/TableGen/DisassemblerEmitter.cpp b/llvm/utils/TableGen/DisassemblerEmitter.cpp
index 0002b0e14db6..7c3f53b31bf4 100644
--- a/llvm/utils/TableGen/DisassemblerEmitter.cpp
+++ b/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -136,7 +136,7 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
// ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
if (Target.getName() == "ARM" || Target.getName() == "Thumb" ||
Target.getName() == "AArch64" || Target.getName() == "ARM64") {
- std::string PredicateNamespace = Target.getName();
+ std::string PredicateNamespace = std::string(Target.getName());
if (PredicateNamespace == "Thumb")
PredicateNamespace = "ARM";
@@ -148,9 +148,9 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
return;
}
- EmitFixedLenDecoder(Records, OS, Target.getName(),
- "if (", " == MCDisassembler::Fail)",
- "MCDisassembler::Success", "MCDisassembler::Fail", "");
+ EmitFixedLenDecoder(Records, OS, std::string(Target.getName()), "if (",
+ " == MCDisassembler::Fail)", "MCDisassembler::Success",
+ "MCDisassembler::Fail", "");
}
} // end namespace llvm
diff --git a/llvm/utils/TableGen/ExegesisEmitter.cpp b/llvm/utils/TableGen/ExegesisEmitter.cpp
index 976d5f51776f..8f784e4a4121 100644
--- a/llvm/utils/TableGen/ExegesisEmitter.cpp
+++ b/llvm/utils/TableGen/ExegesisEmitter.cpp
@@ -101,7 +101,7 @@ ExegesisEmitter::ExegesisEmitter(RecordKeeper &RK)
PrintFatalError("ERROR: No 'Target' subclasses defined!");
if (Targets.size() != 1)
PrintFatalError("ERROR: Multiple subclasses of Target defined!");
- Target = Targets[0]->getName();
+ Target = std::string(Targets[0]->getName());
}
void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,
diff --git a/llvm/utils/TableGen/FastISelEmitter.cpp b/llvm/utils/TableGen/FastISelEmitter.cpp
index b39956859fe8..0729ab70d696 100644
--- a/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -414,7 +414,7 @@ private:
} // End anonymous namespace
static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
- return CGP.getSDNodeInfo(Op).getEnumName();
+ return std::string(CGP.getSDNodeInfo(Op).getEnumName());
}
static std::string getLegalCName(std::string OpName) {
@@ -719,22 +719,20 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
MVT::SimpleValueType RetVT = RI->first;
const PredMap &PM = RI->second;
- OS << "unsigned fastEmit_"
- << getLegalCName(Opcode)
- << "_" << getLegalCName(getName(VT))
- << "_" << getLegalCName(getName(RetVT)) << "_";
+ OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
+ << getLegalCName(std::string(getName(VT))) << "_"
+ << getLegalCName(std::string(getName(RetVT))) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(";
Operands.PrintParameters(OS);
OS << ") {\n";
- emitInstructionCode(OS, Operands, PM, getName(RetVT));
+ emitInstructionCode(OS, Operands, PM, std::string(getName(RetVT)));
}
// Emit one function for the type that demultiplexes on return type.
- OS << "unsigned fastEmit_"
- << getLegalCName(Opcode) << "_"
- << getLegalCName(getName(VT)) << "_";
+ OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
+ << getLegalCName(std::string(getName(VT))) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT RetVT";
if (!Operands.empty())
@@ -745,8 +743,9 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
RI != RE; ++RI) {
MVT::SimpleValueType RetVT = RI->first;
OS << " case " << getName(RetVT) << ": return fastEmit_"
- << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT))
- << "_" << getLegalCName(getName(RetVT)) << "_";
+ << getLegalCName(Opcode) << "_"
+ << getLegalCName(std::string(getName(VT))) << "_"
+ << getLegalCName(std::string(getName(RetVT))) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(";
Operands.PrintArguments(OS);
@@ -756,9 +755,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
} else {
// Non-variadic return type.
- OS << "unsigned fastEmit_"
- << getLegalCName(Opcode) << "_"
- << getLegalCName(getName(VT)) << "_";
+ OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
+ << getLegalCName(std::string(getName(VT))) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT RetVT";
if (!Operands.empty())
@@ -788,7 +786,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
TI != TE; ++TI) {
MVT::SimpleValueType VT = TI->first;
- std::string TypeName = getName(VT);
+ std::string TypeName = std::string(getName(VT));
OS << " case " << TypeName << ": return fastEmit_"
<< getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
Operands.PrintManglingSuffix(OS, ImmediatePredicates);
diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 21ec5897ea50..88d210f7fd39 100644
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -1182,15 +1182,6 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
return (unsigned)(P - Decoders.begin());
}
-static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
- const std::string &PredicateNamespace) {
- if (str[0] == '!')
- o << "!Bits[" << PredicateNamespace << "::"
- << str.slice(1,str.size()) << "]";
- else
- o << "Bits[" << PredicateNamespace << "::" << str << "]";
-}
-
bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
unsigned Opc) const {
ListInit *Predicates =
@@ -1201,21 +1192,50 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
if (!Pred->getValue("AssemblerMatcherPredicate"))
continue;
- StringRef P = Pred->getValueAsString("AssemblerCondString");
-
- if (P.empty())
+ if (!dyn_cast<DagInit>(Pred->getValue("AssemblerCondDag")->getValue()))
continue;
+ const DagInit *D = Pred->getValueAsDag("AssemblerCondDag");
+ std::string CombineType = D->getOperator()->getAsString();
+ if (CombineType != "any_of" && CombineType != "all_of")
+ PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!");
+ if (D->getNumArgs() == 0)
+ PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!");
+ bool IsOr = CombineType == "any_of";
+
if (!IsFirstEmission)
o << " && ";
- std::pair<StringRef, StringRef> pairs = P.split(',');
- while (!pairs.second.empty()) {
- emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
- o << " && ";
- pairs = pairs.second.split(',');
+ if (IsOr)
+ o << "(";
+
+ bool First = true;
+ for (auto *Arg : D->getArgs()) {
+ if (!First) {
+ if (IsOr)
+ o << " || ";
+ else
+ o << " && ";
+ }
+ if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
+ if (NotArg->getOperator()->getAsString() != "not" ||
+ NotArg->getNumArgs() != 1)
+ PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!");
+ Arg = NotArg->getArg(0);
+ o << "!";
+ }
+ if (!isa<DefInit>(Arg) ||
+ !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
+ PrintFatalError(Pred->getLoc(), "Invalid AssemblerCondDag!");
+ o << "Bits[" << Emitter->PredicateNamespace << "::" << Arg->getAsString()
+ << "]";
+
+ First = false;
}
- emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+
+ if (IsOr)
+ o << ")";
+
IsFirstEmission = false;
}
return !Predicates->empty();
@@ -1229,12 +1249,8 @@ bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const {
if (!Pred->getValue("AssemblerMatcherPredicate"))
continue;
- StringRef P = Pred->getValueAsString("AssemblerCondString");
-
- if (P.empty())
- continue;
-
- return true;
+ if (dyn_cast<DagInit>(Pred->getValue("AssemblerCondDag")->getValue()))
+ return true;
}
return false;
}
@@ -1772,7 +1788,7 @@ static std::string findOperandDecoderMethod(TypedInit *TI) {
StringInit *String = DecoderString ?
dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
if (String) {
- Decoder = String->getValue();
+ Decoder = std::string(String->getValue());
if (!Decoder.empty())
return Decoder;
}
@@ -1809,7 +1825,8 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
StringRef InstDecoder = EncodingDef.getValueAsString("DecoderMethod");
if (InstDecoder != "") {
bool HasCompleteInstDecoder = EncodingDef.getValueAsBit("hasCompleteDecoder");
- InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder));
+ InsnOperands.push_back(
+ OperandInfo(std::string(InstDecoder), HasCompleteInstDecoder));
Operands[Opc] = InsnOperands;
return true;
}
@@ -1839,8 +1856,10 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
if (tiedTo != -1) {
std::pair<unsigned, unsigned> SO =
CGI.Operands.getSubOperandNumber(tiedTo);
- TiedNames[InOutOperands[i].second] = InOutOperands[SO.first].second;
- TiedNames[InOutOperands[SO.first].second] = InOutOperands[i].second;
+ TiedNames[std::string(InOutOperands[i].second)] =
+ std::string(InOutOperands[SO.first].second);
+ TiedNames[std::string(InOutOperands[SO.first].second)] =
+ std::string(InOutOperands[i].second);
}
}
@@ -1936,7 +1955,7 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
StringInit *String = DecoderString ?
dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
if (String && String->getValue() != "")
- Decoder = String->getValue();
+ Decoder = std::string(String->getValue());
if (Decoder == "" &&
CGI.Operands[SO.first].MIOperandInfo &&
@@ -1963,7 +1982,7 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
String = DecoderString ?
dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
if (!isReg && String && String->getValue() != "")
- Decoder = String->getValue();
+ Decoder = std::string(String->getValue());
RecordVal *HasCompleteDecoderVal =
TypeRecord->getValue("hasCompleteDecoder");
@@ -1989,16 +2008,17 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
// For each operand, see if we can figure out where it is encoded.
for (const auto &Op : InOutOperands) {
- if (!NumberedInsnOperands[Op.second].empty()) {
+ if (!NumberedInsnOperands[std::string(Op.second)].empty()) {
InsnOperands.insert(InsnOperands.end(),
- NumberedInsnOperands[Op.second].begin(),
- NumberedInsnOperands[Op.second].end());
+ NumberedInsnOperands[std::string(Op.second)].begin(),
+ NumberedInsnOperands[std::string(Op.second)].end());
continue;
}
- if (!NumberedInsnOperands[TiedNames[Op.second]].empty()) {
- if (!NumberedInsnOperandsNoTie.count(TiedNames[Op.second])) {
+ if (!NumberedInsnOperands[TiedNames[std::string(Op.second)]].empty()) {
+ if (!NumberedInsnOperandsNoTie.count(TiedNames[std::string(Op.second)])) {
// Figure out to which (sub)operand we're tied.
- unsigned i = CGI.Operands.getOperandNamed(TiedNames[Op.second]);
+ unsigned i =
+ CGI.Operands.getOperandNamed(TiedNames[std::string(Op.second)]);
int tiedTo = CGI.Operands[i].getTiedRegister();
if (tiedTo == -1) {
i = CGI.Operands.getOperandNamed(Op.second);
@@ -2009,8 +2029,9 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
std::pair<unsigned, unsigned> SO =
CGI.Operands.getSubOperandNumber(tiedTo);
- InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]]
- [SO.second]);
+ InsnOperands.push_back(
+ NumberedInsnOperands[TiedNames[std::string(Op.second)]]
+ [SO.second]);
}
}
continue;
@@ -2065,7 +2086,7 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef,
}
if (Var->getName() != Op.second &&
- Var->getName() != TiedNames[Op.second]) {
+ Var->getName() != TiedNames[std::string(Op.second)]) {
if (Base != ~0U) {
OpInfo.addField(Base, Width, Offset);
Base = ~0U;
@@ -2460,7 +2481,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
if (populateInstruction(Target, *EncodingDef, *Inst, i, Operands)) {
std::string DecoderNamespace =
- EncodingDef->getValueAsString("DecoderNamespace");
+ std::string(EncodingDef->getValueAsString("DecoderNamespace"));
if (!NumberedEncodings[i].HwModeName.empty())
DecoderNamespace +=
std::string("_") + NumberedEncodings[i].HwModeName.str();
diff --git a/llvm/utils/TableGen/GICombinerEmitter.cpp b/llvm/utils/TableGen/GICombinerEmitter.cpp
index 34eb4edac8de..e2a670070ae7 100644
--- a/llvm/utils/TableGen/GICombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GICombinerEmitter.cpp
@@ -636,7 +636,8 @@ void GICombinerEmitter::emitNameMatcher(raw_ostream &OS) const {
std::string Code;
raw_string_ostream SS(Code);
SS << "return " << EnumeratedRule.getID() << ";\n";
- Cases.push_back(std::make_pair(EnumeratedRule.getName(), SS.str()));
+ Cases.push_back(
+ std::make_pair(std::string(EnumeratedRule.getName()), SS.str()));
}
OS << "static Optional<uint64_t> getRuleIdxForIdentifier(StringRef "
@@ -742,7 +743,8 @@ void GICombinerEmitter::generateCodeForTree(raw_ostream &OS,
const Record &RuleDef = Rule->getDef();
OS << Indent << "// Rule: " << RuleDef.getName() << "\n"
- << Indent << "if (!isRuleDisabled(" << Rule->getID() << ")) {\n";
+ << Indent << "if (!RuleConfig->isRuleDisabled(" << Rule->getID()
+ << ")) {\n";
CodeExpansions Expansions;
for (const auto &VarBinding : Leaf.var_bindings()) {
@@ -840,6 +842,13 @@ void GICombinerEmitter::generateCodeForTree(raw_ostream &OS,
OS << Indent << "return false;\n";
}
+static void emitAdditionalHelperMethodArguments(raw_ostream &OS,
+ Record *Combiner) {
+ for (Record *Arg : Combiner->getValueAsListOfDefs("AdditionalArguments"))
+ OS << ",\n " << Arg->getValueAsString("Type")
+ << Arg->getValueAsString("Name");
+}
+
void GICombinerEmitter::run(raw_ostream &OS) {
gatherRules(Rules, Combiner->getValueAsListOfDefs("Rules"));
if (StopAfterParse) {
@@ -889,81 +898,136 @@ void GICombinerEmitter::run(raw_ostream &OS) {
<< "#endif // ifdef " << Name.upper() << "_GENCOMBINERHELPER_DEPS\n\n";
OS << "#ifdef " << Name.upper() << "_GENCOMBINERHELPER_H\n"
- << "class " << getClassName() << " {\n"
+ << "class " << getClassName() << "RuleConfig {\n"
<< " SparseBitVector<> DisabledRules;\n"
<< "\n"
<< "public:\n"
<< " bool parseCommandLineOption();\n"
<< " bool isRuleDisabled(unsigned ID) const;\n"
+ << " bool setRuleEnabled(StringRef RuleIdentifier);\n"
<< " bool setRuleDisabled(StringRef RuleIdentifier);\n"
<< "\n"
+ << "};\n"
+ << "\n"
+ << "class " << getClassName();
+ StringRef StateClass = Combiner->getValueAsString("StateClass");
+ if (!StateClass.empty())
+ OS << " : public " << StateClass;
+ OS << " {\n"
+ << " const " << getClassName() << "RuleConfig *RuleConfig;\n"
+ << "\n"
+ << "public:\n"
+ << " template<typename ... Args>" << getClassName() << "(const "
+ << getClassName() << "RuleConfig &RuleConfig, Args &&... args) : ";
+ if (!StateClass.empty())
+ OS << StateClass << "(std::forward<Args>(args)...), ";
+ OS << "RuleConfig(&RuleConfig) {}\n"
+ << "\n"
<< " bool tryCombineAll(\n"
<< " GISelChangeObserver &Observer,\n"
<< " MachineInstr &MI,\n"
- << " MachineIRBuilder &B,\n"
- << " CombinerHelper &Helper) const;\n"
- << "};\n\n";
+ << " MachineIRBuilder &B";
+ emitAdditionalHelperMethodArguments(OS, Combiner);
+ OS << ") const;\n";
+ OS << "};\n\n";
emitNameMatcher(OS);
- OS << "bool " << getClassName()
- << "::setRuleDisabled(StringRef RuleIdentifier) {\n"
+ OS << "static Optional<std::pair<uint64_t, uint64_t>> "
+ "getRuleRangeForIdentifier(StringRef RuleIdentifier) {\n"
<< " std::pair<StringRef, StringRef> RangePair = "
"RuleIdentifier.split('-');\n"
<< " if (!RangePair.second.empty()) {\n"
- << " const auto First = getRuleIdxForIdentifier(RangePair.first);\n"
- << " const auto Last = getRuleIdxForIdentifier(RangePair.second);\n"
+ << " const auto First = "
+ "getRuleIdxForIdentifier(RangePair.first);\n"
+ << " const auto Last = "
+ "getRuleIdxForIdentifier(RangePair.second);\n"
<< " if (!First.hasValue() || !Last.hasValue())\n"
- << " return false;\n"
+ << " return None;\n"
<< " if (First >= Last)\n"
- << " report_fatal_error(\"Beginning of range should be before end of "
- "range\");\n"
- << " for (auto I = First.getValue(); I < Last.getValue(); ++I)\n"
- << " DisabledRules.set(I);\n"
- << " return true;\n"
+ << " report_fatal_error(\"Beginning of range should be before "
+ "end of range\");\n"
+ << " return {{ *First, *Last + 1 }};\n"
+ << " } else if (RangePair.first == \"*\") {\n"
+ << " return {{ 0, " << Rules.size() << " }};\n"
<< " } else {\n"
<< " const auto I = getRuleIdxForIdentifier(RangePair.first);\n"
<< " if (!I.hasValue())\n"
- << " return false;\n"
- << " DisabledRules.set(I.getValue());\n"
- << " return true;\n"
+ << " return None;\n"
+ << " return {{*I, *I + 1}};\n"
<< " }\n"
- << " return false;\n"
- << "}\n";
+ << " return None;\n"
+ << "}\n\n";
+
+ for (bool Enabled : {true, false}) {
+ OS << "bool " << getClassName() << "RuleConfig::setRule"
+ << (Enabled ? "Enabled" : "Disabled") << "(StringRef RuleIdentifier) {\n"
+ << " auto MaybeRange = getRuleRangeForIdentifier(RuleIdentifier);\n"
+ << " if(!MaybeRange.hasValue())\n"
+ << " return false;\n"
+ << " for (auto I = MaybeRange->first; I < MaybeRange->second; ++I)\n"
+ << " DisabledRules." << (Enabled ? "reset" : "set") << "(I);\n"
+ << " return true;\n"
+ << "}\n\n";
+ }
OS << "bool " << getClassName()
- << "::isRuleDisabled(unsigned RuleID) const {\n"
+ << "RuleConfig::isRuleDisabled(unsigned RuleID) const {\n"
<< " return DisabledRules.test(RuleID);\n"
<< "}\n";
OS << "#endif // ifdef " << Name.upper() << "_GENCOMBINERHELPER_H\n\n";
OS << "#ifdef " << Name.upper() << "_GENCOMBINERHELPER_CPP\n"
<< "\n"
- << "cl::list<std::string> " << Name << "Option(\n"
+ << "std::vector<std::string> " << Name << "Option;\n"
+ << "cl::list<std::string> " << Name << "DisableOption(\n"
<< " \"" << Name.lower() << "-disable-rule\",\n"
<< " cl::desc(\"Disable one or more combiner rules temporarily in "
<< "the " << Name << " pass\"),\n"
<< " cl::CommaSeparated,\n"
<< " cl::Hidden,\n"
- << " cl::cat(GICombinerOptionCategory));\n"
+ << " cl::cat(GICombinerOptionCategory),\n"
+ << " cl::callback([](const std::string &Str) {\n"
+ << " " << Name << "Option.push_back(Str);\n"
+ << " }));\n"
+ << "cl::list<std::string> " << Name << "OnlyEnableOption(\n"
+ << " \"" << Name.lower() << "-only-enable-rule\",\n"
+ << " cl::desc(\"Disable all rules in the " << Name
+ << " pass then re-enable the specified ones\"),\n"
+ << " cl::Hidden,\n"
+ << " cl::cat(GICombinerOptionCategory),\n"
+ << " cl::callback([](const std::string &CommaSeparatedArg) {\n"
+ << " StringRef Str = CommaSeparatedArg;\n"
+ << " " << Name << "Option.push_back(\"*\");\n"
+ << " do {\n"
+ << " auto X = Str.split(\",\");\n"
+ << " " << Name << "Option.push_back((\"!\" + X.first).str());\n"
+ << " Str = X.second;\n"
+ << " } while (!Str.empty());\n"
+ << " }));\n"
<< "\n"
- << "bool " << getClassName() << "::parseCommandLineOption() {\n"
- << " for (const auto &Identifier : " << Name << "Option)\n"
- << " if (!setRuleDisabled(Identifier))\n"
+ << "bool " << getClassName() << "RuleConfig::parseCommandLineOption() {\n"
+ << " for (StringRef Identifier : " << Name << "Option) {\n"
+ << " bool Enabled = Identifier.consume_front(\"!\");\n"
+ << " if (Enabled && !setRuleEnabled(Identifier))\n"
<< " return false;\n"
+ << " if (!Enabled && !setRuleDisabled(Identifier))\n"
+ << " return false;\n"
+ << " }\n"
<< " return true;\n"
<< "}\n\n";
OS << "bool " << getClassName() << "::tryCombineAll(\n"
<< " GISelChangeObserver &Observer,\n"
<< " MachineInstr &MI,\n"
- << " MachineIRBuilder &B,\n"
- << " CombinerHelper &Helper) const {\n"
+ << " MachineIRBuilder &B";
+ emitAdditionalHelperMethodArguments(OS, Combiner);
+ OS << ") const {\n"
<< " MachineBasicBlock *MBB = MI.getParent();\n"
<< " MachineFunction *MF = MBB->getParent();\n"
<< " MachineRegisterInfo &MRI = MF->getRegInfo();\n"
<< " SmallVector<MachineInstr *, 8> MIs = { &MI };\n\n"
- << " (void)MBB; (void)MF; (void)MRI;\n\n";
+ << " (void)MBB; (void)MF; (void)MRI; (void)RuleConfig;\n\n";
OS << " // Match data\n";
for (const auto &Rule : Rules)
diff --git a/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp b/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp
index 4884bdadea91..96dc4fc94893 100644
--- a/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp
+++ b/llvm/utils/TableGen/GlobalISel/GIMatchTree.cpp
@@ -10,6 +10,7 @@
#include "../CodeGenInstruction.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
@@ -611,18 +612,23 @@ void GIMatchTreeOpcodePartitioner::emitPartitionResults(
void GIMatchTreeOpcodePartitioner::generatePartitionSelectorCode(
raw_ostream &OS, StringRef Indent) const {
- OS << Indent << "Partition = -1;\n"
- << Indent << "switch (MIs[" << InstrID << "]->getOpcode()) {\n";
- for (const auto &EnumInstr : enumerate(PartitionToInstr)) {
- if (EnumInstr.value() == nullptr)
- OS << Indent << "default:";
- else
- OS << Indent << "case " << EnumInstr.value()->Namespace
- << "::" << EnumInstr.value()->TheDef->getName() << ":";
- OS << " Partition = " << EnumInstr.index() << "; break;\n";
+ // Make sure not to emit empty switch or switch with just default
+ if (PartitionToInstr.size() == 1 && PartitionToInstr[0] == nullptr) {
+ OS << Indent << "Partition = 0;\n";
+ } else if (PartitionToInstr.size()) {
+ OS << Indent << "Partition = -1;\n"
+ << Indent << "switch (MIs[" << InstrID << "]->getOpcode()) {\n";
+ for (const auto &EnumInstr : enumerate(PartitionToInstr)) {
+ if (EnumInstr.value() == nullptr)
+ OS << Indent << "default:";
+ else
+ OS << Indent << "case " << EnumInstr.value()->Namespace
+ << "::" << EnumInstr.value()->TheDef->getName() << ":";
+ OS << " Partition = " << EnumInstr.index() << "; break;\n";
+ }
+ OS << Indent << "}\n";
}
- OS << Indent << "}\n"
- << Indent
+ OS << Indent
<< "// Default case but without conflicting with potential default case "
"in selection.\n"
<< Indent << "if (Partition == -1) return false;\n";
@@ -774,4 +780,3 @@ void GIMatchTreeVRegDefPartitioner::generatePartitionSelectorCode(
OS << Indent << "if (Partition == -1) return false;\n";
}
-
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index c14294951cc1..4e8dcc52fc20 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -448,7 +448,6 @@ public:
: LabelID(LabelID_.hasValue() ? LabelID_.getValue() : ~0u),
EmitStr(EmitStr), NumElements(NumElements), Flags(Flags),
RawValue(RawValue) {
-
assert((!LabelID_.hasValue() || LabelID != ~0u) &&
"This value is reserved for non-labels");
}
@@ -1044,6 +1043,28 @@ public:
for (const auto &Predicate : predicates())
Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);
}
+
+ /// Provide a function to avoid emitting certain predicates. This is used to
+ /// defer some predicate checks until after others
+ using PredicateFilterFunc = std::function<bool(const PredicateTy&)>;
+
+ /// Emit MatchTable opcodes for predicates which satisfy \p
+ /// ShouldEmitPredicate. This should be called multiple times to ensure all
+ /// predicates are eventually added to the match table.
+ template <class... Args>
+ void emitFilteredPredicateListOpcodes(PredicateFilterFunc ShouldEmitPredicate,
+ MatchTable &Table, Args &&... args) {
+ if (Predicates.empty() && !Optimized) {
+ Table << MatchTable::Comment(getNoPredicateComment())
+ << MatchTable::LineBreak;
+ return;
+ }
+
+ for (const auto &Predicate : predicates()) {
+ if (ShouldEmitPredicate(*Predicate))
+ Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);
+ }
+ }
};
class PredicateMatcher {
@@ -1101,6 +1122,13 @@ public:
PredicateKind getKind() const { return Kind; }
+ bool dependsOnOperands() const {
+ // Custom predicates really depend on the context pattern of the
+ // instruction, not just the individual instruction. This therefore
+ // implicitly depends on all other pattern constraints.
+ return Kind == IPM_GenericPredicate;
+ }
+
virtual bool isIdentical(const PredicateMatcher &B) const {
return B.getKind() == getKind() && InsnVarID == B.InsnVarID &&
OpIdx == B.OpIdx;
@@ -1498,7 +1526,7 @@ public:
const StringRef getSymbolicName() const { return SymbolicName; }
void setSymbolicName(StringRef Name) {
assert(SymbolicName.empty() && "Operand already has a symbolic name");
- SymbolicName = Name;
+ SymbolicName = std::string(Name);
}
/// Construct a new operand predicate and add it to the matcher.
@@ -2128,10 +2156,23 @@ public:
InstructionNumOperandsMatcher(InsnVarID, getNumOperands())
.emitPredicateOpcodes(Table, Rule);
- emitPredicateListOpcodes(Table, Rule);
+ // First emit all instruction level predicates need to be verified before we
+ // can verify operands.
+ emitFilteredPredicateListOpcodes(
+ [](const PredicateMatcher &P) {
+ return !P.dependsOnOperands();
+ }, Table, Rule);
+ // Emit all operand constraints.
for (const auto &Operand : Operands)
Operand->emitPredicateOpcodes(Table, Rule);
+
+ // All of the tablegen defined predicates should now be matched. Now emit
+ // any custom predicates that rely on all generated checks.
+ emitFilteredPredicateListOpcodes(
+ [](const PredicateMatcher &P) {
+ return P.dependsOnOperands();
+ }, Table, Rule);
}
/// Compare the priority of this object and B.
@@ -2585,26 +2626,37 @@ class TempRegRenderer : public OperandRenderer {
protected:
unsigned InsnID;
unsigned TempRegID;
+ const CodeGenSubRegIndex *SubRegIdx;
bool IsDef;
public:
- TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false)
+ TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false,
+ const CodeGenSubRegIndex *SubReg = nullptr)
: OperandRenderer(OR_Register), InsnID(InsnID), TempRegID(TempRegID),
- IsDef(IsDef) {}
+ SubRegIdx(SubReg), IsDef(IsDef) {}
static bool classof(const OperandRenderer *R) {
return R->getKind() == OR_TempRegister;
}
void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
- Table << MatchTable::Opcode("GIR_AddTempRegister")
- << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
+ if (SubRegIdx) {
+ assert(!IsDef);
+ Table << MatchTable::Opcode("GIR_AddTempSubRegister");
+ } else
+ Table << MatchTable::Opcode("GIR_AddTempRegister");
+
+ Table << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
<< MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID)
<< MatchTable::Comment("TempRegFlags");
+
if (IsDef)
Table << MatchTable::NamedValue("RegState::Define");
else
Table << MatchTable::IntValue(0);
+
+ if (SubRegIdx)
+ Table << MatchTable::NamedValue(SubRegIdx->getQualifiedName());
Table << MatchTable::LineBreak;
}
};
@@ -2779,7 +2831,7 @@ private:
std::string S;
public:
- DebugCommentAction(StringRef S) : S(S) {}
+ DebugCommentAction(StringRef S) : S(std::string(S)) {}
void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
Table << MatchTable::Comment(S) << MatchTable::LineBreak;
@@ -2950,8 +3002,8 @@ public:
Table << MatchTable::Opcode("GIR_ConstrainOperandRC")
<< MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
<< MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx)
- << MatchTable::Comment("RC " + RC.getName())
- << MatchTable::IntValue(RC.EnumValue) << MatchTable::LineBreak;
+ << MatchTable::NamedValue(RC.getQualifiedName() + "RegClassID")
+ << MatchTable::LineBreak;
}
};
@@ -3260,6 +3312,22 @@ void SameOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
//===- GlobalISelEmitter class --------------------------------------------===//
+static Expected<LLTCodeGen> getInstResultType(const TreePatternNode *Dst) {
+ ArrayRef<TypeSetByHwMode> ChildTypes = Dst->getExtTypes();
+ if (ChildTypes.size() != 1)
+ return failedImport("Dst pattern child has multiple results");
+
+ Optional<LLTCodeGen> MaybeOpTy;
+ if (ChildTypes.front().isMachineValueType()) {
+ MaybeOpTy =
+ MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
+ }
+
+ if (!MaybeOpTy)
+ return failedImport("Dst operand has an unsupported type");
+ return *MaybeOpTy;
+}
+
class GlobalISelEmitter {
public:
explicit GlobalISelEmitter(RecordKeeper &RK);
@@ -3269,7 +3337,7 @@ private:
const RecordKeeper &RK;
const CodeGenDAGPatterns CGP;
const CodeGenTarget &Target;
- CodeGenRegBank CGRegs;
+ CodeGenRegBank &CGRegs;
/// Keep track of the equivalence between SDNodes and Instruction by mapping
/// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to
@@ -3477,7 +3545,7 @@ GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode *N) const {
GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
: RK(RK), CGP(RK), Target(CGP.getTargetInfo()),
- CGRegs(RK, Target.getHwModes()) {}
+ CGRegs(Target.getRegBank()) {}
//===- Emitter ------------------------------------------------------------===//
@@ -3737,7 +3805,7 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
CCDef->getValueAsString("ICmpPredicate");
if (!PredType.empty()) {
- OM.addPredicate<CmpPredicateOperandMatcher>(PredType);
+ OM.addPredicate<CmpPredicateOperandMatcher>(std::string(PredType));
// Process the other 2 operands normally.
--NumChildren;
}
@@ -3836,9 +3904,10 @@ Error GlobalISelEmitter::importChildMatcher(
Record *PhysReg = nullptr;
StringRef SrcChildName = getSrcChildName(SrcChild, PhysReg);
- OperandMatcher &OM = PhysReg ?
- InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx) :
- InsnMatcher.addOperand(OpIdx, SrcChildName, TempOpIdx);
+ OperandMatcher &OM =
+ PhysReg
+ ? InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx)
+ : InsnMatcher.addOperand(OpIdx, std::string(SrcChildName), TempOpIdx);
if (OM.isSameAsAnotherOperand())
return Error::success();
@@ -3971,6 +4040,10 @@ Error GlobalISelEmitter::importChildMatcher(
"Src pattern child def is an unsupported tablegen class (ImmLeaf)");
}
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ if (ChildRec->getName() == "srcvalue")
+ return Error::success();
+
return failedImport(
"Src pattern child def is an unsupported tablegen class");
}
@@ -4040,20 +4113,13 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
}
if (DstChild->getOperator()->isSubClassOf("Instruction")) {
- ArrayRef<TypeSetByHwMode> ChildTypes = DstChild->getExtTypes();
- if (ChildTypes.size() != 1)
- return failedImport("Dst pattern child has multiple results");
-
- Optional<LLTCodeGen> OpTyOrNone = None;
- if (ChildTypes.front().isMachineValueType())
- OpTyOrNone =
- MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
- if (!OpTyOrNone)
- return failedImport("Dst operand has an unsupported type");
+ auto OpTy = getInstResultType(DstChild);
+ if (!OpTy)
+ return OpTy.takeError();
unsigned TempRegID = Rule.allocateTempRegID();
InsertPt = Rule.insertAction<MakeTempRegisterAction>(
- InsertPt, OpTyOrNone.getValue(), TempRegID);
+ InsertPt, *OpTy, TempRegID);
DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
auto InsertPtOrError = createAndImportSubInstructionRenderer(
@@ -4225,7 +4291,7 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
if (!SubIdx)
return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
- const auto &SrcRCDstRCPair =
+ const auto SrcRCDstRCPair =
(*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
M.insertAction<ConstrainOperandToRegClassAction>(
@@ -4257,6 +4323,29 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
return InsertPtOrError.get();
}
+ if (OpName == "REG_SEQUENCE") {
+ auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
+ M.insertAction<ConstrainOperandToRegClassAction>(
+ InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
+
+ unsigned Num = Dst->getNumChildren();
+ for (unsigned I = 1; I != Num; I += 2) {
+ TreePatternNode *SubRegChild = Dst->getChild(I + 1);
+
+ auto SubIdx = inferSubRegIndexForNode(SubRegChild);
+ if (!SubIdx)
+ return failedImport("REG_SEQUENCE child is not a subreg index");
+
+ const auto SrcRCDstRCPair =
+ (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
+ assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
+ M.insertAction<ConstrainOperandToRegClassAction>(
+ InsertPt, DstMIBuilder.getInsnID(), I, *SrcRCDstRCPair->second);
+ }
+
+ return InsertPtOrError.get();
+ }
+
M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt,
DstMIBuilder.getInsnID());
return InsertPtOrError.get();
@@ -4303,33 +4392,51 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
// EXTRACT_SUBREG needs to use a subregister COPY.
if (Name == "EXTRACT_SUBREG") {
- if (!Dst->getChild(0)->isLeaf())
- return failedImport("EXTRACT_SUBREG child #1 is not a leaf");
-
- if (DefInit *SubRegInit =
- dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) {
- Record *RCDef = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
- if (!RCDef)
- return failedImport("EXTRACT_SUBREG child #0 could not "
- "be coerced to a register class");
-
- CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef);
- CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
-
- const auto &SrcRCDstRCPair =
- RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
- if (SrcRCDstRCPair.hasValue()) {
- assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
- if (SrcRCDstRCPair->first != RC)
- return failedImport("EXTRACT_SUBREG requires an additional COPY");
- }
+ DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue());
+ if (!SubRegInit)
+ return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
+
+ CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
+ TreePatternNode *ValChild = Dst->getChild(0);
+ if (!ValChild->isLeaf()) {
+ // We really have to handle the source instruction, and then insert a
+ // copy from the subregister.
+ auto ExtractSrcTy = getInstResultType(ValChild);
+ if (!ExtractSrcTy)
+ return ExtractSrcTy.takeError();
+
+ unsigned TempRegID = M.allocateTempRegID();
+ InsertPt = M.insertAction<MakeTempRegisterAction>(
+ InsertPt, *ExtractSrcTy, TempRegID);
- DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(),
- SubIdx);
+ auto InsertPtOrError = createAndImportSubInstructionRenderer(
+ ++InsertPt, M, ValChild, TempRegID);
+ if (auto Error = InsertPtOrError.takeError())
+ return std::move(Error);
+
+ DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, false, SubIdx);
return InsertPt;
}
- return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
+ // If this is a source operand, this is just a subregister copy.
+ Record *RCDef = getInitValueAsRegClass(ValChild->getLeafValue());
+ if (!RCDef)
+ return failedImport("EXTRACT_SUBREG child #0 could not "
+ "be coerced to a register class");
+
+ CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef);
+
+ const auto SrcRCDstRCPair =
+ RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
+ if (SrcRCDstRCPair.hasValue()) {
+ assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
+ if (SrcRCDstRCPair->first != RC)
+ return failedImport("EXTRACT_SUBREG requires an additional COPY");
+ }
+
+ DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(),
+ SubIdx);
+ return InsertPt;
}
if (Name == "REG_SEQUENCE") {
@@ -4731,15 +4838,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
if (DstIOpRec == nullptr)
return failedImport("REG_SEQUENCE operand #0 isn't a register class");
} else if (DstIName == "EXTRACT_SUBREG") {
- if (!Dst->getChild(0)->isLeaf())
- return failedImport("EXTRACT_SUBREG operand #0 isn't a leaf");
+ auto InferredClass = inferRegClassFromPattern(Dst->getChild(0));
+ if (!InferredClass)
+ return failedImport("Could not infer class for EXTRACT_SUBREG operand #0");
// We can assume that a subregister is in the same bank as it's super
// register.
- DstIOpRec = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
-
- if (DstIOpRec == nullptr)
- return failedImport("EXTRACT_SUBREG operand #0 isn't a register class");
+ DstIOpRec = (*InferredClass)->getDef();
} else if (DstIName == "INSERT_SUBREG") {
auto MaybeSuperClass = inferSuperRegisterClassForNode(
VTy, Dst->getChild(0), Dst->getChild(2));
@@ -4832,8 +4937,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
assert(Src->getExtTypes().size() == 1 &&
"Expected Src of EXTRACT_SUBREG to have one result type");
- const auto &SrcRCDstRCPair =
+ const auto SrcRCDstRCPair =
(*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
+ if (!SrcRCDstRCPair) {
+ return failedImport("subreg index is incompatible "
+ "with inferred reg class");
+ }
+
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
M.addAction<ConstrainOperandToRegClassAction>(0, 0, *SrcRCDstRCPair->second);
M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first);
@@ -4889,6 +4999,30 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
return std::move(M);
}
+ if (DstIName == "REG_SEQUENCE") {
+ auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
+
+ M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass);
+
+ unsigned Num = Dst->getNumChildren();
+ for (unsigned I = 1; I != Num; I += 2) {
+ TreePatternNode *SubRegChild = Dst->getChild(I + 1);
+
+ auto SubIdx = inferSubRegIndexForNode(SubRegChild);
+ if (!SubIdx)
+ return failedImport("REG_SEQUENCE child is not a subreg index");
+
+ const auto SrcRCDstRCPair =
+ (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
+
+ M.addAction<ConstrainOperandToRegClassAction>(0, I,
+ *SrcRCDstRCPair->second);
+ }
+
+ ++NumPatternImported;
+ return std::move(M);
+ }
+
M.addAction<ConstrainOperandsToDefinitionAction>(0);
// We're done with this pattern! It's eligible for GISel emission; return it.
diff --git a/llvm/utils/TableGen/InstrDocsEmitter.cpp b/llvm/utils/TableGen/InstrDocsEmitter.cpp
index 07efa1885409..66744bf9ecef 100644
--- a/llvm/utils/TableGen/InstrDocsEmitter.cpp
+++ b/llvm/utils/TableGen/InstrDocsEmitter.cpp
@@ -61,7 +61,7 @@ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
unsigned VariantCount = Target.getAsmParserVariantCount();
// Page title.
- std::string Title = Target.getName();
+ std::string Title = std::string(Target.getName());
Title += " Instructions";
writeTitle(Title, OS);
OS << "\n";
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 6ab58bd26a2c..f3141735a995 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -524,7 +524,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "namespace llvm {\n\n";
CodeGenTarget &Target = CDP.getTargetInfo();
- const std::string &TargetName = Target.getName();
+ const std::string &TargetName = std::string(Target.getName());
Record *InstrInfo = Target.getInstructionSet();
// Keep track of all of the def lists we have emitted already.
@@ -561,7 +561,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
unsigned Num = 0;
for (const CodeGenInstruction *Inst : NumberedInstructions) {
// Keep a list of the instruction names.
- InstrNames.add(Inst->TheDef->getName());
+ InstrNames.add(std::string(Inst->TheDef->getName()));
// Emit the record into the table.
emitRecord(*Inst, Num++, InstrInfo, EmittedLists, OperandInfoIDs, OS);
}
@@ -569,9 +569,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
// Emit the array of instruction names.
InstrNames.layout();
- OS << "extern const char " << TargetName << "InstrNameData[] = {\n";
- InstrNames.emit(OS, printChar);
- OS << "};\n\n";
+ InstrNames.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName +
+ "InstrNameData[]");
OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {";
Num = 0;
@@ -579,18 +578,69 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
// Newline every eight entries.
if (Num % 8 == 0)
OS << "\n ";
- OS << InstrNames.get(Inst->TheDef->getName()) << "U, ";
+ OS << InstrNames.get(std::string(Inst->TheDef->getName())) << "U, ";
++Num;
}
-
OS << "\n};\n\n";
+ bool HasDeprecationFeatures =
+ llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {
+ return !Inst->HasComplexDeprecationPredicate &&
+ !Inst->DeprecatedReason.empty();
+ });
+ if (HasDeprecationFeatures) {
+ OS << "extern const uint8_t " << TargetName
+ << "InstrDeprecationFeatures[] = {";
+ Num = 0;
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ if (Num % 8 == 0)
+ OS << "\n ";
+ if (!Inst->HasComplexDeprecationPredicate &&
+ !Inst->DeprecatedReason.empty())
+ OS << Target.getInstNamespace() << "::" << Inst->DeprecatedReason
+ << ", ";
+ else
+ OS << "uint8_t(-1), ";
+ ++Num;
+ }
+ OS << "\n};\n\n";
+ }
+
+ bool HasComplexDeprecationInfos =
+ llvm::any_of(NumberedInstructions, [](const CodeGenInstruction *Inst) {
+ return Inst->HasComplexDeprecationPredicate;
+ });
+ if (HasComplexDeprecationInfos) {
+ OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName
+ << "InstrComplexDeprecationInfos[] = {";
+ Num = 0;
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ if (Num % 8 == 0)
+ OS << "\n ";
+ if (Inst->HasComplexDeprecationPredicate)
+ // Emit a function pointer to the complex predicate method.
+ OS << "&get" << Inst->DeprecatedReason << "DeprecationInfo, ";
+ else
+ OS << "nullptr, ";
+ ++Num;
+ }
+ OS << "\n};\n\n";
+ }
+
// MCInstrInfo initialization routine.
OS << "static inline void Init" << TargetName
<< "MCInstrInfo(MCInstrInfo *II) {\n";
- OS << " II->InitMCInstrInfo(" << TargetName << "Insts, "
- << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
- << NumberedInstructions.size() << ");\n}\n\n";
+ OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " << TargetName
+ << "InstrNameIndices, " << TargetName << "InstrNameData, ";
+ if (HasDeprecationFeatures)
+ OS << TargetName << "InstrDeprecationFeatures, ";
+ else
+ OS << "nullptr, ";
+ if (HasComplexDeprecationInfos)
+ OS << TargetName << "InstrComplexDeprecationInfos, ";
+ else
+ OS << "nullptr, ";
+ OS << NumberedInstructions.size() << ");\n}\n\n";
OS << "} // end namespace llvm\n";
@@ -630,12 +680,28 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n";
OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
OS << "extern const char " << TargetName << "InstrNameData[];\n";
+ if (HasDeprecationFeatures)
+ OS << "extern const uint8_t " << TargetName
+ << "InstrDeprecationFeatures[];\n";
+ if (HasComplexDeprecationInfos)
+ OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName
+ << "InstrComplexDeprecationInfos[];\n";
OS << ClassName << "::" << ClassName
- << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode, int ReturnOpcode)\n"
- << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, ReturnOpcode) {\n"
+ << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode, int "
+ "ReturnOpcode)\n"
+ << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, "
+ "ReturnOpcode) {\n"
<< " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName
- << "InstrNameIndices, " << TargetName << "InstrNameData, "
- << NumberedInstructions.size() << ");\n}\n";
+ << "InstrNameIndices, " << TargetName << "InstrNameData, ";
+ if (HasDeprecationFeatures)
+ OS << TargetName << "InstrDeprecationFeatures, ";
+ else
+ OS << "nullptr, ";
+ if (HasComplexDeprecationInfos)
+ OS << TargetName << "InstrComplexDeprecationInfos, ";
+ else
+ OS << "nullptr, ";
+ OS << NumberedInstructions.size() << ");\n}\n";
OS << "} // end namespace llvm\n";
OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
@@ -746,18 +812,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
else
OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
- if (Inst.HasComplexDeprecationPredicate)
- // Emit a function pointer to the complex predicate method.
- OS << ", -1 "
- << ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
- else if (!Inst.DeprecatedReason.empty())
- // Emit the Subtarget feature.
- OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
- << " ,nullptr";
- else
- // Instruction isn't deprecated.
- OS << ", -1 ,nullptr";
-
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
@@ -768,7 +822,7 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
OS << "namespace llvm {\n\n";
- CodeGenTarget Target(Records);
+ const CodeGenTarget &Target = CDP.getTargetInfo();
// We must emit the PHI opcode first...
StringRef Namespace = Target.getInstNamespace();
diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp
index 9a12571ac6bc..7e4191494149 100644
--- a/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -244,7 +244,9 @@ enum IIT_Info {
IIT_SCALABLE_VEC = 43,
IIT_SUBDIVIDE2_ARG = 44,
IIT_SUBDIVIDE4_ARG = 45,
- IIT_VEC_OF_BITCASTS_TO_INT = 46
+ IIT_VEC_OF_BITCASTS_TO_INT = 46,
+ IIT_V128 = 47,
+ IIT_BF16 = 48
};
static void EncodeFixedValueType(MVT::SimpleValueType VT,
@@ -265,6 +267,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
switch (VT) {
default: PrintFatalError("unhandled MVT in intrinsic!");
case MVT::f16: return Sig.push_back(IIT_F16);
+ case MVT::bf16: return Sig.push_back(IIT_BF16);
case MVT::f32: return Sig.push_back(IIT_F32);
case MVT::f64: return Sig.push_back(IIT_F64);
case MVT::f128: return Sig.push_back(IIT_F128);
@@ -380,6 +383,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
case 16: Sig.push_back(IIT_V16); break;
case 32: Sig.push_back(IIT_V32); break;
case 64: Sig.push_back(IIT_V64); break;
+ case 128: Sig.push_back(IIT_V128); break;
case 512: Sig.push_back(IIT_V512); break;
case 1024: Sig.push_back(IIT_V1024); break;
}
@@ -577,6 +581,12 @@ struct AttributeComparator {
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
+ if (L->isNoSync != R->isNoSync)
+ return R->isNoSync;
+
+ if (L->isNoFree != R->isNoFree)
+ return R->isNoFree;
+
if (L->isWillReturn != R->isWillReturn)
return R->isWillReturn;
@@ -656,14 +666,15 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size();
if (ae) {
while (ai != ae) {
- unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
- unsigned attrIdx = argNo + 1; // Must match AttributeList::FirstArgIndex
+ unsigned attrIdx = intrinsic.ArgumentAttributes[ai].Index;
OS << " const Attribute::AttrKind AttrParam" << attrIdx << "[]= {";
bool addComma = false;
+ bool AllValuesAreZero = true;
+ SmallVector<uint64_t, 8> Values;
do {
- switch (intrinsic.ArgumentAttributes[ai].second) {
+ switch (intrinsic.ArgumentAttributes[ai].Kind) {
case CodeGenIntrinsic::NoCapture:
if (addComma)
OS << ",";
@@ -706,21 +717,48 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << "Attribute::ImmArg";
addComma = true;
break;
+ case CodeGenIntrinsic::Alignment:
+ if (addComma)
+ OS << ',';
+ OS << "Attribute::Alignment";
+ addComma = true;
+ break;
}
+ uint64_t V = intrinsic.ArgumentAttributes[ai].Value;
+ Values.push_back(V);
+ AllValuesAreZero &= (V == 0);
++ai;
- } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
+ } while (ai != ae && intrinsic.ArgumentAttributes[ai].Index == attrIdx);
OS << "};\n";
+
+ // Generate attribute value array if not all attribute values are zero.
+ if (!AllValuesAreZero) {
+ OS << " const uint64_t AttrValParam" << attrIdx << "[]= {";
+ addComma = false;
+ for (const auto V : Values) {
+ if (addComma)
+ OS << ',';
+ OS << V;
+ addComma = true;
+ }
+ OS << "};\n";
+ }
+
OS << " AS[" << numAttrs++ << "] = AttributeList::get(C, "
- << attrIdx << ", AttrParam" << attrIdx << ");\n";
+ << attrIdx << ", AttrParam" << attrIdx;
+ if (!AllValuesAreZero)
+ OS << ", AttrValParam" << attrIdx;
+ OS << ");\n";
}
}
if (!intrinsic.canThrow ||
- (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) ||
- intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold ||
- intrinsic.isNoDuplicate || intrinsic.isConvergent ||
- intrinsic.isSpeculatable) {
+ (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem &&
+ !intrinsic.hasSideEffects) ||
+ intrinsic.isNoReturn || intrinsic.isNoSync || intrinsic.isNoFree ||
+ intrinsic.isWillReturn || intrinsic.isCold || intrinsic.isNoDuplicate ||
+ intrinsic.isConvergent || intrinsic.isSpeculatable) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@@ -733,6 +771,18 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
OS << "Attribute::NoReturn";
addComma = true;
}
+ if (intrinsic.isNoSync) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoSync";
+ addComma = true;
+ }
+ if (intrinsic.isNoFree) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoFree";
+ addComma = true;
+ }
if (intrinsic.isWillReturn) {
if (addComma)
OS << ",";
diff --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp
index c1978ac7ac66..251533a8d154 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -10,20 +10,22 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cctype>
#include <cstring>
#include <map>
+#include <memory>
using namespace llvm;
static const std::string getOptionName(const Record &R) {
// Use the record name unless EnumName is defined.
if (isa<UnsetInit>(R.getValueInit("EnumName")))
- return R.getName();
+ return std::string(R.getName());
- return R.getValueAsString("EnumName");
+ return std::string(R.getValueAsString("EnumName"));
}
static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
@@ -33,6 +35,210 @@ static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
return OS;
}
+static const std::string getOptionSpelling(const Record &R,
+ size_t &PrefixLength) {
+ std::vector<StringRef> Prefixes = R.getValueAsListOfStrings("Prefixes");
+ StringRef Name = R.getValueAsString("Name");
+ if (Prefixes.empty()) {
+ PrefixLength = 0;
+ return Name.str();
+ }
+ PrefixLength = Prefixes[0].size();
+ return (Twine(Prefixes[0]) + Twine(Name)).str();
+}
+
+static const std::string getOptionSpelling(const Record &R) {
+ size_t PrefixLength;
+ return getOptionSpelling(R, PrefixLength);
+}
+
+static void emitNameUsingSpelling(raw_ostream &OS, const Record &R) {
+ size_t PrefixLength;
+ OS << "&";
+ write_cstring(OS, StringRef(getOptionSpelling(R, PrefixLength)));
+ OS << "[" << PrefixLength << "]";
+}
+
+class MarshallingKindInfo {
+public:
+ const Record &R;
+ const char *MacroName;
+ bool ShouldAlwaysEmit;
+ StringRef KeyPath;
+ StringRef DefaultValue;
+ StringRef NormalizedValuesScope;
+
+ void emit(raw_ostream &OS) const {
+ write_cstring(OS, StringRef(getOptionSpelling(R)));
+ OS << ", ";
+ OS << ShouldAlwaysEmit;
+ OS << ", ";
+ OS << KeyPath;
+ OS << ", ";
+ emitScopedNormalizedValue(OS, DefaultValue);
+ OS << ", ";
+ emitSpecific(OS);
+ }
+
+ virtual Optional<StringRef> emitValueTable(raw_ostream &OS) const {
+ return None;
+ }
+
+ virtual ~MarshallingKindInfo() = default;
+
+ static std::unique_ptr<MarshallingKindInfo> create(const Record &R);
+
+protected:
+ void emitScopedNormalizedValue(raw_ostream &OS,
+ StringRef NormalizedValue) const {
+ if (!NormalizedValuesScope.empty())
+ OS << NormalizedValuesScope << "::";
+ OS << NormalizedValue;
+ }
+
+ virtual void emitSpecific(raw_ostream &OS) const = 0;
+ MarshallingKindInfo(const Record &R, const char *MacroName)
+ : R(R), MacroName(MacroName) {}
+};
+
+class MarshallingFlagInfo final : public MarshallingKindInfo {
+public:
+ bool IsPositive;
+
+ void emitSpecific(raw_ostream &OS) const override { OS << IsPositive; }
+
+ static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
+ std::unique_ptr<MarshallingFlagInfo> Ret(new MarshallingFlagInfo(R));
+ Ret->IsPositive = R.getValueAsBit("IsPositive");
+ return Ret;
+ }
+
+private:
+ MarshallingFlagInfo(const Record &R)
+ : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_FLAG") {}
+};
+
+class MarshallingStringInfo final : public MarshallingKindInfo {
+public:
+ StringRef NormalizerRetTy;
+ StringRef Normalizer;
+ StringRef Denormalizer;
+ int TableIndex = -1;
+ std::vector<StringRef> Values;
+ std::vector<StringRef> NormalizedValues;
+ std::string ValueTableName;
+
+ static constexpr const char *ValueTablePreamble = R"(
+struct SimpleEnumValue {
+ const char *Name;
+ unsigned Value;
+};
+
+struct SimpleEnumValueTable {
+ const SimpleEnumValue *Table;
+ unsigned Size;
+};
+)";
+
+ static constexpr const char *ValueTablesDecl =
+ "static const SimpleEnumValueTable SimpleEnumValueTables[] = ";
+
+ void emitSpecific(raw_ostream &OS) const override {
+ emitScopedNormalizedValue(OS, NormalizerRetTy);
+ OS << ", ";
+ OS << Normalizer;
+ OS << ", ";
+ OS << Denormalizer;
+ OS << ", ";
+ OS << TableIndex;
+ }
+
+ Optional<StringRef> emitValueTable(raw_ostream &OS) const override {
+ if (TableIndex == -1)
+ return {};
+ OS << "static const SimpleEnumValue " << ValueTableName << "[] = {\n";
+ for (unsigned I = 0, E = Values.size(); I != E; ++I) {
+ OS << "{";
+ write_cstring(OS, Values[I]);
+ OS << ",";
+ OS << "static_cast<unsigned>(";
+ emitScopedNormalizedValue(OS, NormalizedValues[I]);
+ OS << ")},";
+ }
+ OS << "};\n";
+ return StringRef(ValueTableName);
+ }
+
+ static std::unique_ptr<MarshallingKindInfo> create(const Record &R) {
+ assert(!isa<UnsetInit>(R.getValueInit("NormalizerRetTy")) &&
+ "String options must have a type");
+
+ std::unique_ptr<MarshallingStringInfo> Ret(new MarshallingStringInfo(R));
+ Ret->NormalizerRetTy = R.getValueAsString("NormalizerRetTy");
+
+ Ret->Normalizer = R.getValueAsString("Normalizer");
+ Ret->Denormalizer = R.getValueAsString("Denormalizer");
+
+ if (!isa<UnsetInit>(R.getValueInit("NormalizedValues"))) {
+ assert(!isa<UnsetInit>(R.getValueInit("Values")) &&
+ "Cannot provide normalized values for value-less options");
+ Ret->TableIndex = NextTableIndex++;
+ Ret->NormalizedValues = R.getValueAsListOfStrings("NormalizedValues");
+ Ret->Values.reserve(Ret->NormalizedValues.size());
+ Ret->ValueTableName = getOptionName(R) + "ValueTable";
+
+ StringRef ValuesStr = R.getValueAsString("Values");
+ for (;;) {
+ size_t Idx = ValuesStr.find(',');
+ if (Idx == StringRef::npos)
+ break;
+ if (Idx > 0)
+ Ret->Values.push_back(ValuesStr.slice(0, Idx));
+ ValuesStr = ValuesStr.slice(Idx + 1, StringRef::npos);
+ }
+ if (!ValuesStr.empty())
+ Ret->Values.push_back(ValuesStr);
+
+ assert(Ret->Values.size() == Ret->NormalizedValues.size() &&
+ "The number of normalized values doesn't match the number of "
+ "values");
+ }
+
+ return Ret;
+ }
+
+private:
+ MarshallingStringInfo(const Record &R)
+ : MarshallingKindInfo(R, "OPTION_WITH_MARSHALLING_STRING") {}
+
+ static size_t NextTableIndex;
+};
+
+size_t MarshallingStringInfo::NextTableIndex = 0;
+
+std::unique_ptr<MarshallingKindInfo>
+MarshallingKindInfo::create(const Record &R) {
+ assert(!isa<UnsetInit>(R.getValueInit("KeyPath")) &&
+ !isa<UnsetInit>(R.getValueInit("DefaultValue")) &&
+ "Must provide at least a key-path and a default value for emitting "
+ "marshalling information");
+
+ std::unique_ptr<MarshallingKindInfo> Ret = nullptr;
+ StringRef MarshallingKindStr = R.getValueAsString("MarshallingKind");
+
+ if (MarshallingKindStr == "flag")
+ Ret = MarshallingFlagInfo::create(R);
+ else if (MarshallingKindStr == "string")
+ Ret = MarshallingStringInfo::create(R);
+
+ Ret->ShouldAlwaysEmit = R.getValueAsBit("ShouldAlwaysEmit");
+ Ret->KeyPath = R.getValueAsString("KeyPath");
+ Ret->DefaultValue = R.getValueAsString("DefaultValue");
+ if (!isa<UnsetInit>(R.getValueInit("NormalizedValuesScope")))
+ Ret->NormalizedValuesScope = R.getValueAsString("NormalizedValuesScope");
+ return Ret;
+}
+
/// OptParserEmitter - This tablegen backend takes an input .td file
/// describing a list of options and emits a data structure for parsing and
/// working with those options when given an input command line.
@@ -102,7 +308,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << ", \"" << R.getValueAsString("Name") << '"';
// The option identifier name.
- OS << ", "<< getOptionName(R);
+ OS << ", " << getOptionName(R);
// The option kind.
OS << ", Group";
@@ -135,21 +341,17 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << "//////////\n";
OS << "// Options\n\n";
- for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
- const Record &R = *Opts[i];
-
- // Start a single option entry.
- OS << "OPTION(";
+ auto WriteOptRecordFields = [&](raw_ostream &OS, const Record &R) {
// The option prefix;
std::vector<StringRef> prf = R.getValueAsListOfStrings("Prefixes");
OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
// The option string.
- write_cstring(OS, R.getValueAsString("Name"));
+ emitNameUsingSpelling(OS, R);
// The option identifier name.
- OS << ", "<< getOptionName(R);
+ OS << ", " << getOptionName(R);
// The option kind.
OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
@@ -190,8 +392,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
int NumFlags = 0;
const ListInit *LI = R.getValueAsListInit("Flags");
for (Init *I : *LI)
- OS << (NumFlags++ ? " | " : "")
- << cast<DefInit>(I)->getDef()->getName();
+ OS << (NumFlags++ ? " | " : "") << cast<DefInit>(I)->getDef()->getName();
if (GroupFlags) {
for (Init *I : *GroupFlags)
OS << (NumFlags++ ? " | " : "")
@@ -224,11 +425,52 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
write_cstring(OS, R.getValueAsString("Values"));
else
OS << "nullptr";
+ };
+
+ std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
+ for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
+ const Record &R = *Opts[I];
+ // Start a single option entry.
+ OS << "OPTION(";
+ WriteOptRecordFields(OS, R);
OS << ")\n";
+ if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
+ OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
}
OS << "#endif // OPTION\n";
+ for (const auto &KindInfo : OptsWithMarshalling) {
+ OS << "#ifdef " << KindInfo->MacroName << "\n";
+ OS << KindInfo->MacroName << "(";
+ WriteOptRecordFields(OS, KindInfo->R);
+ OS << ", ";
+ KindInfo->emit(OS);
+ OS << ")\n";
+ OS << "#endif // " << KindInfo->MacroName << "\n";
+ }
+
+ OS << "\n";
+ OS << "#ifdef SIMPLE_ENUM_VALUE_TABLE";
+ OS << "\n";
+ OS << MarshallingStringInfo::ValueTablePreamble;
+ std::vector<StringRef> ValueTableNames;
+ for (const auto &KindInfo : OptsWithMarshalling)
+ if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
+ ValueTableNames.push_back(*MaybeValueTableName);
+
+ OS << MarshallingStringInfo::ValueTablesDecl << "{";
+ for (auto ValueTableName : ValueTableNames)
+ OS << "{" << ValueTableName << ", sizeof(" << ValueTableName
+ << ") / sizeof(SimpleEnumValue)"
+ << "},\n";
+ OS << "};\n";
+ OS << "static const unsigned SimpleEnumValueTablesSize = "
+ "sizeof(SimpleEnumValueTables) / sizeof(SimpleEnumValueTable);\n";
+
+ OS << "#endif // SIMPLE_ENUM_VALUE_TABLE\n";
+ OS << "\n";
+
OS << "\n";
OS << "#ifdef OPTTABLE_ARG_INIT\n";
OS << "//////////\n";
@@ -241,8 +483,9 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
OS << "bool ValuesWereAdded;\n";
OS << R.getValueAsString("ValuesCode");
OS << "\n";
- for (std::string S : R.getValueAsListOfStrings("Prefixes")) {
+ for (StringRef Prefix : R.getValueAsListOfStrings("Prefixes")) {
OS << "ValuesWereAdded = Opt.addValues(";
+ std::string S(Prefix);
S += R.getValueAsString("Name");
write_cstring(OS, S);
OS << ", Values);\n";
diff --git a/llvm/utils/TableGen/OptRSTEmitter.cpp b/llvm/utils/TableGen/OptRSTEmitter.cpp
index 3102f378bc1e..5e44d033109a 100644
--- a/llvm/utils/TableGen/OptRSTEmitter.cpp
+++ b/llvm/utils/TableGen/OptRSTEmitter.cpp
@@ -9,6 +9,7 @@
#include "OptEmitter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
diff --git a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
index 96e4f95937b2..f298e639bf7f 100644
--- a/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
+++ b/llvm/utils/TableGen/RISCVCompressInstEmitter.cpp
@@ -85,7 +85,7 @@ class RISCVCompressInstEmitter {
MapKind Kind;
union {
unsigned Operand; // Operand number mapped to.
- uint64_t Imm; // Integer immediate value.
+ int64_t Imm; // Integer immediate value.
Record *Reg; // Physical register.
} Data;
int TiedOpIdx = -1; // Tied operand index within the instruction.
@@ -141,7 +141,7 @@ bool RISCVCompressInstEmitter::validateRegister(Record *Reg, Record *RegClass) {
assert(Reg->isSubClassOf("Register") && "Reg record should be a Register\n");
assert(RegClass->isSubClassOf("RegisterClass") && "RegClass record should be"
" a RegisterClass\n");
- CodeGenRegisterClass RC = Target.getRegisterClass(RegClass);
+ const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass);
const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower());
assert((R != nullptr) &&
("Register" + Reg->getName().str() + " not defined!!\n").c_str());
@@ -160,8 +160,8 @@ bool RISCVCompressInstEmitter::validateTypes(Record *DagOpType,
if (DagOpType->isSubClassOf("RegisterClass") &&
InstOpType->isSubClassOf("RegisterClass")) {
- CodeGenRegisterClass RC = Target.getRegisterClass(InstOpType);
- CodeGenRegisterClass SubRC = Target.getRegisterClass(DagOpType);
+ const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType);
+ const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType);
return RC.hasSubClass(&SubRC);
}
@@ -474,19 +474,40 @@ void RISCVCompressInstEmitter::evaluateCompressPat(Record *Rec) {
SourceOperandMap, DestOperandMap));
}
-static void getReqFeatures(std::set<StringRef> &FeaturesSet,
- const std::vector<Record *> &ReqFeatures) {
+static void
+getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet,
+ std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets,
+ const std::vector<Record *> &ReqFeatures) {
for (auto &R : ReqFeatures) {
- StringRef AsmCondString = R->getValueAsString("AssemblerCondString");
-
- // AsmCondString has syntax [!]F(,[!]F)*
- SmallVector<StringRef, 4> Ops;
- SplitString(AsmCondString, Ops, ",");
- assert(!Ops.empty() && "AssemblerCondString cannot be empty");
- for (auto &Op : Ops) {
- assert(!Op.empty() && "Empty operator");
- FeaturesSet.insert(Op);
+ const DagInit *D = R->getValueAsDag("AssemblerCondDag");
+ std::string CombineType = D->getOperator()->getAsString();
+ if (CombineType != "any_of" && CombineType != "all_of")
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ if (D->getNumArgs() == 0)
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ bool IsOr = CombineType == "any_of";
+ std::set<std::pair<bool, StringRef>> AnyOfSet;
+
+ for (auto *Arg : D->getArgs()) {
+ bool IsNot = false;
+ if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
+ if (NotArg->getOperator()->getAsString() != "not" ||
+ NotArg->getNumArgs() != 1)
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ Arg = NotArg->getArg(0);
+ IsNot = true;
+ }
+ if (!isa<DefInit>(Arg) ||
+ !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
+ PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
+ if (IsOr)
+ AnyOfSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
+ else
+ FeaturesSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
}
+
+ if (IsOr)
+ AnyOfFeatureSets.insert(AnyOfSet);
}
}
@@ -547,7 +568,7 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
"'PassSubtarget' is false. SubTargetInfo object is needed "
"for target features.\n");
- std::string Namespace = Target.getName();
+ std::string Namespace = std::string(Target.getName());
// Sort entries in CompressPatterns to handle instructions that can have more
// than one candidate for compression\uncompression, e.g ADD can be
@@ -651,9 +672,10 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
CaseStream.indent(4) << "case " + Namespace + "::" + CurOp + ": {\n";
}
- std::set<StringRef> FeaturesSet;
+ std::set<std::pair<bool, StringRef>> FeaturesSet;
+ std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets;
// Add CompressPat required features.
- getReqFeatures(FeaturesSet, CompressPat.PatReqFeatures);
+ getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures);
// Add Dest instruction required features.
std::vector<Record *> ReqFeatures;
@@ -661,19 +683,28 @@ void RISCVCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) {
return R->getValueAsBit("AssemblerMatcherPredicate");
});
- getReqFeatures(FeaturesSet, ReqFeatures);
+ getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures);
// Emit checks for all required features.
for (auto &Op : FeaturesSet) {
- if (Op[0] == '!')
- CondStream.indent(6) << ("!STI.getFeatureBits()[" + Namespace +
- "::" + Op.substr(1) + "]")
- .str() +
- " &&\n";
- else
- CondStream.indent(6)
- << ("STI.getFeatureBits()[" + Namespace + "::" + Op + "]").str() +
- " &&\n";
+ StringRef Not = Op.first ? "!" : "";
+ CondStream.indent(6)
+ << Not << ("STI.getFeatureBits()[" + Namespace + "::" + Op.second + "]").str() +
+ " &&\n";
+ }
+
+ // Emit checks for all required feature groups.
+ for (auto &Set : AnyOfFeatureSets) {
+ CondStream.indent(6) << "(";
+ for (auto &Op : Set) {
+ bool isLast = &Op == &*Set.rbegin();
+ StringRef Not = Op.first ? "!" : "";
+ CondStream << Not << ("STI.getFeatureBits()[" + Namespace + "::" + Op.second +
+ "]").str();
+ if (!isLast)
+ CondStream << " || ";
+ }
+ CondStream << ") &&\n";
}
// Start Source Inst operands validation.
diff --git a/llvm/utils/TableGen/RegisterBankEmitter.cpp b/llvm/utils/TableGen/RegisterBankEmitter.cpp
index 7f6b3931d3de..586f857b1fb0 100644
--- a/llvm/utils/TableGen/RegisterBankEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterBankEmitter.cpp
@@ -19,6 +19,7 @@
#include "CodeGenHwModes.h"
#include "CodeGenRegisters.h"
+#include "CodeGenTarget.h"
#define DEBUG_TYPE "register-bank-emitter"
@@ -60,10 +61,10 @@ public:
/// Get the register classes listed in the RegisterBank.RegisterClasses field.
std::vector<const CodeGenRegisterClass *>
- getExplictlySpecifiedRegisterClasses(
- CodeGenRegBank &RegisterClassHierarchy) const {
+ getExplicitlySpecifiedRegisterClasses(
+ const CodeGenRegBank &RegisterClassHierarchy) const {
std::vector<const CodeGenRegisterClass *> RCs;
- for (const auto &RCDef : getDef().getValueAsListOfDefs("RegisterClasses"))
+ for (const auto *RCDef : getDef().getValueAsListOfDefs("RegisterClasses"))
RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef));
return RCs;
}
@@ -104,8 +105,8 @@ public:
class RegisterBankEmitter {
private:
+ CodeGenTarget Target;
RecordKeeper &Records;
- CodeGenRegBank RegisterClassHierarchy;
void emitHeader(raw_ostream &OS, const StringRef TargetName,
const std::vector<RegisterBank> &Banks);
@@ -115,8 +116,7 @@ private:
std::vector<RegisterBank> &Banks);
public:
- RegisterBankEmitter(RecordKeeper &R)
- : Records(R), RegisterClassHierarchy(Records, CodeGenHwModes(R)) {}
+ RegisterBankEmitter(RecordKeeper &R) : Target(R), Records(R) {}
void run(raw_ostream &OS);
};
@@ -167,8 +167,8 @@ void RegisterBankEmitter::emitBaseClassDefinition(
/// multiple times for a given class if there are multiple paths
/// to the class.
static void visitRegisterBankClasses(
- CodeGenRegBank &RegisterClassHierarchy, const CodeGenRegisterClass *RC,
- const Twine Kind,
+ const CodeGenRegBank &RegisterClassHierarchy,
+ const CodeGenRegisterClass *RC, const Twine Kind,
std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn,
SmallPtrSetImpl<const CodeGenRegisterClass *> &VisitedRCs) {
@@ -212,6 +212,7 @@ static void visitRegisterBankClasses(
void RegisterBankEmitter::emitBaseClassImplementation(
raw_ostream &OS, StringRef TargetName,
std::vector<RegisterBank> &Banks) {
+ const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
OS << "namespace llvm {\n"
<< "namespace " << TargetName << " {\n";
@@ -275,10 +276,8 @@ void RegisterBankEmitter::emitBaseClassImplementation(
}
void RegisterBankEmitter::run(raw_ostream &OS) {
- std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
- if (Targets.size() != 1)
- PrintFatalError("ERROR: Too many or too few subclasses of Target defined!");
- StringRef TargetName = Targets[0]->getName();
+ StringRef TargetName = Target.getName();
+ const CodeGenRegBank &RegisterClassHierarchy = Target.getRegBank();
std::vector<RegisterBank> Banks;
for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) {
@@ -286,7 +285,7 @@ void RegisterBankEmitter::run(raw_ostream &OS) {
RegisterBank Bank(*V);
for (const CodeGenRegisterClass *RC :
- Bank.getExplictlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+ Bank.getExplicitlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
visitRegisterBankClasses(
RegisterClassHierarchy, RC, "explicit",
[&Bank](const CodeGenRegisterClass *RC, StringRef Kind) {
@@ -301,14 +300,14 @@ void RegisterBankEmitter::run(raw_ostream &OS) {
}
// Warn about ambiguous MIR caused by register bank/class name clashes.
- for (const auto &Class : Records.getAllDerivedDefinitions("RegisterClass")) {
+ for (const auto &Class : RegisterClassHierarchy.getRegClasses()) {
for (const auto &Bank : Banks) {
- if (Bank.getName().lower() == Class->getName().lower()) {
+ if (Bank.getName().lower() == StringRef(Class.getName()).lower()) {
PrintWarning(Bank.getDef().getLoc(), "Register bank names should be "
"distinct from register classes "
"to avoid ambiguous MIR");
PrintNote(Bank.getDef().getLoc(), "RegisterBank was declared here");
- PrintNote(Class->getLoc(), "RegisterClass was declared here");
+ PrintNote(Class.getDef()->getLoc(), "RegisterClass was declared here");
}
}
}
diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index 2586ec671b2a..a615587efdee 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -173,7 +173,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
std::string Namespace = SubRegIndices.front().getNamespace();
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
- OS << "enum {\n NoSubRegister,\n";
+ OS << "enum : uint16_t {\n NoSubRegister,\n";
unsigned i = 0;
for (const auto &Idx : SubRegIndices)
OS << " " << Idx.getName() << ",\t// " << ++i << "\n";
@@ -182,6 +182,20 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "} // end namespace " << Namespace << "\n\n";
}
+ OS << "// Register pressure sets enum.\n";
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum RegisterPressureSets {\n";
+ unsigned NumSets = Bank.getNumRegPressureSets();
+ for (unsigned i = 0; i < NumSets; ++i ) {
+ const RegUnitSet &RegUnits = Bank.getRegSetAt(i);
+ OS << " " << RegUnits.Name << " = " << i << ",\n";
+ }
+ OS << "};\n";
+ if (!Namespace.empty())
+ OS << "} // end namespace " << Namespace << '\n';
+ OS << '\n';
+
OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
@@ -202,13 +216,13 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
<< " static const RegClassWeight RCWeightTable[] = {\n";
for (const auto &RC : RegBank.getRegClasses()) {
const CodeGenRegister::Vec &Regs = RC.getMembers();
+ OS << " {" << RC.getWeight(RegBank) << ", ";
if (Regs.empty() || RC.Artificial)
- OS << " {0, 0";
+ OS << '0';
else {
std::vector<unsigned> RegUnits;
RC.buildRegUnitSet(RegBank, RegUnits);
- OS << " {" << (*Regs.begin())->getWeight(RegBank)
- << ", " << RegBank.getRegUnitSetWeight(RegUnits);
+ OS << RegBank.getRegUnitSetWeight(RegUnits);
}
OS << "}, \t// " << RC.getName() << "\n";
}
@@ -897,7 +911,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
unsigned i = 0;
for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) {
const auto &Reg = *I;
- RegStrings.add(Reg.getName());
+ RegStrings.add(std::string(Reg.getName()));
// Compute the ordered sub-register list.
SetVector<const CodeGenRegister*> SR;
@@ -963,7 +977,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "namespace llvm {\n\n";
- const std::string &TargetName = Target.getName();
+ const std::string &TargetName = std::string(Target.getName());
// Emit the shared table of differential lists.
OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
@@ -992,9 +1006,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit the string table.
RegStrings.layout();
- OS << "extern const char " << TargetName << "RegStrings[] = {\n";
- RegStrings.emit(OS, printChar);
- OS << "};\n\n";
+ RegStrings.emitStringLiteralDef(OS, Twine("extern const char ") + TargetName +
+ "RegStrings[]");
OS << "extern const MCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
@@ -1003,7 +1016,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit the register descriptors now.
i = 0;
for (const auto &Reg : Regs) {
- OS << " { " << RegStrings.get(Reg.getName()) << ", "
+ OS << " { " << RegStrings.get(std::string(Reg.getName())) << ", "
<< DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i])
<< ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "
<< (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", "
@@ -1065,9 +1078,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "} // end anonymous namespace\n\n";
RegClassStrings.layout();
- OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
- RegClassStrings.emit(OS, printChar);
- OS << "};\n\n";
+ RegClassStrings.emitStringLiteralDef(
+ OS, Twine("extern const char ") + TargetName + "RegClassStrings[]");
OS << "extern const MCRegisterClass " << TargetName
<< "MCRegisterClasses[] = {\n";
@@ -1134,7 +1146,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "\n#ifdef GET_REGINFO_HEADER\n";
OS << "#undef GET_REGINFO_HEADER\n\n";
- const std::string &TargetName = Target.getName();
+ const std::string &TargetName = std::string(Target.getName());
std::string ClassName = TargetName + "GenRegisterInfo";
OS << "#include \"llvm/CodeGen/TargetRegisterInfo.h\"\n\n";
@@ -1430,7 +1442,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "} // end anonymous namespace\n";
// Emit extra information about registers.
- const std::string &TargetName = Target.getName();
+ const std::string &TargetName = std::string(Target.getName());
OS << "\nstatic const TargetRegisterInfoDesc "
<< TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
OS << " { 0, false },\n";
diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp
index cfe48eb1949d..326cb4e54edc 100644
--- a/llvm/utils/TableGen/SearchableTableEmitter.cpp
+++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -57,7 +57,7 @@ struct GenericField {
bool IsInstruction = false;
GenericEnum *Enum = nullptr;
- GenericField(StringRef Name) : Name(Name) {}
+ GenericField(StringRef Name) : Name(std::string(Name)) {}
};
struct SearchIndex {
@@ -114,13 +114,17 @@ private:
else if (BitInit *BI = dyn_cast<BitInit>(I))
return BI->getValue() ? "true" : "false";
else if (CodeInit *CI = dyn_cast<CodeInit>(I))
- return CI->getValue();
+ return std::string(CI->getValue());
else if (Field.IsIntrinsic)
return "Intrinsic::" + getIntrinsic(I).EnumName;
else if (Field.IsInstruction)
return I->getAsString();
- else if (Field.Enum)
- return Field.Enum->EntryMap[cast<DefInit>(I)->getDef()]->first;
+ else if (Field.Enum) {
+ auto *Entry = Field.Enum->EntryMap[cast<DefInit>(I)->getDef()];
+ if (!Entry)
+ PrintFatalError(Twine("Entry for field '") + Field.Name + "' is null");
+ return std::string(Entry->first);
+ }
PrintFatalError(Twine("invalid field type for field '") + Field.Name +
"', expected: string, bits, bit or code");
}
@@ -274,7 +278,7 @@ bool SearchableTableEmitter::compareBy(Record *LHS, Record *RHS,
void SearchableTableEmitter::emitIfdef(StringRef Guard, raw_ostream &OS) {
OS << "#ifdef " << Guard << "\n";
- PreprocessorGuards.insert(Guard);
+ PreprocessorGuards.insert(std::string(Guard));
}
/// Emit a generic enum.
@@ -542,7 +546,7 @@ SearchableTableEmitter::parseSearchIndex(GenericTable &Table, StringRef Name,
const std::vector<StringRef> &Key,
bool EarlyOut) {
auto Index = std::make_unique<SearchIndex>();
- Index->Name = Name;
+ Index->Name = std::string(Name);
Index->EarlyOut = EarlyOut;
for (const auto &FieldName : Key) {
@@ -595,10 +599,13 @@ void SearchableTableEmitter::collectEnumEntries(
void SearchableTableEmitter::collectTableEntries(
GenericTable &Table, const std::vector<Record *> &Items) {
+ if (Items.empty())
+ PrintWarning(Twine("Table '") + Table.Name + "' has no items");
+
for (auto EntryRec : Items) {
for (auto &Field : Table.Fields) {
auto TI = dyn_cast<TypedInit>(EntryRec->getValueInit(Field.Name));
- if (!TI) {
+ if (!TI || !TI->isComplete()) {
PrintFatalError(EntryRec->getLoc(),
Twine("Record '") + EntryRec->getName() +
"' in table '" + Table.Name +
@@ -623,6 +630,10 @@ void SearchableTableEmitter::collectTableEntries(
Record *IntrinsicClass = Records.getClass("Intrinsic");
Record *InstructionClass = Records.getClass("Instruction");
for (auto &Field : Table.Fields) {
+ if (!Field.RecType)
+ PrintFatalError(Twine("Cannot determine type of field '") + Field.Name +
+ "' in table '" + Table.Name + "'. Maybe it is not used?");
+
if (auto RecordTy = dyn_cast<RecordRecTy>(Field.RecType)) {
if (IntrinsicClass && RecordTy->isSubClassOf(IntrinsicClass))
Field.IsIntrinsic = true;
@@ -648,8 +659,8 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
ValueField = EnumRec->getValueAsString("ValueField");
auto Enum = std::make_unique<GenericEnum>();
- Enum->Name = EnumRec->getName();
- Enum->PreprocessorGuard = EnumRec->getName();
+ Enum->Name = std::string(EnumRec->getName());
+ Enum->PreprocessorGuard = std::string(EnumRec->getName());
StringRef FilterClass = EnumRec->getValueAsString("FilterClass");
Enum->Class = Records.getClass(FilterClass);
@@ -665,9 +676,9 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
for (auto TableRec : Records.getAllDerivedDefinitions("GenericTable")) {
auto Table = std::make_unique<GenericTable>();
- Table->Name = TableRec->getName();
- Table->PreprocessorGuard = TableRec->getName();
- Table->CppTypeName = TableRec->getValueAsString("CppTypeName");
+ Table->Name = std::string(TableRec->getName());
+ Table->PreprocessorGuard = std::string(TableRec->getName());
+ Table->CppTypeName = std::string(TableRec->getValueAsString("CppTypeName"));
std::vector<StringRef> Fields = TableRec->getValueAsListOfStrings("Fields");
for (const auto &FieldName : Fields) {
@@ -746,10 +757,10 @@ void SearchableTableEmitter::run(raw_ostream &OS) {
auto Table = std::make_unique<GenericTable>();
Table->Name = (Twine(Class->getName()) + "sList").str();
Table->PreprocessorGuard = Class->getName().upper();
- Table->CppTypeName = Class->getName();
+ Table->CppTypeName = std::string(Class->getName());
for (const RecordVal &Field : Class->getValues()) {
- std::string FieldName = Field.getName();
+ std::string FieldName = std::string(Field.getName());
// Skip uninteresting fields: either special to us, or injected
// template parameters (if they contain a ':').
diff --git a/llvm/utils/TableGen/SequenceToOffsetTable.h b/llvm/utils/TableGen/SequenceToOffsetTable.h
index 327da39f4774..41cdefdb1949 100644
--- a/llvm/utils/TableGen/SequenceToOffsetTable.h
+++ b/llvm/utils/TableGen/SequenceToOffsetTable.h
@@ -15,6 +15,7 @@
#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H
#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -23,6 +24,61 @@
#include <map>
namespace llvm {
+extern llvm::cl::opt<bool> EmitLongStrLiterals;
+
+// Helper function for SequenceToOffsetTable<string>.
+static inline void printStrLitEscChar(raw_ostream &OS, char C) {
+ const char *Escapes[] = {
+ "\\000", "\\001", "\\002", "\\003", "\\004", "\\005", "\\006", "\\007",
+ "\\010", "\\t", "\\n", "\\013", "\\014", "\\r", "\\016", "\\017",
+ "\\020", "\\021", "\\022", "\\023", "\\024", "\\025", "\\026", "\\027",
+ "\\030", "\\031", "\\032", "\\033", "\\034", "\\035", "\\036", "\\037",
+ " ", "!", "\\\"", "#", "$", "%", "&", "'",
+ "(", ")", "*", "+", ",", "-", ".", "/",
+ "0", "1", "2", "3", "4", "5", "6", "7",
+ "8", "9", ":", ";", "<", "=", ">", "?",
+ "@", "A", "B", "C", "D", "E", "F", "G",
+ "H", "I", "J", "K", "L", "M", "N", "O",
+ "P", "Q", "R", "S", "T", "U", "V", "W",
+ "X", "Y", "Z", "[", "\\\\", "]", "^", "_",
+ "`", "a", "b", "c", "d", "e", "f", "g",
+ "h", "i", "j", "k", "l", "m", "n", "o",
+ "p", "q", "r", "s", "t", "u", "v", "w",
+ "x", "y", "z", "{", "|", "}", "~", "\\177",
+ "\\200", "\\201", "\\202", "\\203", "\\204", "\\205", "\\206", "\\207",
+ "\\210", "\\211", "\\212", "\\213", "\\214", "\\215", "\\216", "\\217",
+ "\\220", "\\221", "\\222", "\\223", "\\224", "\\225", "\\226", "\\227",
+ "\\230", "\\231", "\\232", "\\233", "\\234", "\\235", "\\236", "\\237",
+ "\\240", "\\241", "\\242", "\\243", "\\244", "\\245", "\\246", "\\247",
+ "\\250", "\\251", "\\252", "\\253", "\\254", "\\255", "\\256", "\\257",
+ "\\260", "\\261", "\\262", "\\263", "\\264", "\\265", "\\266", "\\267",
+ "\\270", "\\271", "\\272", "\\273", "\\274", "\\275", "\\276", "\\277",
+ "\\300", "\\301", "\\302", "\\303", "\\304", "\\305", "\\306", "\\307",
+ "\\310", "\\311", "\\312", "\\313", "\\314", "\\315", "\\316", "\\317",
+ "\\320", "\\321", "\\322", "\\323", "\\324", "\\325", "\\326", "\\327",
+ "\\330", "\\331", "\\332", "\\333", "\\334", "\\335", "\\336", "\\337",
+ "\\340", "\\341", "\\342", "\\343", "\\344", "\\345", "\\346", "\\347",
+ "\\350", "\\351", "\\352", "\\353", "\\354", "\\355", "\\356", "\\357",
+ "\\360", "\\361", "\\362", "\\363", "\\364", "\\365", "\\366", "\\367",
+ "\\370", "\\371", "\\372", "\\373", "\\374", "\\375", "\\376", "\\377"};
+
+ static_assert(sizeof Escapes / sizeof Escapes[0] ==
+ std::numeric_limits<unsigned char>::max() + 1,
+ "unsupported character type");
+ OS << Escapes[static_cast<unsigned char>(C)];
+}
+
+static inline void printChar(raw_ostream &OS, char C) {
+ unsigned char UC(C);
+ if (isalnum(UC) || ispunct(UC)) {
+ OS << '\'';
+ if (C == '\\' || C == '\'')
+ OS << '\\';
+ OS << C << '\'';
+ } else {
+ OS << unsigned(UC);
+ }
+}
/// SequenceToOffsetTable - Collect a number of terminated sequences of T.
/// Compute the layout of a table that contains all the sequences, possibly by
@@ -108,6 +164,37 @@ public:
return I->second + (I->first.size() - Seq.size());
}
+ /// `emitStringLiteralDef` - Print out the table as the body of an array
+ /// initializer, where each element is a C string literal terminated by
+ /// `\0`. Falls back to emitting a comma-separated integer list if
+ /// `EmitLongStrLiterals` is false
+ void emitStringLiteralDef(raw_ostream &OS, const llvm::Twine &Decl) const {
+ assert(Entries && "Call layout() before emitStringLiteralDef()");
+ if (EmitLongStrLiterals) {
+ OS << "\n#ifdef __GNUC__\n"
+ << "#pragma GCC diagnostic push\n"
+ << "#pragma GCC diagnostic ignored \"-Woverlength-strings\"\n"
+ << "#endif\n"
+ << Decl << " = {\n";
+ } else {
+ OS << Decl << " = {\n";
+ emit(OS, printChar, "0");
+ OS << "\n};\n\n";
+ return;
+ }
+ for (auto I : Seqs) {
+ OS << " /* " << I.second << " */ \"";
+ for (auto C : I.first) {
+ printStrLitEscChar(OS, C);
+ }
+ OS << "\\0\"\n";
+ }
+ OS << "};\n"
+ << "#ifdef __GNUC__\n"
+ << "#pragma GCC diagnostic pop\n"
+ << "#endif\n\n";
+ }
+
/// emit - Print out the table as the body of an array initializer.
/// Use the Print function to print elements.
void emit(raw_ostream &OS,
@@ -127,19 +214,6 @@ public:
}
};
-// Helper function for SequenceToOffsetTable<string>.
-static inline void printChar(raw_ostream &OS, char C) {
- unsigned char UC(C);
- if (isalnum(UC) || ispunct(UC)) {
- OS << '\'';
- if (C == '\\' || C == '\'')
- OS << '\\';
- OS << C << '\'';
- } else {
- OS << unsigned(UC);
- }
-}
-
} // end namespace llvm
#endif
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 9b094adb7d5c..68ee839c43ba 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -128,8 +128,8 @@ class SubtargetEmitter {
public:
SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT)
- : TGT(TGT), Records(R), SchedModels(TGT.getSchedModels()),
- Target(TGT.getName()) {}
+ : TGT(TGT), Records(R), SchedModels(TGT.getSchedModels()),
+ Target(TGT.getName()) {}
void run(raw_ostream &o);
};
@@ -396,8 +396,8 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
<< "namespace " << Name << "FU {\n";
for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
- OS << " const unsigned " << FUs[j]->getName()
- << " = 1 << " << j << ";\n";
+ OS << " const InstrStage::FuncUnits " << FUs[j]->getName()
+ << " = 1ULL << " << j << ";\n";
OS << "} // end namespace " << Name << "FU\n";
@@ -460,7 +460,8 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
std::string ItinStageString;
unsigned NStages = 0;
if (ItinData)
- FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
+ FormItineraryStageString(std::string(Name), ItinData, ItinStageString,
+ NStages);
// Get string and operand cycle count
std::string ItinOperandCycleString;
@@ -470,7 +471,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
NOperandCycles);
- FormItineraryBypassString(Name, ItinData, ItinBypassString,
+ FormItineraryBypassString(std::string(Name), ItinData, ItinBypassString,
NOperandCycles);
}
diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
index 5430f73d5e09..3821f4757464 100644
--- a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
+++ b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
@@ -119,33 +119,43 @@ void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
const SubtargetFeatureInfo &SFI = SF.second;
OS << " if (";
- std::string CondStorage =
- SFI.TheDef->getValueAsString("AssemblerCondString");
- StringRef Conds = CondStorage;
- std::pair<StringRef, StringRef> Comma = Conds.split(',');
- bool First = true;
- do {
- if (!First)
- OS << " && ";
-
- bool Neg = false;
- StringRef Cond = Comma.first;
- if (Cond[0] == '!') {
- Neg = true;
- Cond = Cond.substr(1);
- }
+ const DagInit *D = SFI.TheDef->getValueAsDag("AssemblerCondDag");
+ std::string CombineType = D->getOperator()->getAsString();
+ if (CombineType != "any_of" && CombineType != "all_of")
+ PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
+ if (D->getNumArgs() == 0)
+ PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
+ bool IsOr = CombineType == "any_of";
+
+ if (IsOr)
OS << "(";
- if (Neg)
- OS << "!";
- OS << "FB[" << TargetName << "::" << Cond << "])";
- if (Comma.second.empty())
- break;
+ bool First = true;
+ for (auto *Arg : D->getArgs()) {
+ if (!First) {
+ if (IsOr)
+ OS << " || ";
+ else
+ OS << " && ";
+ }
+ if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
+ if (NotArg->getOperator()->getAsString() != "not" ||
+ NotArg->getNumArgs() != 1)
+ PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
+ Arg = NotArg->getArg(0);
+ OS << "!";
+ }
+ if (!isa<DefInit>(Arg) ||
+ !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
+ PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
+ OS << "FB[" << TargetName << "::" << Arg->getAsString() << "]";
First = false;
- Comma = Comma.second.split(',');
- } while (true);
+ }
+
+ if (IsOr)
+ OS << ")";
OS << ")\n";
OS << " Features.set(" << SFI.getEnumBitName() << ");\n";
diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp
index bdb963c15d32..8015a58471ca 100644
--- a/llvm/utils/TableGen/TableGen.cpp
+++ b/llvm/utils/TableGen/TableGen.cpp
@@ -54,12 +54,21 @@ enum ActionType {
GenRegisterBank,
GenExegesis,
GenAutomata,
+ GenDirectivesEnumDecl,
+ GenDirectivesEnumImpl,
+ GenDirectivesEnumGen,
};
namespace llvm {
/// Storage for TimeRegionsOpt as a global so that backends aren't required to
/// include CommandLine.h
bool TimeRegions = false;
+cl::opt<bool> EmitLongStrLiterals(
+ "long-string-literals",
+ cl::desc("when emitting large string tables, prefer string literals over "
+ "comma-separated char literals. This can be a readability and "
+ "compile-time performance win, but upsets some compilers"),
+ cl::Hidden, cl::init(true));
} // end namespace llvm
namespace {
@@ -122,7 +131,13 @@ cl::opt<ActionType> Action(
"Generate registers bank descriptions"),
clEnumValN(GenExegesis, "gen-exegesis",
"Generate llvm-exegesis tables"),
- clEnumValN(GenAutomata, "gen-automata", "Generate generic automata")));
+ clEnumValN(GenAutomata, "gen-automata", "Generate generic automata"),
+ clEnumValN(GenDirectivesEnumDecl, "gen-directive-decl",
+ "Generate directive related declaration code (header file)"),
+ clEnumValN(GenDirectivesEnumImpl, "gen-directive-impl",
+ "Generate directive related implementation code"),
+ clEnumValN(GenDirectivesEnumGen, "gen-directive-gen",
+ "Generate directive related implementation code part")));
cl::OptionCategory PrintEnumsCat("Options for -print-enums");
cl::opt<std::string> Class("class", cl::desc("Print Enum list for this class"),
@@ -247,6 +262,15 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenAutomata:
EmitAutomata(Records, OS);
break;
+ case GenDirectivesEnumDecl:
+ EmitDirectivesDecl(Records, OS);
+ break;
+ case GenDirectivesEnumImpl:
+ EmitDirectivesImpl(Records, OS);
+ break;
+ case GenDirectivesEnumGen:
+ EmitDirectivesGen(Records, OS);
+ break;
}
return false;
diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h
index 9eef77a4577f..92204f39f8fa 100644
--- a/llvm/utils/TableGen/TableGenBackends.h
+++ b/llvm/utils/TableGen/TableGenBackends.h
@@ -90,6 +90,9 @@ void EmitX86FoldTables(RecordKeeper &RK, raw_ostream &OS);
void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS);
void EmitExegesis(RecordKeeper &RK, raw_ostream &OS);
void EmitAutomata(RecordKeeper &RK, raw_ostream &OS);
+void EmitDirectivesDecl(RecordKeeper &RK, raw_ostream &OS);
+void EmitDirectivesImpl(RecordKeeper &RK, raw_ostream &OS);
+void EmitDirectivesGen(RecordKeeper &RK, raw_ostream &OS);
} // End llvm namespace
diff --git a/llvm/utils/TableGen/X86DisassemblerTables.cpp b/llvm/utils/TableGen/X86DisassemblerTables.cpp
index 5dc653ac3806..76e4fd9a13ee 100644
--- a/llvm/utils/TableGen/X86DisassemblerTables.cpp
+++ b/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -669,7 +669,7 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) {
// Empty table.
- o2 << "{ " << stringForDecisionType(dt) << ", 0 }";
+ o2 << "{" << stringForDecisionType(dt) << ", 0}";
return;
}
@@ -708,18 +708,17 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
EntryNumber = ModRMTableNum;
ModRMTableNum += ModRMDecision.size();
- o1 << "/* Table" << EntryNumber << " */\n";
+ o1 << "/*Table" << EntryNumber << "*/\n";
i1++;
for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
E = ModRMDecision.end(); I != E; ++I) {
- o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
- << InstructionSpecifiers[*I].name << " */\n";
+ o1.indent(i1 * 2) << format("0x%hx", *I) << ", /*"
+ << InstructionSpecifiers[*I].name << "*/\n";
}
i1--;
}
- o2 << "{ " << stringForDecisionType(dt) << ", " << EntryNumber << " /* Table"
- << EntryNumber << " */ }";
+ o2 << "{" << stringForDecisionType(dt) << ", " << EntryNumber << "}";
switch (dt) {
default:
@@ -769,11 +768,10 @@ void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
o2 << "},\n";
} else {
o2 << " /* struct OpcodeDecision */ {\n";
- ++i2;
for (index = 0; index < 256; ++index) {
o2.indent(i2);
- o2 << "/* 0x" << format("%02hhx", index) << " */ ";
+ o2 << "/*0x" << format("%02hhx", index) << "*/";
emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
opDecision.modRMDecisions[index]);
@@ -783,7 +781,6 @@ void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
o2 << "\n";
}
- --i2;
o2.indent(i2) << "}\n";
--i2;
o2.indent(i2) << "},\n";
@@ -795,24 +792,20 @@ void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &ModRMTableNum,
ContextDecision &decision,
const char* name) const {
- o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
- i2++;
- o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
+ o2.indent(i2) << "static const struct ContextDecision " << name << " = {{/* opcodeDecisions */\n";
i2++;
for (unsigned index = 0; index < IC_max; ++index) {
- o2.indent(i2) << "/* ";
+ o2.indent(i2) << "/*";
o2 << stringForContext((InstructionContext)index);
- o2 << " */ ";
+ o2 << "*/ ";
emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
decision.opcodeDecisions[index]);
}
i2--;
- o2.indent(i2) << "}" << "\n";
- i2--;
- o2.indent(i2) << "};" << "\n";
+ o2.indent(i2) << "}};" << "\n";
}
void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
@@ -976,9 +969,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
else
o << "IC";
- o << ", /* " << index << " */";
-
- o << "\n";
+ o << ", // " << index << "\n";
}
i--;
@@ -1021,7 +1012,7 @@ void DisassemblerTables::emit(raw_ostream &o) const {
std::vector<unsigned> EmptyTable(1, 0);
ModRMTable[EmptyTable] = ModRMTableNum;
ModRMTableNum += EmptyTable.size();
- o1 << "/* EmptyTable */\n";
+ o1 << "/*EmptyTable*/\n";
o1.indent(i1 * 2) << "0x0,\n";
i1--;
emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
diff --git a/llvm/utils/TableGen/X86ModRMFilters.cpp b/llvm/utils/TableGen/X86ModRMFilters.cpp
index 98e6fb6104d7..cf7507094fa7 100644
--- a/llvm/utils/TableGen/X86ModRMFilters.cpp
+++ b/llvm/utils/TableGen/X86ModRMFilters.cpp
@@ -18,4 +18,6 @@ void ModFilter::anchor() { }
void ExtendedFilter::anchor() { }
+void ExtendedRMFilter::anchor() { }
+
void ExactFilter::anchor() { }
diff --git a/llvm/utils/TableGen/X86ModRMFilters.h b/llvm/utils/TableGen/X86ModRMFilters.h
index c77b4c21aec4..f0b8af5fb82a 100644
--- a/llvm/utils/TableGen/X86ModRMFilters.h
+++ b/llvm/utils/TableGen/X86ModRMFilters.h
@@ -108,6 +108,29 @@ public:
}
};
+/// ExtendedRMFilter - Extended opcodes are classified based on the value of the
+/// mod field [bits 7-6] and the value of the nnn field [bits 2-0].
+class ExtendedRMFilter : public ModRMFilter {
+ void anchor() override;
+ bool R;
+ uint8_t NNN;
+public:
+ /// Constructor
+ ///
+ /// \param r True if the mod field must be set to 11; false otherwise.
+ /// The name is explained at ModFilter.
+ /// \param nnn The required value of the nnn field.
+ ExtendedRMFilter(bool r, uint8_t nnn) :
+ ModRMFilter(),
+ R(r),
+ NNN(nnn) {
+ }
+
+ bool accepts(uint8_t modRM) const override {
+ return ((R && ((modRM & 0xc0) == 0xc0)) &&
+ ((modRM & 0x7) == NNN));
+ }
+};
/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR)
/// requires the ModR/M byte to have a specific value.
class ExactFilter : public ModRMFilter {
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index 1048ef81a378..84f6d5210d74 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -65,7 +65,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
UID = uid;
Rec = insn.TheDef;
- Name = Rec->getName();
+ Name = std::string(Rec->getName());
Spec = &tables.specForUID(UID);
if (!Rec->isSubClassOf("X86Inst")) {
@@ -94,7 +94,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
CD8_Scale = byteFromRec(Rec, "CD8_Scale");
- Name = Rec->getName();
+ Name = std::string(Rec->getName());
Operands = &insn.Operands.OperandList;
@@ -352,10 +352,13 @@ void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) {
// The scaling factor for AVX512 compressed displacement encoding is an
// instruction attribute. Adjust the ModRM encoding type to include the
// scale for compressed displacement.
- if ((encoding != ENCODING_RM && encoding != ENCODING_VSIB) ||CD8_Scale == 0)
+ if ((encoding != ENCODING_RM &&
+ encoding != ENCODING_VSIB &&
+ encoding != ENCODING_SIB) ||CD8_Scale == 0)
return;
encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale));
assert(((encoding >= ENCODING_RM && encoding <= ENCODING_RM_CD64) ||
+ (encoding == ENCODING_SIB) ||
(encoding >= ENCODING_VSIB && encoding <= ENCODING_VSIB_CD64)) &&
"Invalid CDisp scaling");
}
@@ -383,12 +386,12 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
StringRef typeName = (*Operands)[operandIndex].Rec->getName();
- OperandEncoding encoding = encodingFromString(typeName, OpSize);
+ OperandEncoding encoding = encodingFromString(std::string(typeName), OpSize);
// Adjust the encoding type for an operand based on the instruction.
adjustOperandEncoding(encoding);
Spec->operands[operandIndex].encoding = encoding;
- Spec->operands[operandIndex].type = typeFromString(typeName,
- HasREX_WPrefix, OpSize);
+ Spec->operands[operandIndex].type =
+ typeFromString(std::string(typeName), HasREX_WPrefix, OpSize);
++operandIndex;
++physicalOperandIndex;
@@ -459,6 +462,8 @@ void RecognizableInstr::emitInstructionSpecifier() {
switch (Form) {
default: llvm_unreachable("Unhandled form");
+ case X86Local::PrefixByte:
+ return;
case X86Local::RawFrmSrc:
HANDLE_OPERAND(relocation);
return;
@@ -517,6 +522,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMDestMem:
+ case X86Local::MRMDestMemFSIB:
// Operand 1 is a memory operand (possibly SIB-extended)
// Operand 2 is a register operand in the Reg/Opcode field.
// - In AVX, there is a register operand in the VEX.vvvv field here -
@@ -587,6 +593,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPERAND(opcodeModifier)
break;
case X86Local::MRMSrcMem:
+ case X86Local::MRMSrcMemFSIB:
// Operand 1 is a register operand in the Reg/Opcode field.
// Operand 2 is a memory operand (possibly SIB-extended)
// - In AVX, there is a register operand in the VEX.vvvv field here -
@@ -639,6 +646,10 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPERAND(rmRegister)
HANDLE_OPERAND(opcodeModifier)
break;
+ case X86Local::MRMr0:
+ // Operand 1 is a register operand in the R/M field.
+ HANDLE_OPERAND(roRegister)
+ break;
case X86Local::MRMXr:
case X86Local::MRM0r:
case X86Local::MRM1r:
@@ -706,6 +717,14 @@ void RecognizableInstr::emitInstructionSpecifier() {
HANDLE_OPERAND(immediate)
HANDLE_OPERAND(immediate)
break;
+ case X86Local::MRM0X:
+ case X86Local::MRM1X:
+ case X86Local::MRM2X:
+ case X86Local::MRM3X:
+ case X86Local::MRM4X:
+ case X86Local::MRM5X:
+ case X86Local::MRM6X:
+ case X86Local::MRM7X:
#define MAP(from, to) case X86Local::MRM_##from:
X86_INSTR_MRM_MAPPING
#undef MAP
@@ -749,6 +768,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::RawFrmImm8:
case X86Local::RawFrmImm16:
case X86Local::AddCCFrm:
+ case X86Local::PrefixByte:
filter = std::make_unique<DumbFilter>();
break;
case X86Local::MRMDestReg:
@@ -761,7 +781,9 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
filter = std::make_unique<ModFilter>(true);
break;
case X86Local::MRMDestMem:
+ case X86Local::MRMDestMemFSIB:
case X86Local::MRMSrcMem:
+ case X86Local::MRMSrcMemFSIB:
case X86Local::MRMSrcMem4VOp3:
case X86Local::MRMSrcMemOp4:
case X86Local::MRMSrcMemCC:
@@ -775,6 +797,15 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::MRM6r: case X86Local::MRM7r:
filter = std::make_unique<ExtendedFilter>(true, Form - X86Local::MRM0r);
break;
+ case X86Local::MRM0X: case X86Local::MRM1X:
+ case X86Local::MRM2X: case X86Local::MRM3X:
+ case X86Local::MRM4X: case X86Local::MRM5X:
+ case X86Local::MRM6X: case X86Local::MRM7X:
+ filter = std::make_unique<ExtendedFilter>(true, Form - X86Local::MRM0X);
+ break;
+ case X86Local::MRMr0:
+ filter = std::make_unique<ExtendedRMFilter>(true, Form - X86Local::MRMr0);
+ break;
case X86Local::MRM0m: case X86Local::MRM1m:
case X86Local::MRM2m: case X86Local::MRM3m:
case X86Local::MRM4m: case X86Local::MRM5m:
@@ -894,6 +925,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i64imm", TYPE_IMM)
TYPE("anymem", TYPE_M)
TYPE("opaquemem", TYPE_M)
+ TYPE("sibmem", TYPE_MSIB)
TYPE("SEGMENT_REG", TYPE_SEGMENTREG)
TYPE("DEBUG_REG", TYPE_DEBUGREG)
TYPE("CONTROL_REG", TYPE_CONTROLREG)
@@ -952,6 +984,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("vz256mem", TYPE_MVSIBZ)
TYPE("vz512mem", TYPE_MVSIBZ)
TYPE("BNDR", TYPE_BNDR)
+ TYPE("TILE", TYPE_TMM)
errs() << "Unhandled type string " << s << "\n";
llvm_unreachable("Unhandled type string");
}
@@ -991,6 +1024,7 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s,
ENCODING("VR128X", ENCODING_IB)
ENCODING("VR256X", ENCODING_IB)
ENCODING("VR512", ENCODING_IB)
+ ENCODING("TILE", ENCODING_IB)
errs() << "Unhandled immediate encoding " << s << "\n";
llvm_unreachable("Unhandled immediate encoding");
}
@@ -1029,6 +1063,7 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
ENCODING("VK8PAIR", ENCODING_RM)
ENCODING("VK16PAIR", ENCODING_RM)
ENCODING("BNDR", ENCODING_RM)
+ ENCODING("TILE", ENCODING_RM)
errs() << "Unhandled R/M register encoding " << s << "\n";
llvm_unreachable("Unhandled R/M register encoding");
}
@@ -1075,6 +1110,7 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
ENCODING("VK32WM", ENCODING_REG)
ENCODING("VK64WM", ENCODING_REG)
ENCODING("BNDR", ENCODING_REG)
+ ENCODING("TILE", ENCODING_REG)
errs() << "Unhandled reg/opcode register encoding " << s << "\n";
llvm_unreachable("Unhandled reg/opcode register encoding");
}
@@ -1106,6 +1142,7 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s,
ENCODING("VK4PAIR", ENCODING_VVVV)
ENCODING("VK8PAIR", ENCODING_VVVV)
ENCODING("VK16PAIR", ENCODING_VVVV)
+ ENCODING("TILE", ENCODING_VVVV)
errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
llvm_unreachable("Unhandled VEX.vvvv register encoding");
}
@@ -1146,6 +1183,7 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s,
ENCODING("lea64mem", ENCODING_RM)
ENCODING("anymem", ENCODING_RM)
ENCODING("opaquemem", ENCODING_RM)
+ ENCODING("sibmem", ENCODING_SIB)
ENCODING("vx64mem", ENCODING_VSIB)
ENCODING("vx128mem", ENCODING_VSIB)
ENCODING("vx256mem", ENCODING_VSIB)
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.h b/llvm/utils/TableGen/X86RecognizableInstr.h
index b15bef4e1931..a7b88b4d12ed 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -102,22 +102,28 @@ namespace X86Local {
RawFrmImm8 = 7,
RawFrmImm16 = 8,
AddCCFrm = 9,
- MRMDestMem = 32,
- MRMSrcMem = 33,
- MRMSrcMem4VOp3 = 34,
- MRMSrcMemOp4 = 35,
- MRMSrcMemCC = 36,
- MRMXmCC = 38, MRMXm = 39,
- MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43,
- MRM4m = 44, MRM5m = 45, MRM6m = 46, MRM7m = 47,
- MRMDestReg = 48,
- MRMSrcReg = 49,
- MRMSrcReg4VOp3 = 50,
- MRMSrcRegOp4 = 51,
- MRMSrcRegCC = 52,
- MRMXrCC = 54, MRMXr = 55,
- MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59,
- MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63,
+ PrefixByte = 10,
+ MRMr0 = 21,
+ MRMSrcMemFSIB = 22,
+ MRMDestMemFSIB = 23,
+ MRMDestMem = 24,
+ MRMSrcMem = 25,
+ MRMSrcMem4VOp3 = 26,
+ MRMSrcMemOp4 = 27,
+ MRMSrcMemCC = 28,
+ MRMXmCC = 30, MRMXm = 31,
+ MRM0m = 32, MRM1m = 33, MRM2m = 34, MRM3m = 35,
+ MRM4m = 36, MRM5m = 37, MRM6m = 38, MRM7m = 39,
+ MRMDestReg = 40,
+ MRMSrcReg = 41,
+ MRMSrcReg4VOp3 = 42,
+ MRMSrcRegOp4 = 43,
+ MRMSrcRegCC = 44,
+ MRMXrCC = 46, MRMXr = 47,
+ MRM0r = 48, MRM1r = 49, MRM2r = 50, MRM3r = 51,
+ MRM4r = 52, MRM5r = 53, MRM6r = 54, MRM7r = 55,
+ MRM0X = 56, MRM1X = 57, MRM2X = 58, MRM3X = 59,
+ MRM4X = 60, MRM5X = 61, MRM6X = 62, MRM7X = 63,
#define MAP(from, to) MRM_##from = to,
X86_INSTR_MRM_MAPPING
#undef MAP