summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp')
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp439
1 files changed, 262 insertions, 177 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 8b86c23..39a3c25 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -99,6 +99,7 @@
#include "AsmMatcherEmitter.h"
#include "CodeGenTarget.h"
#include "StringMatcher.h"
+#include "StringToOffsetTable.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -107,6 +108,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include <map>
@@ -251,12 +253,7 @@ public:
switch (Kind) {
case Invalid:
- assert(0 && "Invalid kind!");
- case Token:
- // Tokens are comparable by value.
- //
- // FIXME: Compare by enum value.
- return ValueName < RHS.ValueName;
+ llvm_unreachable("Invalid kind!");
default:
// This class precedes the RHS if it is a proper subset of the RHS.
@@ -287,7 +284,11 @@ struct MatchableInfo {
/// The suboperand index within SrcOpName, or -1 for the entire operand.
int SubOpIdx;
- explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {}
+ /// Register record if this token is singleton register.
+ Record *SingletonReg;
+
+ explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1),
+ SingletonReg(0) {}
};
/// ResOperand - This represents a single operand in the result instruction
@@ -366,6 +367,9 @@ struct MatchableInfo {
}
};
+ /// AsmVariantID - Target's assembly syntax variant no.
+ int AsmVariantID;
+
/// TheDef - This is the definition of the instruction or InstAlias that this
/// matchable came from.
Record *const TheDef;
@@ -406,24 +410,28 @@ struct MatchableInfo {
std::string ConversionFnKind;
MatchableInfo(const CodeGenInstruction &CGI)
- : TheDef(CGI.TheDef), DefRec(&CGI), AsmString(CGI.AsmString) {
+ : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI),
+ AsmString(CGI.AsmString) {
}
MatchableInfo(const CodeGenInstAlias *Alias)
- : TheDef(Alias->TheDef), DefRec(Alias), AsmString(Alias->AsmString) {
+ : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias),
+ AsmString(Alias->AsmString) {
}
void Initialize(const AsmMatcherInfo &Info,
- SmallPtrSet<Record*, 16> &SingletonRegisters);
+ SmallPtrSet<Record*, 16> &SingletonRegisters,
+ int AsmVariantNo, std::string &RegisterPrefix);
/// Validate - Return true if this matchable is a valid thing to match against
/// and perform a bunch of validity checking.
bool Validate(StringRef CommentDelimiter, bool Hack) const;
- /// getSingletonRegisterForAsmOperand - If the specified token is a singleton
- /// register, return the Record for it, otherwise return null.
- Record *getSingletonRegisterForAsmOperand(unsigned i,
- const AsmMatcherInfo &Info) const;
+ /// extractSingletonRegisterForAsmOperand - Extract singleton register,
+ /// if present, from specified token.
+ void
+ extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info,
+ std::string &RegisterPrefix);
/// FindAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
@@ -557,9 +565,6 @@ public:
/// Target - The target information.
CodeGenTarget &Target;
- /// The AsmParser "RegisterPrefix" value.
- std::string RegisterPrefix;
-
/// The classes which are needed for matching.
std::vector<ClassInfo*> Classes;
@@ -591,7 +596,8 @@ private:
/// getOperandClass - Lookup or create the class for the given operand.
ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,
- int SubOpIdx = -1);
+ int SubOpIdx);
+ ClassInfo *getOperandClass(Record *Rec, int SubOpIdx);
/// BuildRegisterClasses - Build the ClassInfo* instances for register
/// classes.
@@ -645,9 +651,11 @@ void MatchableInfo::dump() {
}
void MatchableInfo::Initialize(const AsmMatcherInfo &Info,
- SmallPtrSet<Record*, 16> &SingletonRegisters) {
- // TODO: Eventually support asmparser for Variant != 0.
- AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, 0);
+ SmallPtrSet<Record*, 16> &SingletonRegisters,
+ int AsmVariantNo, std::string &RegisterPrefix) {
+ AsmVariantID = AsmVariantNo;
+ AsmString =
+ CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo);
TokenizeAsmString(Info);
@@ -660,7 +668,8 @@ void MatchableInfo::Initialize(const AsmMatcherInfo &Info,
// Collect singleton registers, if used.
for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
- if (Record *Reg = getSingletonRegisterForAsmOperand(i, Info))
+ extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix);
+ if (Record *Reg = AsmOperands[i].SingletonReg)
SingletonRegisters.insert(Reg);
}
}
@@ -736,9 +745,12 @@ void MatchableInfo::TokenizeAsmString(const AsmMatcherInfo &Info) {
// 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?");
+ if (AsmOperands.empty())
+ throw TGError(TheDef->getLoc(),
+ "Instruction '" + TheDef->getName() + "' has no tokens");
Mnemonic = AsmOperands[0].Token;
- if (Mnemonic[0] == '$' || getSingletonRegisterForAsmOperand(0, Info))
+ // FIXME : Check and raise an error if it is a register.
+ if (Mnemonic[0] == '$')
throw TGError(TheDef->getLoc(),
"Invalid instruction mnemonic '" + Mnemonic.str() + "'!");
@@ -801,28 +813,30 @@ bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const {
return true;
}
-/// getSingletonRegisterForAsmOperand - If the specified token is a singleton
-/// register, return the register name, otherwise return a null StringRef.
-Record *MatchableInfo::
-getSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info) const{
- StringRef Tok = AsmOperands[i].Token;
- if (!Tok.startswith(Info.RegisterPrefix))
- return 0;
+/// extractSingletonRegisterForAsmOperand - Extract singleton register,
+/// if present, from specified token.
+void MatchableInfo::
+extractSingletonRegisterForAsmOperand(unsigned OperandNo,
+ const AsmMatcherInfo &Info,
+ std::string &RegisterPrefix) {
+ StringRef Tok = AsmOperands[OperandNo].Token;
+ if (RegisterPrefix.empty()) {
+ std::string LoweredTok = Tok.lower();
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
+ AsmOperands[OperandNo].SingletonReg = Reg->TheDef;
+ return;
+ }
+
+ if (!Tok.startswith(RegisterPrefix))
+ return;
- StringRef RegName = Tok.substr(Info.RegisterPrefix.size());
+ StringRef RegName = Tok.substr(RegisterPrefix.size());
if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
- return Reg->TheDef;
+ AsmOperands[OperandNo].SingletonReg = Reg->TheDef;
// If there is no register prefix (i.e. "%" in "%eax"), then this may
// be some random non-register token, just ignore it.
- if (Info.RegisterPrefix.empty())
- return 0;
-
- // Otherwise, we have something invalid prefixed with the register prefix,
- // such as %foo.
- std::string Err = "unable to find register for '" + RegName.str() +
- "' (which matches register prefix)";
- throw TGError(TheDef->getLoc(), Err);
+ return;
}
static std::string getEnumNameForToken(StringRef Str) {
@@ -870,7 +884,11 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
Record *Rec = OI.Rec;
if (SubOpIdx != -1)
Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
+ return getOperandClass(Rec, SubOpIdx);
+}
+ClassInfo *
+AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
if (Rec->isSubClassOf("RegisterOperand")) {
// RegisterOperand may have an associated ParserMatchClass. If it does,
// use it, else just fall back to the underlying register class.
@@ -1102,8 +1120,7 @@ void AsmMatcherInfo::BuildOperandClasses() {
AsmMatcherInfo::AsmMatcherInfo(Record *asmParser,
CodeGenTarget &target,
RecordKeeper &records)
- : Records(records), AsmParser(asmParser), Target(target),
- RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) {
+ : Records(records), AsmParser(asmParser), Target(target) {
}
/// BuildOperandMatchInfo - Build the necessary information to handle user
@@ -1158,86 +1175,92 @@ void AsmMatcherInfo::BuildInfo() {
assert(FeatureNo < 32 && "Too many subtarget features!");
}
- std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter");
-
// Parse the instructions; we need to do this first so that we can gather the
// singleton register classes.
SmallPtrSet<Record*, 16> SingletonRegisters;
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- const CodeGenInstruction &CGI = **I;
-
- // If the tblgen -match-prefix option is specified (for tblgen hackers),
- // filter the set of instructions we consider.
- if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
- continue;
+ unsigned VariantCount = Target.getAsmParserVariantCount();
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ std::string CommentDelimiter = AsmVariant->getValueAsString("CommentDelimiter");
+ std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
+ int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
+
+ for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
+ E = Target.inst_end(); I != E; ++I) {
+ const CodeGenInstruction &CGI = **I;
+
+ // If the tblgen -match-prefix option is specified (for tblgen hackers),
+ // filter the set of instructions we consider.
+ if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
+ continue;
- // Ignore "codegen only" instructions.
- if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
- continue;
+ // Ignore "codegen only" instructions.
+ if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
+ continue;
- // Validate the operand list to ensure we can handle this instruction.
- for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
- const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
-
- // Validate tied operands.
- if (OI.getTiedRegister() != -1) {
- // If we have a tied operand that consists of multiple MCOperands,
- // reject it. We reject aliases and ignore instructions for now.
- if (OI.MINumOperands != 1) {
- // 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: '" << CGI.TheDef->getName() << "': "
- << "ignoring instruction with multi-operand tied operand '"
- << OI.Name << "'\n";
- });
- continue;
+ // Validate the operand list to ensure we can handle this instruction.
+ for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
+
+ // Validate tied operands.
+ if (OI.getTiedRegister() != -1) {
+ // If we have a tied operand that consists of multiple MCOperands,
+ // reject it. We reject aliases and ignore instructions for now.
+ if (OI.MINumOperands != 1) {
+ // 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: '" << CGI.TheDef->getName() << "': "
+ << "ignoring instruction with multi-operand tied operand '"
+ << OI.Name << "'\n";
+ });
+ continue;
+ }
}
}
- }
- OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
+ OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
- II->Initialize(*this, SingletonRegisters);
+ II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
- // Ignore instructions which shouldn't be matched and diagnose invalid
- // instruction definitions with an error.
- if (!II->Validate(CommentDelimiter, true))
- continue;
+ // Ignore instructions which shouldn't be matched and diagnose invalid
+ // instruction definitions with an error.
+ if (!II->Validate(CommentDelimiter, true))
+ continue;
- // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
- //
- // FIXME: This is a total hack.
- if (StringRef(II->TheDef->getName()).startswith("Int_") ||
- StringRef(II->TheDef->getName()).endswith("_Int"))
- continue;
+ // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
+ //
+ // FIXME: This is a total hack.
+ if (StringRef(II->TheDef->getName()).startswith("Int_") ||
+ StringRef(II->TheDef->getName()).endswith("_Int"))
+ continue;
- Matchables.push_back(II.take());
- }
+ Matchables.push_back(II.take());
+ }
- // Parse all of the InstAlias definitions and stick them in the list of
- // matchables.
- std::vector<Record*> AllInstAliases =
- Records.getAllDerivedDefinitions("InstAlias");
- for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
- CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target);
-
- // If the tblgen -match-prefix option is specified (for tblgen hackers),
- // filter the set of instruction aliases we consider, based on the target
- // instruction.
- if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith(
- MatchPrefix))
- continue;
+ // Parse all of the InstAlias definitions and stick them in the list of
+ // matchables.
+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+ for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
+ CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target);
+
+ // If the tblgen -match-prefix option is specified (for tblgen hackers),
+ // filter the set of instruction aliases we consider, based on the target
+ // instruction.
+ if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith(
+ MatchPrefix))
+ continue;
- OwningPtr<MatchableInfo> II(new MatchableInfo(Alias));
+ OwningPtr<MatchableInfo> II(new MatchableInfo(Alias));
- II->Initialize(*this, SingletonRegisters);
+ II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix);
- // Validate the alias definitions.
- II->Validate(CommentDelimiter, false);
+ // Validate the alias definitions.
+ II->Validate(CommentDelimiter, false);
- Matchables.push_back(II.take());
+ Matchables.push_back(II.take());
+ }
}
// Build info for the register classes.
@@ -1260,7 +1283,7 @@ void AsmMatcherInfo::BuildInfo() {
StringRef Token = Op.Token;
// Check for singleton registers.
- if (Record *RegRecord = II->getSingletonRegisterForAsmOperand(i, *this)) {
+ if (Record *RegRecord = II->AsmOperands[i].SingletonReg) {
Op.Class = RegisterClasses[RegRecord];
assert(Op.Class && Op.Class->Registers.size() == 1 &&
"Unexpected class for singleton register");
@@ -1297,6 +1320,17 @@ void AsmMatcherInfo::BuildInfo() {
II->BuildAliasResultOperands();
}
+ // Process token alias definitions and set up the associated superclass
+ // information.
+ std::vector<Record*> AllTokenAliases =
+ Records.getAllDerivedDefinitions("TokenAlias");
+ for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) {
+ Record *Rec = AllTokenAliases[i];
+ ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));
+ ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));
+ FromClass->SuperClasses.push_back(ToClass);
+ }
+
// Reorder classes so that classes precede super classes.
std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
}
@@ -1375,9 +1409,11 @@ void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
CGA.ResultOperands[i].getName() == OperandName) {
// It's safe to go with the first one we find, because CodeGenInstAlias
// validates that all operands with the same name have the same record.
- unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first;
Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
- Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx],
+ // Use the match class from the Alias definition, not the
+ // destination instruction, as we may have an immediate that's
+ // being munged by the match class.
+ Op.Class = getOperandClass(CGA.ResultOperands[i].getRecord(),
Op.SubOpIdx);
Op.SrcOpName = OperandName;
return;
@@ -1453,7 +1489,6 @@ void MatchableInfo::BuildAliasResultOperands() {
// Find out what operand from the asmparser that this MCInst operand
// comes from.
switch (CGA.ResultOperands[AliasOpNo].Kind) {
- default: assert(0 && "unexpected InstAlias operand kind");
case CodeGenInstAlias::ResultOperand::K_Record: {
StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
int SrcOperand = FindAsmOperand(Name, SubIdx);
@@ -1656,7 +1691,7 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target,
/// EmitValidateOperandClass - Emit the function to validate an operand class.
static void EmitValidateOperandClass(AsmMatcherInfo &Info,
raw_ostream &OS) {
- OS << "static bool ValidateOperandClass(MCParsedAsmOperand *GOp, "
+ OS << "static bool validateOperandClass(MCParsedAsmOperand *GOp, "
<< "MatchClassKind Kind) {\n";
OS << " " << Info.Target.getName() << "Operand &Operand = *("
<< Info.Target.getName() << "Operand*)GOp;\n";
@@ -1667,7 +1702,8 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info,
// Check for Token operands first.
OS << " if (Operand.isToken())\n";
- OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n";
+ OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind);"
+ << "\n\n";
// Check for register operands, including sub-classes.
OS << " if (Operand.isReg()) {\n";
@@ -1681,7 +1717,7 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info,
<< it->first->getName() << ": OpKind = " << it->second->Name
<< "; break;\n";
OS << " }\n";
- OS << " return IsSubclass(OpKind, Kind);\n";
+ OS << " return isSubclass(OpKind, Kind);\n";
OS << " }\n\n";
// Check the user classes. We don't care what order since we're only
@@ -1708,8 +1744,8 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info,
static void EmitIsSubclass(CodeGenTarget &Target,
std::vector<ClassInfo*> &Infos,
raw_ostream &OS) {
- OS << "/// IsSubclass - Compute whether \\arg A is a subclass of \\arg B.\n";
- OS << "static bool IsSubclass(MatchClassKind A, MatchClassKind B) {\n";
+ OS << "/// isSubclass - Compute whether \\arg A is a subclass of \\arg B.\n";
+ OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n";
OS << " if (A == B)\n";
OS << " return true;\n\n";
@@ -1720,32 +1756,30 @@ static void EmitIsSubclass(CodeGenTarget &Target,
ie = Infos.end(); it != ie; ++it) {
ClassInfo &A = **it;
- if (A.Kind != ClassInfo::Token) {
- std::vector<StringRef> SuperClasses;
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
- ie = Infos.end(); it != ie; ++it) {
- ClassInfo &B = **it;
-
- if (&A != &B && A.isSubsetOf(B))
- SuperClasses.push_back(B.Name);
- }
+ std::vector<StringRef> SuperClasses;
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ ClassInfo &B = **it;
- if (SuperClasses.empty())
- continue;
+ if (&A != &B && A.isSubsetOf(B))
+ SuperClasses.push_back(B.Name);
+ }
- OS << "\n case " << A.Name << ":\n";
+ if (SuperClasses.empty())
+ continue;
- if (SuperClasses.size() == 1) {
- OS << " return B == " << SuperClasses.back() << ";\n";
- continue;
- }
+ OS << "\n case " << A.Name << ":\n";
- OS << " switch (B) {\n";
- OS << " default: return false;\n";
- for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
- OS << " case " << SuperClasses[i] << ": return true;\n";
- OS << " }\n";
+ if (SuperClasses.size() == 1) {
+ OS << " return B == " << SuperClasses.back() << ";\n";
+ continue;
}
+
+ OS << " switch (B) {\n";
+ OS << " default: return false;\n";
+ for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
+ OS << " case " << SuperClasses[i] << ": return true;\n";
+ OS << " }\n";
}
OS << " }\n";
OS << "}\n\n";
@@ -1767,7 +1801,7 @@ static void EmitMatchTokenString(CodeGenTarget &Target,
"return " + CI.Name + ";"));
}
- OS << "static MatchClassKind MatchTokenString(StringRef Name) {\n";
+ OS << "static MatchClassKind matchTokenString(StringRef Name) {\n";
StringMatcher("Name", Matches, OS).Emit();
@@ -1905,7 +1939,7 @@ static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");
if (Aliases.empty()) return false;
- OS << "static void ApplyMnemonicAliases(StringRef &Mnemonic, "
+ OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
"unsigned Features) {\n";
// Keep track of all the aliases from a mnemonic. Use an std::map so that the
@@ -1975,45 +2009,62 @@ static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
return true;
}
+static const char *getMinimalTypeForRange(uint64_t Range) {
+ assert(Range < 0xFFFFFFFFULL && "Enum too large");
+ if (Range > 0xFFFF)
+ return "uint32_t";
+ if (Range > 0xFF)
+ return "uint16_t";
+ return "uint8_t";
+}
+
static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
const AsmMatcherInfo &Info, StringRef ClassName) {
// Emit the static custom operand parsing table;
OS << "namespace {\n";
OS << " struct OperandMatchEntry {\n";
- OS << " const char *Mnemonic;\n";
- OS << " unsigned OperandMask;\n";
- OS << " MatchClassKind Class;\n";
- OS << " unsigned RequiredFeatures;\n";
+ OS << " static const char *const MnemonicTable;\n";
+ OS << " uint32_t OperandMask;\n";
+ OS << " uint32_t Mnemonic;\n";
+ OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size())
+ << " RequiredFeatures;\n";
+ OS << " " << getMinimalTypeForRange(Info.Classes.size())
+ << " Class;\n\n";
+ OS << " StringRef getMnemonic() const {\n";
+ OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
+ OS << " MnemonicTable[Mnemonic]);\n";
+ OS << " }\n";
OS << " };\n\n";
OS << " // Predicate for searching for an opcode.\n";
OS << " struct LessOpcodeOperand {\n";
OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n";
- OS << " return StringRef(LHS.Mnemonic) < RHS;\n";
+ OS << " return LHS.getMnemonic() < RHS;\n";
OS << " }\n";
OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n";
- OS << " return LHS < StringRef(RHS.Mnemonic);\n";
+ OS << " return LHS < RHS.getMnemonic();\n";
OS << " }\n";
OS << " bool operator()(const OperandMatchEntry &LHS,";
OS << " const OperandMatchEntry &RHS) {\n";
- OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n";
+ OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n";
OS << " }\n";
OS << " };\n";
OS << "} // end anonymous namespace.\n\n";
+ StringToOffsetTable StringTable;
+
OS << "static const OperandMatchEntry OperandMatchTable["
<< Info.OperandMatchInfo.size() << "] = {\n";
- OS << " /* Mnemonic, Operand List Mask, Operand Class, Features */\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;
const MatchableInfo &II = *OMI.MI;
- OS << " { \"" << II.Mnemonic << "\""
- << ", " << OMI.OperandMask;
+ OS << " { " << OMI.OperandMask;
OS << " /* ";
bool printComma = false;
@@ -2026,8 +2077,10 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
}
OS << " */";
- OS << ", " << OMI.CI->Name
- << ", ";
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
+ << " /* " << II.Mnemonic << " */, ";
// Write the required features mask.
if (!II.RequiredFeatures.empty()) {
@@ -2037,15 +2090,22 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
}
} else
OS << "0";
+
+ OS << ", " << OMI.CI->Name;
+
OS << " },\n";
}
OS << "};\n\n";
+ OS << "const char *const OperandMatchEntry::MnemonicTable =\n";
+ StringTable.EmitString(OS);
+ OS << ";\n\n";
+
// Emit the operand class switch to call the correct custom parser for
// the found operand class.
OS << Target.getName() << ClassName << "::OperandMatchResultTy "
<< Target.getName() << ClassName << "::\n"
- << "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>"
+ << "tryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n unsigned MCK) {\n\n"
<< " switch(MCK) {\n";
@@ -2094,7 +2154,7 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
<< " *ie = MnemonicRange.second; it != ie; ++it) {\n";
OS << " // equal_range guarantees that instruction mnemonic matches.\n";
- OS << " assert(Mnemonic == it->Mnemonic);\n\n";
+ OS << " assert(Mnemonic == it->getMnemonic());\n\n";
// Emit check that the required features are available.
OS << " // check if the available features match\n";
@@ -2111,7 +2171,7 @@ static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit call to the custom parser method
OS << " // call custom parse method to handle the operand\n";
OS << " OperandMatchResultTy Result = ";
- OS << "TryCustomParseOperand(Operands, it->Class);\n";
+ OS << "tryCustomParseOperand(Operands, it->Class);\n";
OS << " if (Result != MatchOperand_NoMatch)\n";
OS << " return Result;\n";
OS << " }\n\n";
@@ -2186,7 +2246,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " bool MnemonicIsValid(StringRef Mnemonic);\n";
OS << " unsigned MatchInstructionImpl(\n";
OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
- OS << " MCInst &Inst, unsigned &ErrorInfo);\n";
+ OS << " MCInst &Inst, unsigned &ErrorInfo, unsigned VariantID = 0);\n";
if (Info.OperandMatchInfo.size()) {
OS << "\n enum OperandMatchResultTy {\n";
@@ -2198,7 +2258,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " StringRef Mnemonic);\n";
- OS << " OperandMatchResultTy TryCustomParseOperand(\n";
+ OS << " OperandMatchResultTy tryCustomParseOperand(\n";
OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " unsigned MCK);\n\n";
}
@@ -2260,28 +2320,39 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// following the mnemonic.
OS << "namespace {\n";
OS << " struct MatchEntry {\n";
- OS << " unsigned Opcode;\n";
- OS << " const char *Mnemonic;\n";
- OS << " ConversionKind ConvertFn;\n";
- OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
- OS << " unsigned RequiredFeatures;\n";
+ OS << " static const char *const MnemonicTable;\n";
+ OS << " uint32_t Mnemonic;\n";
+ OS << " uint16_t Opcode;\n";
+ OS << " " << getMinimalTypeForRange(Info.Matchables.size())
+ << " ConvertFn;\n";
+ OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size())
+ << " RequiredFeatures;\n";
+ OS << " " << getMinimalTypeForRange(Info.Classes.size())
+ << " Classes[" << MaxNumOperands << "];\n";
+ OS << " uint8_t AsmVariantID;\n\n";
+ OS << " StringRef getMnemonic() const {\n";
+ OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
+ OS << " MnemonicTable[Mnemonic]);\n";
+ OS << " }\n";
OS << " };\n\n";
OS << " // Predicate for searching for an opcode.\n";
OS << " struct LessOpcode {\n";
OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n";
- OS << " return StringRef(LHS.Mnemonic) < RHS;\n";
+ OS << " return LHS.getMnemonic() < RHS;\n";
OS << " }\n";
OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n";
- OS << " return LHS < StringRef(RHS.Mnemonic);\n";
+ OS << " return LHS < RHS.getMnemonic();\n";
OS << " }\n";
OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n";
- OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n";
+ OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n";
OS << " }\n";
OS << " };\n";
OS << "} // end anonymous namespace.\n\n";
+ StringToOffsetTable StringTable;
+
OS << "static const MatchEntry MatchTable["
<< Info.Matchables.size() << "] = {\n";
@@ -2290,16 +2361,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
it != ie; ++it) {
MatchableInfo &II = **it;
- OS << " { " << Target.getName() << "::"
- << II.getResultInst()->TheDef->getName() << ", \"" << II.Mnemonic << "\""
- << ", " << II.ConversionFnKind << ", { ";
- for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
- MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
-
- if (i) OS << ", ";
- OS << Op.Class->Name;
- }
- OS << " }, ";
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
+ << " /* " << II.Mnemonic << " */, "
+ << Target.getName() << "::"
+ << II.getResultInst()->TheDef->getName() << ", "
+ << II.ConversionFnKind << ", ";
// Write the required features mask.
if (!II.RequiredFeatures.empty()) {
@@ -2310,11 +2378,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
} else
OS << "0";
+ OS << ", { ";
+ for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
+ MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
+
+ if (i) OS << ", ";
+ OS << Op.Class->Name;
+ }
+ OS << " }, " << II.AsmVariantID;
OS << "},\n";
}
OS << "};\n\n";
+ OS << "const char *const MatchEntry::MnemonicTable =\n";
+ StringTable.EmitString(OS);
+ OS << ";\n\n";
+
// A method to determine if a mnemonic is in the list.
OS << "bool " << Target.getName() << ClassName << "::\n"
<< "MnemonicIsValid(StringRef Mnemonic) {\n";
@@ -2330,7 +2410,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< Target.getName() << ClassName << "::\n"
<< "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
<< " &Operands,\n";
- OS << " MCInst &Inst, unsigned &ErrorInfo) {\n";
+ OS << " MCInst &Inst, unsigned &ErrorInfo,\n";
+ OS << " unsigned VariantID) {\n";
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
@@ -2342,7 +2423,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasMnemonicAliases) {
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
- OS << " ApplyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n";
+ OS << " // FIXME : Add an entry in AsmParserVariant to check this.\n";
+ OS << " if (!VariantID)\n";
+ OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n";
}
// Emit code to compute the class list for this operand vector.
@@ -2375,16 +2458,18 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " it != ie; ++it) {\n";
OS << " // equal_range guarantees that instruction mnemonic matches.\n";
- OS << " assert(Mnemonic == it->Mnemonic);\n";
+ OS << " assert(Mnemonic == it->getMnemonic());\n";
// Emit check that the subclasses match.
+ OS << " if (VariantID != it->AsmVariantID) continue;\n";
OS << " bool OperandsValid = true;\n";
OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
OS << " if (i + 1 >= Operands.size()) {\n";
OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
OS << " break;\n";
OS << " }\n";
- OS << " if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n";
+ OS << " if (validateOperandClass(Operands[i+1], "
+ "(MatchClassKind)it->Classes[i]))\n";
OS << " continue;\n";
OS << " // If this operand is broken for all of the instances of this\n";
OS << " // mnemonic, keep track of it so we can report loc info.\n";
OpenPOWER on IntegriCloud