move FlattenVariants out of AsmMatcherEmitter into a shared

CodeGenInstruction::FlattenAsmStringVariants method.  Use it
to simplify the code in AsmWriterInst, which now no longer 
needs to worry about variants.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@117886 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-11-01 01:07:14 +00:00
parent 52de0ef922
commit 4d43d0fd99
4 changed files with 98 additions and 121 deletions

View File

@ -92,54 +92,6 @@ static cl::opt<std::string>
MatchPrefix("match-prefix", cl::init(""), MatchPrefix("match-prefix", cl::init(""),
cl::desc("Only match instructions with the given prefix")); 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. /// TokenizeAsmString - Tokenize a simplified assembly string.
static void TokenizeAsmString(StringRef AsmString, static void TokenizeAsmString(StringRef AsmString,
SmallVectorImpl<StringRef> &Tokens) { SmallVectorImpl<StringRef> &Tokens) {
@ -516,7 +468,6 @@ struct InstructionInfo {
return !(HasLT ^ HasGT); return !(HasLT ^ HasGT);
} }
public:
void dump(); void dump();
}; };
@ -932,7 +883,8 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
II->InstrName = CGI.TheDef->getName(); II->InstrName = CGI.TheDef->getName();
II->Instr = &CGI; 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 // Remove comments from the asm string. We know that the asmstring only
// has one line. // has one line.
@ -944,7 +896,8 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
TokenizeAsmString(II->AsmString, II->Tokens); 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)) if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens))
continue; continue;

View File

@ -53,8 +53,6 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
int OperandSpacing) { int OperandSpacing) {
this->CGI = &CGI; 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. // This is the number of tabs we've seen if we're doing columnar layout.
unsigned CurColumn = 0; unsigned CurColumn = 0;
@ -62,54 +60,48 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
// NOTE: Any extensions to this code need to be mirrored in the // NOTE: Any extensions to this code need to be mirrored in the
// AsmPrinter::printInlineAsm code that executes as compile time (assuming // AsmPrinter::printInlineAsm code that executes as compile time (assuming
// that inline asm strings should also get the new feature)! // 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; std::string::size_type LastEmitted = 0;
while (LastEmitted != AsmString.size()) { while (LastEmitted != AsmString.size()) {
std::string::size_type DollarPos = std::string::size_type DollarPos =
AsmString.find_first_of("${|}\\", LastEmitted); AsmString.find_first_of("$\\", LastEmitted);
if (DollarPos == std::string::npos) DollarPos = AsmString.size(); if (DollarPos == std::string::npos) DollarPos = AsmString.size();
// Emit a constant string fragment. // Emit a constant string fragment.
if (DollarPos != LastEmitted) { if (DollarPos != LastEmitted) {
if (CurVariant == Variant || CurVariant == ~0U) { for (; LastEmitted != DollarPos; ++LastEmitted)
for (; LastEmitted != DollarPos; ++LastEmitted) switch (AsmString[LastEmitted]) {
switch (AsmString[LastEmitted]) { case '\n':
case '\n': AddLiteralString("\\n");
AddLiteralString("\\n"); break;
break; case '\t':
case '\t': // If the asm writer is not using a columnar layout, \t is not
// If the asm writer is not using a columnar layout, \t is not // magic.
// magic. if (FirstOperandColumn == -1 || OperandSpacing == -1) {
if (FirstOperandColumn == -1 || OperandSpacing == -1) { AddLiteralString("\\t");
AddLiteralString("\\t"); } else {
} else { // We recognize a tab as an operand delimeter.
// We recognize a tab as an operand delimeter. unsigned DestColumn = FirstOperandColumn +
unsigned DestColumn = FirstOperandColumn + CurColumn++ * OperandSpacing;
CurColumn++ * OperandSpacing; Operands.push_back(
Operands.push_back( AsmWriterOperand(
AsmWriterOperand( "O.PadToColumn(" +
"O.PadToColumn(" + utostr(DestColumn) + ");\n",
utostr(DestColumn) + ");\n", AsmWriterOperand::isLiteralStatementOperand));
AsmWriterOperand::isLiteralStatementOperand)); }
} break;
break; case '"':
case '"': AddLiteralString("\\\"");
AddLiteralString("\\\""); break;
break; case '\\':
case '\\': AddLiteralString("\\\\");
AddLiteralString("\\\\"); break;
break; default:
default: AddLiteralString(std::string(1, AsmString[LastEmitted]));
AddLiteralString(std::string(1, AsmString[LastEmitted])); break;
break; }
}
} else {
LastEmitted = DollarPos;
}
} else if (AsmString[DollarPos] == '\\') { } else if (AsmString[DollarPos] == '\\') {
if (DollarPos+1 != AsmString.size() && if (DollarPos+1 != AsmString.size()) {
(CurVariant == Variant || CurVariant == ~0U)) {
if (AsmString[DollarPos+1] == 'n') { if (AsmString[DollarPos+1] == 'n') {
AddLiteralString("\\n"); AddLiteralString("\\n");
} else if (AsmString[DollarPos+1] == 't') { } else if (AsmString[DollarPos+1] == 't') {
@ -137,29 +129,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
LastEmitted = DollarPos+2; LastEmitted = DollarPos+2;
continue; 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() && } else if (DollarPos+1 != AsmString.size() &&
AsmString[DollarPos+1] == '$') { AsmString[DollarPos+1] == '$') {
if (CurVariant == Variant || CurVariant == ~0U) { AddLiteralString("$"); // "$$" -> $
AddLiteralString("$"); // "$$" -> $
}
LastEmitted = DollarPos+2; LastEmitted = DollarPos+2;
} else { } else {
// Get the name of the variable. // Get the name of the variable.
@ -229,13 +201,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
unsigned OpNo = CGI.getOperandNamed(VarName); unsigned OpNo = CGI.getOperandNamed(VarName);
CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
if (CurVariant == Variant || CurVariant == ~0U) { unsigned MIOp = OpInfo.MIOperandNo;
unsigned MIOp = OpInfo.MIOperandNo; Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, OpNo, MIOp, Modifier));
OpNo,
MIOp,
Modifier));
}
} }
LastEmitted = VarEnd; LastEmitted = VarEnd;
} }

View File

@ -321,3 +321,52 @@ HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
return MVT::Other; 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;
}

View File

@ -23,6 +23,7 @@ namespace llvm {
class Record; class Record;
class DagInit; class DagInit;
class CodeGenTarget; class CodeGenTarget;
class StringRef;
class CodeGenInstruction { class CodeGenInstruction {
public: public:
@ -201,6 +202,12 @@ namespace llvm {
/// MVT::Other. /// MVT::Other.
MVT::SimpleValueType MVT::SimpleValueType
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; 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);
}; };
} }