summaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/AsmWriterEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/AsmWriterEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/AsmWriterEmitter.cpp123
1 files changed, 83 insertions, 40 deletions
diff --git a/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 58c0d32d44eb9..d10ea71e97e3f 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";
}