diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 847a1c0b818..6cddc6d5b84 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -92,54 +92,6 @@ static cl::opt MatchPrefix("match-prefix", cl::init(""), cl::desc("Only match instructions with the given prefix")); -/// FlattenVariants - Flatten an .td file assembly string by selecting the -/// variant at index \arg N. -static std::string FlattenVariants(const std::string &AsmString, - unsigned N) { - StringRef Cur = AsmString; - std::string Res = ""; - - for (;;) { - // Find the start of the next variant string. - size_t VariantsStart = 0; - for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) - if (Cur[VariantsStart] == '{' && - (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && - Cur[VariantsStart-1] != '\\'))) - break; - - // Add the prefix to the result. - Res += Cur.slice(0, VariantsStart); - if (VariantsStart == Cur.size()) - break; - - ++VariantsStart; // Skip the '{'. - - // Scan to the end of the variants string. - size_t VariantsEnd = VariantsStart; - unsigned NestedBraces = 1; - for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { - if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { - if (--NestedBraces == 0) - break; - } else if (Cur[VariantsEnd] == '{') - ++NestedBraces; - } - - // Select the Nth variant (or empty). - StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); - for (unsigned i = 0; i != N; ++i) - Selection = Selection.split('|').second; - Res += Selection.split('|').first; - - assert(VariantsEnd != Cur.size() && - "Unterminated variants in assembly string!"); - Cur = Cur.substr(VariantsEnd + 1); - } - - return Res; -} - /// TokenizeAsmString - Tokenize a simplified assembly string. static void TokenizeAsmString(StringRef AsmString, SmallVectorImpl &Tokens) { @@ -516,7 +468,6 @@ struct InstructionInfo { return !(HasLT ^ HasGT); } -public: void dump(); }; @@ -932,7 +883,8 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) { II->InstrName = CGI.TheDef->getName(); II->Instr = &CGI; - II->AsmString = FlattenVariants(CGI.AsmString, 0); + // TODO: Eventually support asmparser for Variant != 0. + II->AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, 0); // Remove comments from the asm string. We know that the asmstring only // has one line. @@ -944,7 +896,8 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) { TokenizeAsmString(II->AsmString, II->Tokens); - // Ignore instructions which shouldn't be matched. + // Ignore instructions which shouldn't be matched and diagnose invalid + // instruction definitions with an error. if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens)) continue; diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index b2228b037dd..7989406d6fa 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -53,8 +53,6 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, int OperandSpacing) { this->CGI = &CGI; - unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #. - // This is the number of tabs we've seen if we're doing columnar layout. unsigned CurColumn = 0; @@ -62,54 +60,48 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, // NOTE: Any extensions to this code need to be mirrored in the // AsmPrinter::printInlineAsm code that executes as compile time (assuming // that inline asm strings should also get the new feature)! - const std::string &AsmString = CGI.AsmString; + std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant); std::string::size_type LastEmitted = 0; while (LastEmitted != AsmString.size()) { std::string::size_type DollarPos = - AsmString.find_first_of("${|}\\", LastEmitted); + AsmString.find_first_of("$\\", LastEmitted); if (DollarPos == std::string::npos) DollarPos = AsmString.size(); // Emit a constant string fragment. - if (DollarPos != LastEmitted) { - if (CurVariant == Variant || CurVariant == ~0U) { - for (; LastEmitted != DollarPos; ++LastEmitted) - switch (AsmString[LastEmitted]) { - case '\n': - AddLiteralString("\\n"); - break; - case '\t': - // If the asm writer is not using a columnar layout, \t is not - // magic. - if (FirstOperandColumn == -1 || OperandSpacing == -1) { - AddLiteralString("\\t"); - } else { - // We recognize a tab as an operand delimeter. - unsigned DestColumn = FirstOperandColumn + - CurColumn++ * OperandSpacing; - Operands.push_back( - AsmWriterOperand( - "O.PadToColumn(" + - utostr(DestColumn) + ");\n", - AsmWriterOperand::isLiteralStatementOperand)); - } - break; - case '"': - AddLiteralString("\\\""); - break; - case '\\': - AddLiteralString("\\\\"); - break; - default: - AddLiteralString(std::string(1, AsmString[LastEmitted])); - break; - } - } else { - LastEmitted = DollarPos; - } + for (; LastEmitted != DollarPos; ++LastEmitted) + switch (AsmString[LastEmitted]) { + case '\n': + AddLiteralString("\\n"); + break; + case '\t': + // If the asm writer is not using a columnar layout, \t is not + // magic. + if (FirstOperandColumn == -1 || OperandSpacing == -1) { + AddLiteralString("\\t"); + } else { + // We recognize a tab as an operand delimeter. + unsigned DestColumn = FirstOperandColumn + + CurColumn++ * OperandSpacing; + Operands.push_back( + AsmWriterOperand( + "O.PadToColumn(" + + utostr(DestColumn) + ");\n", + AsmWriterOperand::isLiteralStatementOperand)); + } + break; + case '"': + AddLiteralString("\\\""); + break; + case '\\': + AddLiteralString("\\\\"); + break; + default: + AddLiteralString(std::string(1, AsmString[LastEmitted])); + break; + } } else if (AsmString[DollarPos] == '\\') { - if (DollarPos+1 != AsmString.size() && - (CurVariant == Variant || CurVariant == ~0U)) { + if (DollarPos+1 != AsmString.size()) { if (AsmString[DollarPos+1] == 'n') { AddLiteralString("\\n"); } else if (AsmString[DollarPos+1] == 't') { @@ -137,29 +129,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, LastEmitted = DollarPos+2; continue; } - } else if (AsmString[DollarPos] == '{') { - if (CurVariant != ~0U) - throw "Nested variants found for instruction '" + - CGI.TheDef->getName() + "'!"; - LastEmitted = DollarPos+1; - CurVariant = 0; // We are now inside of the variant! - } else if (AsmString[DollarPos] == '|') { - if (CurVariant == ~0U) - throw "'|' character found outside of a variant in instruction '" - + CGI.TheDef->getName() + "'!"; - ++CurVariant; - ++LastEmitted; - } else if (AsmString[DollarPos] == '}') { - if (CurVariant == ~0U) - throw "'}' character found outside of a variant in instruction '" - + CGI.TheDef->getName() + "'!"; - ++LastEmitted; - CurVariant = ~0U; } else if (DollarPos+1 != AsmString.size() && AsmString[DollarPos+1] == '$') { - if (CurVariant == Variant || CurVariant == ~0U) { - AddLiteralString("$"); // "$$" -> $ - } + AddLiteralString("$"); // "$$" -> $ LastEmitted = DollarPos+2; } else { // Get the name of the variable. @@ -229,13 +201,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned OpNo = CGI.getOperandNamed(VarName); CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; - if (CurVariant == Variant || CurVariant == ~0U) { - unsigned MIOp = OpInfo.MIOperandNo; - Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, - OpNo, - MIOp, - Modifier)); - } + unsigned MIOp = OpInfo.MIOperandNo; + Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, + OpNo, MIOp, Modifier)); } LastEmitted = VarEnd; } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 6e71502cbc2..f7b45e243a4 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -321,3 +321,52 @@ HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const { return MVT::Other; } + +/// FlattenAsmStringVariants - Flatten the specified AsmString to only +/// include text from the specified variant, returning the new string. +std::string CodeGenInstruction:: +FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { + std::string Res = ""; + + for (;;) { + // Find the start of the next variant string. + size_t VariantsStart = 0; + for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) + if (Cur[VariantsStart] == '{' && + (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && + Cur[VariantsStart-1] != '\\'))) + break; + + // Add the prefix to the result. + Res += Cur.slice(0, VariantsStart); + if (VariantsStart == Cur.size()) + break; + + ++VariantsStart; // Skip the '{'. + + // Scan to the end of the variants string. + size_t VariantsEnd = VariantsStart; + unsigned NestedBraces = 1; + for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { + if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { + if (--NestedBraces == 0) + break; + } else if (Cur[VariantsEnd] == '{') + ++NestedBraces; + } + + // Select the Nth variant (or empty). + StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); + for (unsigned i = 0; i != Variant; ++i) + Selection = Selection.split('|').second; + Res += Selection.split('|').first; + + assert(VariantsEnd != Cur.size() && + "Unterminated variants in assembly string!"); + Cur = Cur.substr(VariantsEnd + 1); + } + + return Res; +} + + diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index e895361d69c..93d1ce1ddfd 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -23,6 +23,7 @@ namespace llvm { class Record; class DagInit; class CodeGenTarget; + class StringRef; class CodeGenInstruction { public: @@ -201,6 +202,12 @@ namespace llvm { /// MVT::Other. MVT::SimpleValueType HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; + + + /// FlattenAsmStringVariants - Flatten the specified AsmString to only + /// include text from the specified variant, returning the new string. + static std::string FlattenAsmStringVariants(StringRef AsmString, + unsigned Variant); }; }