summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-01-06 20:01:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-01-06 20:01:02 +0000
commit8a6c1c25bce0267ee4072bd7b786b921e8a66a35 (patch)
treeea70b740d40cffe568a990c7aecd1acb5f83f786 /utils
parent84fe440ded1bfc237d720c49408b36798d67ceff (diff)
downloadsrc-test2-8a6c1c25bce0267ee4072bd7b786b921e8a66a35.tar.gz
src-test2-8a6c1c25bce0267ee4072bd7b786b921e8a66a35.zip
Notes
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp307
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp28
-rw-r--r--utils/TableGen/TableGen.cpp3
3 files changed, 186 insertions, 152 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 4177388840be..6e9a9484dc88 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -493,7 +493,8 @@ struct MatchableInfo {
void initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
- AsmVariantInfo const &Variant);
+ AsmVariantInfo const &Variant,
+ bool HasMnemonicFirst);
/// validate - Return true if this matchable is a valid thing to match against
/// and perform a bunch of validity checking.
@@ -502,20 +503,21 @@ struct MatchableInfo {
/// findAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
int findAsmOperand(StringRef N, int SubOpIdx) const {
- for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
- if (N == AsmOperands[i].SrcOpName &&
- SubOpIdx == AsmOperands[i].SubOpIdx)
- return i;
- return -1;
+ auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(),
+ [&](const AsmOperand &Op) {
+ return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
+ });
+ return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
}
/// findAsmOperandNamed - Find the first AsmOperand with the specified name.
/// This does not check the suboperand index.
int findAsmOperandNamed(StringRef N) const {
- for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
- if (N == AsmOperands[i].SrcOpName)
- return i;
- return -1;
+ auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(),
+ [&](const AsmOperand &Op) {
+ return Op.SrcOpName == N;
+ });
+ return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
}
void buildInstructionResultOperands();
@@ -587,7 +589,7 @@ struct MatchableInfo {
HasGT = true;
}
- return !(HasLT ^ HasGT);
+ return HasLT == HasGT;
}
void dump() const;
@@ -595,8 +597,7 @@ struct MatchableInfo {
private:
void tokenizeAsmString(AsmMatcherInfo const &Info,
AsmVariantInfo const &Variant);
- void addAsmOperand(size_t Start, size_t End,
- std::string const &SeparatorCharacters);
+ void addAsmOperand(StringRef Token, bool IsIsolatedToken = false);
};
/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
@@ -837,7 +838,8 @@ extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
void MatchableInfo::initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
- AsmVariantInfo const &Variant) {
+ AsmVariantInfo const &Variant,
+ bool HasMnemonicFirst) {
AsmVariantID = Variant.AsmVariantNo;
AsmString =
CodeGenInstruction::FlattenAsmStringVariants(AsmString,
@@ -845,6 +847,24 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info,
tokenizeAsmString(Info, Variant);
+ // The first token of the instruction is the mnemonic, which must be a
+ // simple string, not a $foo variable or a singleton register.
+ if (AsmOperands.empty())
+ PrintFatalError(TheDef->getLoc(),
+ "Instruction '" + TheDef->getName() + "' has no tokens");
+
+ assert(!AsmOperands[0].Token.empty());
+ if (HasMnemonicFirst) {
+ Mnemonic = AsmOperands[0].Token;
+ if (Mnemonic[0] == '$')
+ PrintFatalError(TheDef->getLoc(),
+ "Invalid instruction mnemonic '" + Mnemonic + "'!");
+
+ // Remove the first operand, it is tracked in the mnemonic field.
+ AsmOperands.erase(AsmOperands.begin());
+ } else if (AsmOperands[0].Token[0] != '$')
+ Mnemonic = AsmOperands[0].Token;
+
// Compute the require features.
for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates"))
if (const SubtargetFeatureInfo *Feature =
@@ -867,16 +887,8 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info,
}
/// Append an AsmOperand for the given substring of AsmString.
-void MatchableInfo::addAsmOperand(size_t Start, size_t End,
- std::string const &Separators) {
- StringRef String = AsmString;
- // Look for separators before and after to figure out is this token is
- // isolated. Accept '$$' as that's how we escape '$'.
- bool IsIsolatedToken =
- (!Start || Separators.find(String[Start - 1]) != StringRef::npos ||
- String.substr(Start - 1, 2) == "$$") &&
- (End >= String.size() || Separators.find(String[End]) != StringRef::npos);
- AsmOperands.push_back(AsmOperand(IsIsolatedToken, String.slice(Start, End)));
+void MatchableInfo::addAsmOperand(StringRef Token, bool IsIsolatedToken) {
+ AsmOperands.push_back(AsmOperand(IsIsolatedToken, Token));
}
/// tokenizeAsmString - Tokenize a simplified assembly string.
@@ -885,50 +897,58 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,
StringRef String = AsmString;
size_t Prev = 0;
bool InTok = false;
- std::string Separators = Variant.TokenizingCharacters +
- Variant.SeparatorCharacters;
+ bool IsIsolatedToken = true;
for (size_t i = 0, e = String.size(); i != e; ++i) {
- if(Variant.BreakCharacters.find(String[i]) != std::string::npos) {
- if(InTok) {
- addAsmOperand(Prev, i, Separators);
+ char Char = String[i];
+ if (Variant.BreakCharacters.find(Char) != std::string::npos) {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), false);
Prev = i;
+ IsIsolatedToken = false;
}
InTok = true;
continue;
}
- if(Variant.TokenizingCharacters.find(String[i]) != std::string::npos) {
- if(InTok) {
- addAsmOperand(Prev, i, Separators);
+ if (Variant.TokenizingCharacters.find(Char) != std::string::npos) {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
InTok = false;
+ IsIsolatedToken = false;
}
- addAsmOperand(i, i + 1, Separators);
+ addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);
Prev = i + 1;
+ IsIsolatedToken = true;
continue;
}
- if(Variant.SeparatorCharacters.find(String[i]) != std::string::npos) {
- if(InTok) {
- addAsmOperand(Prev, i, Separators);
+ if (Variant.SeparatorCharacters.find(Char) != std::string::npos) {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
InTok = false;
}
Prev = i + 1;
+ IsIsolatedToken = true;
continue;
}
- switch (String[i]) {
+
+ switch (Char) {
case '\\':
if (InTok) {
- addAsmOperand(Prev, i, Separators);
+ addAsmOperand(String.slice(Prev, i), false);
InTok = false;
+ IsIsolatedToken = false;
}
++i;
assert(i != String.size() && "Invalid quoted character");
- addAsmOperand(i, i + 1, Separators);
+ addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);
Prev = i + 1;
+ IsIsolatedToken = false;
break;
case '$': {
- if (InTok && Prev != i) {
- addAsmOperand(Prev, i, Separators);
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), false);
InTok = false;
+ IsIsolatedToken = false;
}
// If this isn't "${", start new identifier looking like "$xxx"
@@ -940,26 +960,20 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,
size_t EndPos = String.find('}', i);
assert(EndPos != StringRef::npos &&
"Missing brace in operand reference!");
- addAsmOperand(i, EndPos+1, Separators);
+ addAsmOperand(String.slice(i, EndPos+1), IsIsolatedToken);
Prev = EndPos + 1;
i = EndPos;
+ IsIsolatedToken = false;
break;
}
+
default:
InTok = true;
+ break;
}
}
if (InTok && Prev != String.size())
- addAsmOperand(Prev, StringRef::npos, Separators);
-
- // The first token of the instruction is the mnemonic, which must be a
- // simple string, not a $foo variable or a singleton register.
- if (AsmOperands.empty())
- PrintFatalError(TheDef->getLoc(),
- "Instruction '" + TheDef->getName() + "' has no tokens");
- assert(!AsmOperands[0].Token.empty());
- if (AsmOperands[0].Token[0] != '$')
- Mnemonic = AsmOperands[0].Token;
+ addAsmOperand(String.substr(Prev), IsIsolatedToken);
}
bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
@@ -1352,8 +1366,7 @@ void AsmMatcherInfo::buildInfo() {
// Build information about all of the AssemblerPredicates.
std::vector<Record*> AllPredicates =
Records.getAllDerivedDefinitions("Predicate");
- for (unsigned i = 0, e = AllPredicates.size(); i != e; ++i) {
- Record *Pred = AllPredicates[i];
+ for (Record *Pred : AllPredicates) {
// Ignore predicates that are not intended for the assembler.
if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
continue;
@@ -1367,6 +1380,8 @@ void AsmMatcherInfo::buildInfo() {
assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
}
+ bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
+
// Parse the instructions; we need to do this first so that we can gather the
// singleton register classes.
SmallPtrSet<Record*, 16> SingletonRegisters;
@@ -1398,7 +1413,7 @@ void AsmMatcherInfo::buildInfo() {
auto II = llvm::make_unique<MatchableInfo>(*CGI);
- II->initialize(*this, SingletonRegisters, Variant);
+ II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
// Ignore instructions which shouldn't be matched and diagnose invalid
// instruction definitions with an error.
@@ -1426,7 +1441,7 @@ void AsmMatcherInfo::buildInfo() {
auto II = llvm::make_unique<MatchableInfo>(std::move(Alias));
- II->initialize(*this, SingletonRegisters, Variant);
+ II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
// Validate the alias definitions.
II->validate(CommentDelimiter, false);
@@ -1732,7 +1747,7 @@ static unsigned getConverterOperandID(const std::string &Name,
static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
- raw_ostream &OS) {
+ bool HasMnemonicFirst, raw_ostream &OS) {
SmallSetVector<std::string, 16> OperandConversionKinds;
SmallSetVector<std::string, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t> > ConversionTable;
@@ -1866,7 +1881,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Add the operand entry to the instruction kind conversion row.
ConversionRow.push_back(ID);
- ConversionRow.push_back(OpInfo.AsmOperandNum);
+ ConversionRow.push_back(OpInfo.AsmOperandNum + HasMnemonicFirst);
if (!IsNewConverter)
break;
@@ -1988,8 +2003,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Output the operand conversion kind enum.
OS << "enum OperatorConversionKind {\n";
- for (unsigned i = 0, e = OperandConversionKinds.size(); i != e; ++i)
- OS << " " << OperandConversionKinds[i] << ",\n";
+ for (const std::string &Converter : OperandConversionKinds)
+ OS << " " << Converter << ",\n";
OS << " CVT_NUM_CONVERTERS\n";
OS << "};\n\n";
@@ -2156,11 +2171,12 @@ static void emitIsSubclass(CodeGenTarget &Target,
OS << " return false;\n";
}
}
- OS << " }\n";
// If there were case statements emitted into the string stream write the
// default.
- if (!EmittedSwitch)
+ if (EmittedSwitch)
+ OS << " }\n";
+ else
OS << " return false;\n";
OS << "}\n\n";
@@ -2247,19 +2263,16 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {
// Get the set of diagnostic types from all of the operand classes.
std::set<StringRef> Types;
- for (std::map<Record*, ClassInfo*>::const_iterator
- I = Info.AsmOperandClasses.begin(),
- E = Info.AsmOperandClasses.end(); I != E; ++I) {
- if (!I->second->DiagnosticType.empty())
- Types.insert(I->second->DiagnosticType);
+ for (const auto &OpClassEntry : Info.AsmOperandClasses) {
+ if (!OpClassEntry.second->DiagnosticType.empty())
+ Types.insert(OpClassEntry.second->DiagnosticType);
}
if (Types.empty()) return;
// Now emit the enum entries.
- for (std::set<StringRef>::const_iterator I = Types.begin(), E = Types.end();
- I != E; ++I)
- OS << " Match_" << *I << ",\n";
+ for (StringRef Type : Types)
+ OS << " Match_" << Type << ",\n";
OS << " END_OPERAND_DIAGNOSTIC_TYPES\n";
}
@@ -2367,8 +2380,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
// iteration order of the map is stable.
std::map<std::string, std::vector<Record*> > AliasesFromMnemonic;
- for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
- Record *R = Aliases[i];
+ for (Record *R : Aliases) {
// FIXME: Allow AssemblerVariantName to be a comma separated list.
std::string AsmVariantName = R->getValueAsString("AsmVariantName");
if (AsmVariantName != AsmParserVariantName)
@@ -2381,10 +2393,8 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
// Process each alias a "from" mnemonic at a time, building the code executed
// by the string remapper.
std::vector<StringMatcher::StringPair> Cases;
- for (std::map<std::string, std::vector<Record*> >::iterator
- I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end();
- I != E; ++I) {
- const std::vector<Record*> &ToVec = I->second;
+ for (const auto &AliasEntry : AliasesFromMnemonic) {
+ const std::vector<Record*> &ToVec = AliasEntry.second;
// Loop through each alias and emit code that handles each case. If there
// are two instructions without predicates, emit an error. If there is one,
@@ -2409,7 +2419,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
AliasWithNoPredicate = i;
continue;
}
- if (R->getValueAsString("ToMnemonic") == I->first)
+ if (R->getValueAsString("ToMnemonic") == AliasEntry.first)
PrintFatalError(R->getLoc(), "MnemonicAlias to the same string");
if (!MatchCode.empty())
@@ -2427,7 +2437,7 @@ static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
MatchCode += "return;";
- Cases.push_back(std::make_pair(I->first, MatchCode));
+ Cases.push_back(std::make_pair(AliasEntry.first, MatchCode));
}
StringMatcher("Mnemonic", Cases, OS).Emit(Indent);
}
@@ -2470,12 +2480,10 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
const AsmMatcherInfo &Info, StringRef ClassName,
StringToOffsetTable &StringTable,
- unsigned MaxMnemonicIndex) {
+ unsigned MaxMnemonicIndex, bool HasMnemonicFirst) {
unsigned MaxMask = 0;
- for (std::vector<OperandMatchEntry>::const_iterator it =
- Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end();
- it != ie; ++it) {
- MaxMask |= it->OperandMask;
+ for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
+ MaxMask |= OMI.OperandMask;
}
// Emit the static custom operand parsing table;
@@ -2515,10 +2523,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
<< Info.OperandMatchInfo.size() << "] = {\n";
OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n";
- for (std::vector<OperandMatchEntry>::const_iterator it =
- Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end();
- it != ie; ++it) {
- const OperandMatchEntry &OMI = *it;
+ for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
const MatchableInfo &II = *OMI.MI;
OS << " { ";
@@ -2589,19 +2594,25 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the next operand index.\n";
- OS << " unsigned NextOpNum = Operands.size();\n";
+ OS << " unsigned NextOpNum = Operands.size()"
+ << (HasMnemonicFirst ? " - 1" : "") << ";\n";
// Emit code to search the table.
OS << " // Search the table.\n";
- OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>";
- OS << " MnemonicRange\n";
- OS << " (OperandMatchTable, OperandMatchTable+";
- OS << Info.OperandMatchInfo.size() << ");\n";
- OS << " if(!Mnemonic.empty())\n";
- OS << " MnemonicRange = std::equal_range(OperandMatchTable,";
- OS << " OperandMatchTable+"
- << Info.OperandMatchInfo.size() << ", Mnemonic,\n"
- << " LessOpcodeOperand());\n\n";
+ if (HasMnemonicFirst) {
+ OS << " auto MnemonicRange =\n";
+ OS << " std::equal_range(std::begin(OperandMatchTable), "
+ "std::end(OperandMatchTable),\n";
+ OS << " Mnemonic, LessOpcodeOperand());\n\n";
+ } else {
+ OS << " auto MnemonicRange = std::make_pair(std::begin(OperandMatchTable),"
+ " std::end(OperandMatchTable));\n";
+ OS << " if (!Mnemonic.empty())\n";
+ OS << " MnemonicRange =\n";
+ OS << " std::equal_range(std::begin(OperandMatchTable), "
+ "std::end(OperandMatchTable),\n";
+ OS << " Mnemonic, LessOpcodeOperand());\n\n";
+ }
OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
OS << " return MatchOperand_NoMatch;\n\n";
@@ -2686,6 +2697,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Compute the information on the custom operand parsing.
Info.buildOperandMatchInfo();
+ bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
+
// Write the output.
// Information for the class declaration.
@@ -2700,7 +2713,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "&Operands);\n";
OS << " void convertToMapAndConstraints(unsigned Kind,\n ";
OS << " const OperandVector &Operands) override;\n";
- OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n";
+ if (HasMnemonicFirst)
+ OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n";
OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
<< " MCInst &Inst,\n"
<< " uint64_t &ErrorInfo,"
@@ -2761,7 +2775,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Generate the convertToMCInst function to convert operands into an MCInst.
// Also, generate the convertToMapAndConstraints function for MS-style inline
// assembly. The latter doesn't actually generate a MCInst.
- emitConvertFuncs(Target, ClassName, Info.Matchables, OS);
+ emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst, OS);
// Emit the enumeration for classes which participate in matching.
emitMatchClassEnumeration(Target, Info.Classes, OS);
@@ -2883,24 +2897,26 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
}
// A method to determine if a mnemonic is in the list.
- OS << "bool " << Target.getName() << ClassName << "::\n"
- << "mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n";
- OS << " // Find the appropriate table for this asm variant.\n";
- OS << " const MatchEntry *Start, *End;\n";
- OS << " switch (VariantID) {\n";
- OS << " default: llvm_unreachable(\"invalid variant!\");\n";
- for (unsigned VC = 0; VC != VariantCount; ++VC) {
- Record *AsmVariant = Target.getAsmParserVariant(VC);
- int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
- OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
- << "); End = std::end(MatchTable" << VC << "); break;\n";
+ if (HasMnemonicFirst) {
+ OS << "bool " << Target.getName() << ClassName << "::\n"
+ << "mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {\n";
+ OS << " // Find the appropriate table for this asm variant.\n";
+ OS << " const MatchEntry *Start, *End;\n";
+ OS << " switch (VariantID) {\n";
+ OS << " default: llvm_unreachable(\"invalid variant!\");\n";
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
+ OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
+ << "); End = std::end(MatchTable" << VC << "); break;\n";
+ }
+ OS << " }\n";
+ OS << " // Search the table.\n";
+ OS << " auto MnemonicRange = ";
+ OS << "std::equal_range(Start, End, Mnemonic, LessOpcode());\n";
+ OS << " return MnemonicRange.first != MnemonicRange.second;\n";
+ OS << "}\n\n";
}
- OS << " }\n";
- OS << " // Search the table.\n";
- OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n";
- OS << " std::equal_range(Start, End, Mnemonic, LessOpcode());\n";
- OS << " return MnemonicRange.first != MnemonicRange.second;\n";
- OS << "}\n\n";
// Finally, build the match function.
OS << "unsigned " << Target.getName() << ClassName << "::\n"
@@ -2909,8 +2925,10 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " bool matchingInlineAsm, unsigned VariantID) {\n";
OS << " // Eliminate obvious mismatches.\n";
- OS << " if (Operands.size() > " << MaxNumOperands << ") {\n";
- OS << " ErrorInfo = " << MaxNumOperands << ";\n";
+ OS << " if (Operands.size() > "
+ << (MaxNumOperands + HasMnemonicFirst) << ") {\n";
+ OS << " ErrorInfo = "
+ << (MaxNumOperands + HasMnemonicFirst) << ";\n";
OS << " return Match_InvalidOperand;\n";
OS << " }\n\n";
@@ -2919,10 +2937,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
OS << " // Get the instruction mnemonic, which is the first token.\n";
- OS << " StringRef Mnemonic;\n";
- OS << " if (Operands[0]->isToken())\n";
- OS << " Mnemonic = ((" << Target.getName()
- << "Operand&)*Operands[0]).getToken();\n\n";
+ if (HasMnemonicFirst) {
+ OS << " StringRef Mnemonic = ((" << Target.getName()
+ << "Operand&)*Operands[0]).getToken();\n\n";
+ } else {
+ OS << " StringRef Mnemonic;\n";
+ OS << " if (Operands[0]->isToken())\n";
+ OS << " Mnemonic = ((" << Target.getName()
+ << "Operand&)*Operands[0]).getToken();\n\n";
+ }
if (HasMnemonicAliases) {
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
@@ -2951,12 +2974,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "); End = std::end(MatchTable" << VC << "); break;\n";
}
OS << " }\n";
+
OS << " // Search the table.\n";
- OS << " std::pair<const MatchEntry*, const MatchEntry*> "
- "MnemonicRange(Start, End);\n";
- OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
- OS << " if (!Mnemonic.empty())\n";
- OS << " MnemonicRange = std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
+ if (HasMnemonicFirst) {
+ OS << " auto MnemonicRange = "
+ "std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";
+ } else {
+ OS << " auto MnemonicRange = std::make_pair(Start, End);\n";
+ OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
+ OS << " if (!Mnemonic.empty())\n";
+ OS << " MnemonicRange = "
+ "std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
+ }
OS << " // Return a more specific error code if no mnemonics match.\n";
OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
@@ -2966,16 +2995,25 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "*ie = MnemonicRange.second;\n";
OS << " it != ie; ++it) {\n";
+ if (HasMnemonicFirst) {
+ OS << " // equal_range guarantees that instruction mnemonic matches.\n";
+ OS << " assert(Mnemonic == it->getMnemonic());\n";
+ }
+
// Emit check that the subclasses match.
OS << " bool OperandsValid = true;\n";
- OS << " for (unsigned i = SIndex; i != " << MaxNumOperands << "; ++i) {\n";
+ OS << " for (unsigned i = " << (HasMnemonicFirst ? "0" : "SIndex")
+ << "; i != " << MaxNumOperands << "; ++i) {\n";
OS << " auto Formal = static_cast<MatchClassKind>(it->Classes[i]);\n";
- OS << " if (i >= Operands.size()) {\n";
+ OS << " if (i" << (HasMnemonicFirst ? "+1" : "")
+ << " >= Operands.size()) {\n";
OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n";
- OS << " if (!OperandsValid) ErrorInfo = i;\n";
+ OS << " if (!OperandsValid) ErrorInfo = i"
+ << (HasMnemonicFirst ? "+1" : "") << ";\n";
OS << " break;\n";
OS << " }\n";
- OS << " MCParsedAsmOperand &Actual = *Operands[i];\n";
+ OS << " MCParsedAsmOperand &Actual = *Operands[i"
+ << (HasMnemonicFirst ? "+1" : "") << "];\n";
OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n";
OS << " if (Diag == Match_Success)\n";
OS << " continue;\n";
@@ -2991,8 +3029,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // If we already had a match that only failed due to a\n";
OS << " // target predicate, that diagnostic is preferred.\n";
OS << " if (!HadMatchOtherThanPredicate &&\n";
- OS << " (it == MnemonicRange.first || ErrorInfo <= i)) {\n";
- OS << " ErrorInfo = i;\n";
+ OS << " (it == MnemonicRange.first || ErrorInfo <= i"
+ << (HasMnemonicFirst ? "+1" : "") << ")) {\n";
+ OS << " ErrorInfo = i" << (HasMnemonicFirst ? "+1" : "") << ";\n";
OS << " // InvalidOperand is the default. Prefer specificity.\n";
OS << " if (Diag != Match_InvalidOperand)\n";
OS << " RetCode = Diag;\n";
@@ -3067,7 +3106,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (!Info.OperandMatchInfo.empty())
emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
- MaxMnemonicIndex);
+ MaxMnemonicIndex, HasMnemonicFirst);
OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
}
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 6246d811123d..d056de003e18 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -185,16 +185,12 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
const std::vector<Record*> &ImpliesList =
Feature->getValueAsListOfDefs("Implies");
- if (ImpliesList.empty()) {
- OS << "{ }";
- } else {
- OS << "{ ";
- for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
- OS << Target << "::" << ImpliesList[j]->getName();
- if (++j < M) OS << ", ";
- }
- OS << " }";
+ OS << "{";
+ for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
+ OS << " " << Target << "::" << ImpliesList[j]->getName();
+ if (++j < M) OS << ",";
}
+ OS << " }";
OS << " }";
++NumFeatures;
@@ -240,16 +236,12 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
<< "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", ";
- if (FeatureList.empty()) {
- OS << "{ }";
- } else {
- OS << "{ ";
- for (unsigned j = 0, M = FeatureList.size(); j < M;) {
- OS << Target << "::" << FeatureList[j]->getName();
- if (++j < M) OS << ", ";
- }
- OS << " }";
+ OS << "{";
+ for (unsigned j = 0, M = FeatureList.size(); j < M;) {
+ OS << " " << Target << "::" << FeatureList[j]->getName();
+ if (++j < M) OS << ",";
}
+ OS << " }";
// The { } is for the "implies" section of this data structure.
OS << ", { } }";
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index c16a5583eb36..bcc594d69a1d 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -13,6 +13,7 @@
#include "TableGenBackends.h" // Declares all backends.
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
@@ -182,6 +183,8 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
+ llvm_shutdown_obj Y;
+
return TableGenMain(argv[0], &LLVMTableGenMain);
}