aboutsummaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-11-02 17:30:52 +0000
committerChris Lattner <sabre@nondot.org>2010-11-02 17:30:52 +0000
commitd19ec05e0785152e7a520ffd4a88da4459a380aa (patch)
tree910b9edaff10f1e2b6933b1f6f1536e6abe8a3c1 /utils
parent3ff57094a7d176a759ddb1e1668489d89064f56c (diff)
downloadexternal_llvm-d19ec05e0785152e7a520ffd4a88da4459a380aa.zip
external_llvm-d19ec05e0785152e7a520ffd4a88da4459a380aa.tar.gz
external_llvm-d19ec05e0785152e7a520ffd4a88da4459a380aa.tar.bz2
refactor/cleanup MatchableInfo by eliminating the Tokens array,
merging it into a Token field in Operand, and moving the first token to an explicit mnemonic field. These were parallel arrays before (except for the mnemonic) which kept confusing me. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118024 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp253
1 files changed, 127 insertions, 126 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index b9345d3..dccbaf7 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -93,82 +93,6 @@ static cl::opt<std::string>
MatchPrefix("match-prefix", cl::init(""),
cl::desc("Only match instructions with the given prefix"));
-/// TokenizeAsmString - Tokenize a simplified assembly string.
-static void TokenizeAsmString(StringRef AsmString,
- SmallVectorImpl<StringRef> &Tokens) {
- unsigned Prev = 0;
- bool InTok = true;
- for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
- switch (AsmString[i]) {
- case '[':
- case ']':
- case '*':
- case '!':
- case ' ':
- case '\t':
- case ',':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- if (!isspace(AsmString[i]) && AsmString[i] != ',')
- Tokens.push_back(AsmString.substr(i, 1));
- Prev = i + 1;
- break;
-
- case '\\':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- ++i;
- assert(i != AsmString.size() && "Invalid quoted character");
- Tokens.push_back(AsmString.substr(i, 1));
- Prev = i + 1;
- break;
-
- case '$': {
- // If this isn't "${", treat like a normal token.
- if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') {
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- Prev = i;
- break;
- }
-
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
-
- StringRef::iterator End =
- std::find(AsmString.begin() + i, AsmString.end(), '}');
- assert(End != AsmString.end() && "Missing brace in operand reference!");
- size_t EndPos = End - AsmString.begin();
- Tokens.push_back(AsmString.slice(i, EndPos+1));
- Prev = EndPos + 1;
- i = EndPos;
- break;
- }
-
- case '.':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- }
- Prev = i;
- InTok = true;
- break;
-
- default:
- InTok = true;
- }
- }
- if (InTok && Prev != AsmString.size())
- Tokens.push_back(AsmString.substr(Prev));
-}
-
namespace {
class AsmMatcherInfo;
@@ -324,14 +248,16 @@ public:
/// instruction or alias which is capable of being matched.
struct MatchableInfo {
struct Operand {
+ /// Token - This is the token that the operand came from.
+ StringRef Token;
+
/// The unique class instance this operand should match.
ClassInfo *Class;
/// The original operand this corresponds to, if any.
const CGIOperandList::OperandInfo *OperandInfo;
- Operand(ClassInfo *C, const CGIOperandList::OperandInfo *OpInfo)
- : Class(C), OperandInfo(OpInfo) {}
+ explicit Operand(StringRef T) : Token(T), Class(0), OperandInfo(0) {}
};
/// InstrName - The target name for this instruction.
@@ -344,9 +270,10 @@ struct MatchableInfo {
/// removed).
std::string AsmString;
- /// Tokens - The tokenized assembly pattern that this instruction matches.
- SmallVector<StringRef, 4> Tokens;
-
+ /// Mnemonic - This is the first token of the matched instruction, its
+ /// mnemonic.
+ StringRef Mnemonic;
+
/// AsmOperands - The textual operands that this instruction matches,
/// including literal tokens for the mnemonic, etc.
SmallVector<Operand, 4> AsmOperands;
@@ -382,16 +309,16 @@ struct MatchableInfo {
/// and perform a bunch of validity checking.
bool Validate(StringRef CommentDelimiter, bool Hack) const;
- /// getSingletonRegisterForToken - If the specified token is a singleton
+ /// getSingletonRegisterForAsmOperand - If the specified token is a singleton
/// register, return the Record for it, otherwise return null.
- Record *getSingletonRegisterForToken(unsigned i,
- const AsmMatcherInfo &Info) const;
+ Record *getSingletonRegisterForAsmOperand(unsigned i,
+ const AsmMatcherInfo &Info) const;
/// operator< - Compare two matchables.
bool operator<(const MatchableInfo &RHS) const {
// The primary comparator is the instruction mnemonic.
- if (Tokens[0] != RHS.Tokens[0])
- return Tokens[0] < RHS.Tokens[0];
+ if (Mnemonic != RHS.Mnemonic)
+ return Mnemonic < RHS.Mnemonic;
if (AsmOperands.size() != RHS.AsmOperands.size())
return AsmOperands.size() < RHS.AsmOperands.size();
@@ -413,7 +340,7 @@ struct MatchableInfo {
/// strictly superior match).
bool CouldMatchAmiguouslyWith(const MatchableInfo &RHS) {
// The primary comparator is the instruction mnemonic.
- if (Tokens[0] != RHS.Tokens[0])
+ if (Mnemonic != RHS.Mnemonic)
return false;
// The number of operands is unambiguous.
@@ -448,6 +375,9 @@ struct MatchableInfo {
}
void dump();
+
+private:
+ void TokenizeAsmString(const AsmMatcherInfo &Info);
};
/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
@@ -535,20 +465,13 @@ public:
}
void MatchableInfo::dump() {
- errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
- << ", tokens:[";
- for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
- errs() << Tokens[i];
- if (i + 1 != e)
- errs() << ", ";
- }
- errs() << "]\n";
+ errs() << InstrName << " -- " << "flattened:\"" << AsmString << "\"\n";
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
Operand &Op = AsmOperands[i];
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
if (Op.Class->Kind == ClassInfo::Token) {
- errs() << '\"' << Tokens[i] << "\"\n";
+ errs() << '\"' << Op.Token << "\"\n";
continue;
}
@@ -568,7 +491,7 @@ void MatchableInfo::Initialize(const AsmMatcherInfo &Info,
// TODO: Eventually support asmparser for Variant != 0.
AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, 0);
- TokenizeAsmString(AsmString, Tokens);
+ TokenizeAsmString(Info);
// Compute the require features.
std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates");
@@ -578,12 +501,98 @@ void MatchableInfo::Initialize(const AsmMatcherInfo &Info,
RequiredFeatures.push_back(Feature);
// Collect singleton registers, if used.
- for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
- if (Record *Reg = getSingletonRegisterForToken(i, Info))
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ if (Record *Reg = getSingletonRegisterForAsmOperand(i, Info))
SingletonRegisters.insert(Reg);
}
}
+/// TokenizeAsmString - Tokenize a simplified assembly string.
+void MatchableInfo::TokenizeAsmString(const AsmMatcherInfo &Info) {
+ StringRef String = AsmString;
+ unsigned Prev = 0;
+ bool InTok = true;
+ for (unsigned i = 0, e = String.size(); i != e; ++i) {
+ switch (String[i]) {
+ case '[':
+ case ']':
+ case '*':
+ case '!':
+ case ' ':
+ case '\t':
+ case ',':
+ if (InTok) {
+ AsmOperands.push_back(Operand(String.slice(Prev, i)));
+ InTok = false;
+ }
+ if (!isspace(String[i]) && String[i] != ',')
+ AsmOperands.push_back(Operand(String.substr(i, 1)));
+ Prev = i + 1;
+ break;
+
+ case '\\':
+ if (InTok) {
+ AsmOperands.push_back(Operand(String.slice(Prev, i)));
+ InTok = false;
+ }
+ ++i;
+ assert(i != String.size() && "Invalid quoted character");
+ AsmOperands.push_back(Operand(String.substr(i, 1)));
+ Prev = i + 1;
+ break;
+
+ case '$': {
+ // If this isn't "${", treat like a normal token.
+ if (i + 1 == String.size() || String[i + 1] != '{') {
+ if (InTok) {
+ AsmOperands.push_back(Operand(String.slice(Prev, i)));
+ InTok = false;
+ }
+ Prev = i;
+ break;
+ }
+
+ if (InTok) {
+ AsmOperands.push_back(Operand(String.slice(Prev, i)));
+ InTok = false;
+ }
+
+ StringRef::iterator End = std::find(String.begin() + i, String.end(),'}');
+ assert(End != String.end() && "Missing brace in operand reference!");
+ size_t EndPos = End - String.begin();
+ AsmOperands.push_back(Operand(String.slice(i, EndPos+1)));
+ Prev = EndPos + 1;
+ i = EndPos;
+ break;
+ }
+
+ case '.':
+ if (InTok)
+ AsmOperands.push_back(Operand(String.slice(Prev, i)));
+ Prev = i;
+ InTok = true;
+ break;
+
+ default:
+ InTok = true;
+ }
+ }
+ if (InTok && Prev != String.size())
+ AsmOperands.push_back(Operand(String.substr(Prev)));
+
+ // The first token of the instruction is the mnemonic, which must be a
+ // simple string, not a $foo variable or a singleton register.
+ assert(!AsmOperands.empty() && "Instruction has no tokens?");
+ Mnemonic = AsmOperands[0].Token;
+ if (Mnemonic[0] == '$' || getSingletonRegisterForAsmOperand(0, Info))
+ throw TGError(TheDef->getLoc(),
+ "Invalid instruction mnemonic '" + Mnemonic.str() + "'!");
+
+ // Remove the first operand, it is tracked in the mnemonic field.
+ AsmOperands.erase(AsmOperands.begin());
+}
+
+
/// getRegisterRecord - Get the register record for \arg name, or 0.
static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
@@ -623,24 +632,25 @@ bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const {
// Also, check for instructions which reference the operand multiple times;
// this implies a constraint we would not honor.
std::set<std::string> OperandNames;
- for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
- if (Tokens[i][0] == '$' && Tokens[i].find(':') != StringRef::npos)
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ StringRef Tok = AsmOperands[i].Token;
+ if (Tok[0] == '$' && Tok.find(':') != StringRef::npos)
throw TGError(TheDef->getLoc(),
- "matchable with operand modifier '" + Tokens[i].str() +
+ "matchable with operand modifier '" + Tok.str() +
"' not supported by asm matcher. Mark isCodeGenOnly!");
// Verify that any operand is only mentioned once.
- if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
+ if (Tok[0] == '$' && !OperandNames.insert(Tok).second) {
if (!Hack)
throw TGError(TheDef->getLoc(),
- "ERROR: matchable with tied operand '" + Tokens[i].str() +
+ "ERROR: matchable with tied operand '" + Tok.str() +
"' can never be matched!");
// FIXME: Should reject these. The ARM backend hits this with $lane in a
// bunch of instructions. It is unclear what the right answer is.
DEBUG({
errs() << "warning: '" << InstrName << "': "
<< "ignoring instruction with tied operand '"
- << Tokens[i].str() << "'\n";
+ << Tok.str() << "'\n";
});
return false;
}
@@ -650,11 +660,11 @@ bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const {
}
-/// getSingletonRegisterForToken - If the specified token is a singleton
+/// getSingletonRegisterForAsmOperand - If the specified token is a singleton
/// register, return the register name, otherwise return a null StringRef.
Record *MatchableInfo::
-getSingletonRegisterForToken(unsigned i, const AsmMatcherInfo &Info) const {
- StringRef Tok = Tokens[i];
+getSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info) const{
+ StringRef Tok = AsmOperands[i].Token;
if (!Tok.startswith(Info.RegisterPrefix))
return 0;
@@ -1000,31 +1010,22 @@ void AsmMatcherInfo::BuildInfo() {
ie = Matchables.end(); it != ie; ++it) {
MatchableInfo *II = *it;
- // The first token of the instruction is the mnemonic, which must be a
- // simple string, not a $foo variable or a singleton register.
- assert(!II->Tokens.empty() && "Instruction has no tokens?");
- StringRef Mnemonic = II->Tokens[0];
- if (Mnemonic[0] == '$' || II->getSingletonRegisterForToken(0, *this))
- throw TGError(II->TheDef->getLoc(),
- "Invalid instruction mnemonic '" + Mnemonic.str() + "'!");
-
// Parse the tokens after the mnemonic.
- for (unsigned i = 1, e = II->Tokens.size(); i != e; ++i) {
- StringRef Token = II->Tokens[i];
+ for (unsigned i = 0, e = II->AsmOperands.size(); i != e; ++i) {
+ MatchableInfo::Operand &Op = II->AsmOperands[i];
+ StringRef Token = Op.Token;
// Check for singleton registers.
- if (Record *RegRecord = II->getSingletonRegisterForToken(i, *this)) {
- MatchableInfo::Operand Op(RegisterClasses[RegRecord], 0);
+ if (Record *RegRecord = II->getSingletonRegisterForAsmOperand(i, *this)) {
+ Op.Class = RegisterClasses[RegRecord];
assert(Op.Class && Op.Class->Registers.size() == 1 &&
"Unexpected class for singleton register");
- II->AsmOperands.push_back(Op);
continue;
}
// Check for simple tokens.
if (Token[0] != '$') {
- II->AsmOperands.push_back(MatchableInfo::Operand(getTokenClass(Token),
- 0));
+ Op.Class = getTokenClass(Token);
continue;
}
@@ -1061,8 +1062,8 @@ void AsmMatcherInfo::BuildInfo() {
assert(OI && "Unable to find tied operand target!");
}
- II->AsmOperands.push_back(MatchableInfo::Operand(getOperandClass(Token,
- *OI), OI));
+ Op.Class = getOperandClass(Token, *OI);
+ Op.OperandInfo = OI;
}
}
@@ -1749,7 +1750,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
MatchableInfo &II = **it;
OS << " { " << Target.getName() << "::" << II.InstrName
- << ", \"" << II.Tokens[0] << "\""
+ << ", \"" << II.Mnemonic << "\""
<< ", " << II.ConversionFnKind << ", { ";
for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
MatchableInfo::Operand &Op = II.AsmOperands[i];