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(""),
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<StringRef> &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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
};
}