#include "Record.h"
#include "StringMatcher.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
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) {
Tokens.push_back(AsmString.substr(Prev));
}
-static bool IsAssemblerInstruction(StringRef Name,
- const CodeGenInstruction &CGI,
- const SmallVectorImpl<StringRef> &Tokens) {
- // Ignore "codegen only" instructions.
- if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
- return false;
-
- // Ignore pseudo ops.
- //
- // FIXME: This is a hack; can we convert these instructions to set the
- // "codegen only" bit instead?
- if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
- if (Form->getValue()->getAsString() == "Pseudo")
- return false;
-
- // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
- //
- // FIXME: This is a total hack.
- if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int"))
- return false;
-
- // Ignore instructions with no .s string.
- //
- // FIXME: What are these?
- if (CGI.AsmString.empty())
- return false;
-
- // FIXME: Hack; ignore any instructions with a newline in them.
- if (std::find(CGI.AsmString.begin(),
- CGI.AsmString.end(), '\n') != CGI.AsmString.end())
- return false;
-
- // Ignore instructions with attributes, these are always fake instructions for
- // simplifying codegen.
- //
- // FIXME: Is this true?
- //
- // 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] == '$' &&
- std::find(Tokens[i].begin(),
- Tokens[i].end(), ':') != Tokens[i].end()) {
- DEBUG({
- errs() << "warning: '" << Name << "': "
- << "ignoring instruction; operand with attribute '"
- << Tokens[i] << "'\n";
- });
- return false;
- }
-
- if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
- DEBUG({
- errs() << "warning: '" << Name << "': "
- << "ignoring instruction with tied operand '"
- << Tokens[i].str() << "'\n";
- });
- return false;
- }
- }
-
- return true;
-}
namespace {
-
+ class AsmMatcherInfo;
struct SubtargetFeatureInfo;
/// ClassInfo - Helper class for storing the information about a particular
}
};
-/// InstructionInfo - Helper class for storing the necessary information for an
-/// instruction which is capable of being matched.
-struct InstructionInfo {
+/// MatchableInfo - Helper class for storing the necessary information for an
+/// instruction or alias which is capable of being matched.
+struct MatchableInfo {
struct Operand {
/// The unique class instance this operand should match.
ClassInfo *Class;
/// The original operand this corresponds to, if any.
- const CodeGenInstruction::OperandInfo *OperandInfo;
+ const CGIOperandList::OperandInfo *OperandInfo;
+
+ Operand(ClassInfo *C, const CGIOperandList::OperandInfo *OpInfo)
+ : Class(C), OperandInfo(OpInfo) {}
};
/// InstrName - The target name for this instruction.
std::string InstrName;
- /// Instr - The instruction this matches.
- const CodeGenInstruction *Instr;
+ Record *const TheDef;
+ const CGIOperandList &OperandList;
/// AsmString - The assembly string for this instruction (with variants
/// removed).
/// ConvertToMCInst to convert parsed operands into an MCInst for this
/// function.
std::string ConversionFnKind;
+
+ MatchableInfo(const CodeGenInstruction &CGI)
+ : TheDef(CGI.TheDef), OperandList(CGI.Operands), AsmString(CGI.AsmString) {
+ InstrName = TheDef->getName();
+ }
- /// operator< - Compare two instructions.
- bool operator<(const InstructionInfo &RHS) const {
+ MatchableInfo(const CodeGenInstAlias *Alias)
+ : TheDef(Alias->TheDef), OperandList(Alias->Operands),
+ AsmString(Alias->AsmString) {
+
+ // FIXME: Huge hack.
+ DefInit *DI = dynamic_cast<DefInit*>(Alias->Result->getOperator());
+ assert(DI);
+
+ InstrName = DI->getDef()->getName();
+ }
+
+ void Initialize(const AsmMatcherInfo &Info,
+ SmallPtrSet<Record*, 16> &SingletonRegisters);
+
+ /// 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;
+
+ /// getSingletonRegisterForToken - If the specified token is a singleton
+ /// register, return the Record for it, otherwise return null.
+ Record *getSingletonRegisterForToken(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];
return false;
}
- /// CouldMatchAmiguouslyWith - Check whether this instruction could
+ /// CouldMatchAmiguouslyWith - Check whether this matchable could
/// ambiguously match the same set of operands as \arg RHS (without being a
/// strictly superior match).
- bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) {
+ bool CouldMatchAmiguouslyWith(const MatchableInfo &RHS) {
+ // The primary comparator is the instruction mnemonic.
+ if (Tokens[0] != RHS.Tokens[0])
+ return false;
+
// The number of operands is unambiguous.
if (Operands.size() != RHS.Operands.size())
return false;
return !(HasLT ^ HasGT);
}
-public:
void dump();
};
/// \brief An unique index assigned to represent this feature.
unsigned Index;
+ SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {}
+
/// \brief The name of the enumerated constant identifying this feature.
- std::string EnumName;
+ std::string getEnumName() const {
+ return "Feature_" + TheDef->getName();
+ }
};
class AsmMatcherInfo {
/// The tablegen AsmParser record.
Record *AsmParser;
- /// The AsmParser "CommentDelimiter" value.
- std::string CommentDelimiter;
+ /// Target - The target information.
+ CodeGenTarget &Target;
/// The AsmParser "RegisterPrefix" value.
std::string RegisterPrefix;
/// The classes which are needed for matching.
std::vector<ClassInfo*> Classes;
- /// The information on the instruction to match.
- std::vector<InstructionInfo*> Instructions;
+ /// The information on the matchables to match.
+ std::vector<MatchableInfo*> Matchables;
/// Map of Register records to their class information.
std::map<Record*, ClassInfo*> RegisterClasses;
/// Map of Predicate records to their subtarget information.
std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures;
-
+
private:
/// Map of token to class information which has already been constructed.
std::map<std::string, ClassInfo*> TokenClasses;
/// getOperandClass - Lookup or create the class for the given operand.
ClassInfo *getOperandClass(StringRef Token,
- const CodeGenInstruction::OperandInfo &OI);
-
- /// getSubtargetFeature - Lookup or create the subtarget feature info for the
- /// given operand.
- SubtargetFeatureInfo *getSubtargetFeature(Record *Def) {
- assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
-
- SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
- if (!Entry) {
- Entry = new SubtargetFeatureInfo();
- Entry->TheDef = Def;
- Entry->Index = SubtargetFeatures.size() - 1;
- Entry->EnumName = "Feature_" + Def->getName();
- assert(Entry->Index < 32 && "Too many subtarget features!");
- }
-
- return Entry;
- }
+ const CGIOperandList::OperandInfo &OI);
/// BuildRegisterClasses - Build the ClassInfo* instances for register
/// classes.
- void BuildRegisterClasses(CodeGenTarget &Target,
- std::set<std::string> &SingletonRegisterNames);
+ void BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters);
/// BuildOperandClasses - Build the ClassInfo* instances for user defined
/// operand classes.
- void BuildOperandClasses(CodeGenTarget &Target);
+ void BuildOperandClasses();
public:
- AsmMatcherInfo(Record *_AsmParser);
+ AsmMatcherInfo(Record *AsmParser, CodeGenTarget &Target);
/// BuildInfo - Construct the various tables used during matching.
- void BuildInfo(CodeGenTarget &Target);
+ void BuildInfo();
+
+ /// getSubtargetFeature - Lookup or create the subtarget feature info for the
+ /// given operand.
+ SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
+ assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
+ std::map<Record*, SubtargetFeatureInfo*>::const_iterator I =
+ SubtargetFeatures.find(Def);
+ return I == SubtargetFeatures.end() ? 0 : I->second;
+ }
};
}
-void InstructionInfo::dump() {
+void MatchableInfo::dump() {
errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
<< ", tokens:[";
for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
continue;
}
- const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo;
+ const CGIOperandList::OperandInfo &OI = *Op.OperandInfo;
errs() << OI.Name << " " << OI.Rec->getName()
<< " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
}
}
+void MatchableInfo::Initialize(const AsmMatcherInfo &Info,
+ SmallPtrSet<Record*, 16> &SingletonRegisters) {
+ // TODO: Eventually support asmparser for Variant != 0.
+ AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, 0);
+
+ TokenizeAsmString(AsmString, Tokens);
+
+ // Compute the require features.
+ std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates");
+ for (unsigned i = 0, e = Predicates.size(); i != e; ++i)
+ if (SubtargetFeatureInfo *Feature =
+ Info.getSubtargetFeature(Predicates[i]))
+ 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))
+ SingletonRegisters.insert(Reg);
+ }
+}
+
+
+/// getRegisterRecord - Get the register record for \arg name, or 0.
+static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
+ for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Target.getRegisters()[i];
+ if (Name == Reg.TheDef->getValueAsString("AsmName"))
+ return Reg.TheDef;
+ }
+
+ return 0;
+}
+
+bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const {
+ // Reject matchables with no .s string.
+ if (AsmString.empty())
+ throw TGError(TheDef->getLoc(), "instruction with empty asm string");
+
+ // Reject any matchables with a newline in them, they should be marked
+ // isCodeGenOnly if they are pseudo instructions.
+ if (AsmString.find('\n') != std::string::npos)
+ throw TGError(TheDef->getLoc(),
+ "multiline instruction is not valid for the asmparser, "
+ "mark it isCodeGenOnly");
+
+ // Remove comments from the asm string. We know that the asmstring only
+ // has one line.
+ if (!CommentDelimiter.empty() &&
+ StringRef(AsmString).find(CommentDelimiter) != StringRef::npos)
+ throw TGError(TheDef->getLoc(),
+ "asmstring for instruction has comment character in it, "
+ "mark it isCodeGenOnly");
+
+ // Reject matchables with operand modifiers, these aren't something we can
+ /// handle, the target should be refactored to use operands instead of
+ /// modifiers.
+ //
+ // 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)
+ throw TGError(TheDef->getLoc(),
+ "matchable with operand modifier '" + Tokens[i].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 (!Hack)
+ throw TGError(TheDef->getLoc(),
+ "ERROR: matchable with tied operand '" + Tokens[i].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";
+ });
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/// getSingletonRegisterForToken - 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];
+ if (!Tok.startswith(Info.RegisterPrefix))
+ return 0;
+
+ StringRef RegName = Tok.substr(Info.RegisterPrefix.size());
+ if (Record *Rec = getRegisterRecord(Info.Target, RegName))
+ return Rec;
+
+ // 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;
+
+ std::string Err = "unable to find register for '" + RegName.str() +
+ "' (which matches register prefix)";
+ throw TGError(TheDef->getLoc(), Err);
+}
+
+
static std::string getEnumNameForToken(StringRef Str) {
std::string Res;
case '*': Res += "_STAR_"; break;
case '%': Res += "_PCT_"; break;
case ':': Res += "_COLON_"; break;
-
default:
- if (isalnum(*it)) {
+ if (isalnum(*it))
Res += *it;
- } else {
+ else
Res += "_" + utostr((unsigned) *it) + "_";
- }
}
}
return Res;
}
-/// getRegisterRecord - Get the register record for \arg name, or 0.
-static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
- for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
- const CodeGenRegister &Reg = Target.getRegisters()[i];
- if (Name == Reg.TheDef->getValueAsString("AsmName"))
- return Reg.TheDef;
- }
-
- return 0;
-}
-
ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
ClassInfo *&Entry = TokenClasses[Token];
ClassInfo *
AsmMatcherInfo::getOperandClass(StringRef Token,
- const CodeGenInstruction::OperandInfo &OI) {
+ const CGIOperandList::OperandInfo &OI) {
if (OI.Rec->isSubClassOf("RegisterClass")) {
ClassInfo *CI = RegisterClassClasses[OI.Rec];
- if (!CI) {
- PrintError(OI.Rec->getLoc(), "register class has no class info!");
- throw std::string("ERROR: Missing register class!");
- }
+ if (!CI)
+ throw TGError(OI.Rec->getLoc(), "register class has no class info!");
return CI;
}
Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
ClassInfo *CI = AsmOperandClasses[MatchClass];
- if (!CI) {
- PrintError(OI.Rec->getLoc(), "operand has no match class!");
- throw std::string("ERROR: Missing match class!");
- }
+ if (!CI)
+ throw TGError(OI.Rec->getLoc(), "operand has no match class!");
return CI;
}
-void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target,
- std::set<std::string>
- &SingletonRegisterNames) {
+void AsmMatcherInfo::
+BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
std::vector<CodeGenRegisterClass> RegisterClasses;
std::vector<CodeGenRegister> Registers;
it->Elements.end()));
// Add any required singleton sets.
- for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
- ie = SingletonRegisterNames.end(); it != ie; ++it)
- if (Record *Rec = getRegisterRecord(Target, *it))
- RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
+ for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
+ ie = SingletonRegisters.end(); it != ie; ++it) {
+ Record *Rec = *it;
+ RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
+ }
// Introduce derived sets where necessary (when a register does not determine
// a unique register set class), and build the mapping of registers to the set
this->RegisterClasses[it->first] = RegisterSetClasses[it->second];
// Name the register classes which correspond to singleton registers.
- for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
- ie = SingletonRegisterNames.end(); it != ie; ++it) {
- if (Record *Rec = getRegisterRecord(Target, *it)) {
- ClassInfo *CI = this->RegisterClasses[Rec];
- assert(CI && "Missing singleton register class info!");
-
- if (CI->ValueName.empty()) {
- CI->ClassName = Rec->getName();
- CI->Name = "MCK_" + Rec->getName();
- CI->ValueName = Rec->getName();
- } else
- CI->ValueName = CI->ValueName + "," + Rec->getName();
- }
+ for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
+ ie = SingletonRegisters.end(); it != ie; ++it) {
+ Record *Rec = *it;
+ ClassInfo *CI = this->RegisterClasses[Rec];
+ assert(CI && "Missing singleton register class info!");
+
+ if (CI->ValueName.empty()) {
+ CI->ClassName = Rec->getName();
+ CI->Name = "MCK_" + Rec->getName();
+ CI->ValueName = Rec->getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + Rec->getName();
}
}
-void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) {
- std::vector<Record*> AsmOperands;
- AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+void AsmMatcherInfo::BuildOperandClasses() {
+ std::vector<Record*> AsmOperands =
+ Records.getAllDerivedDefinitions("AsmOperandClass");
// Pre-populate AsmOperandClasses map.
for (std::vector<Record*>::iterator it = AsmOperands.begin(),
}
}
-AsmMatcherInfo::AsmMatcherInfo(Record *_AsmParser)
- : AsmParser(_AsmParser),
- CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")),
- RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix"))
-{
+AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target)
+ : AsmParser(asmParser), Target(target),
+ RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) {
}
-void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
- // Parse the instructions; we need to do this first so that we can gather the
- // singleton register classes.
- std::set<std::string> SingletonRegisterNames;
- const std::vector<const CodeGenInstruction*> &InstrList =
- Target.getInstructionsByEnumValue();
+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];
+ // Ignore predicates that are not intended for the assembler.
+ if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
+ continue;
+
+ if (Pred->getName().empty())
+ throw TGError(Pred->getLoc(), "Predicate has no name!");
+
+ unsigned FeatureNo = SubtargetFeatures.size();
+ SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
+ assert(FeatureNo < 32 && "Too many subtarget features!");
+ }
- for (unsigned i = 0, e = InstrList.size(); i != e; ++i) {
- const CodeGenInstruction &CGI = *InstrList[i];
+ StringRef 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;
- OwningPtr<InstructionInfo> II(new InstructionInfo());
-
- II->InstrName = CGI.TheDef->getName();
- II->Instr = &CGI;
- II->AsmString = FlattenVariants(CGI.AsmString, 0);
-
- // Remove comments from the asm string.
- if (!CommentDelimiter.empty()) {
- size_t Idx = StringRef(II->AsmString).find(CommentDelimiter);
- if (Idx != StringRef::npos)
- II->AsmString = II->AsmString.substr(0, Idx);
- }
-
- TokenizeAsmString(II->AsmString, II->Tokens);
-
- // Ignore instructions which shouldn't be matched.
- if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens))
+ // Ignore "codegen only" instructions.
+ if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
continue;
+
+ OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
- // Collect singleton registers, if used.
- for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
- if (!II->Tokens[i].startswith(RegisterPrefix))
- continue;
-
- StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
- Record *Rec = getRegisterRecord(Target, RegName);
-
- if (!Rec) {
- // If there is no register prefix (i.e. "%" in "%eax"), then this may
- // be some random non-register token, just ignore it.
- if (RegisterPrefix.empty())
- continue;
-
- std::string Err = "unable to find register for '" + RegName.str() +
- "' (which matches register prefix)";
- throw TGError(CGI.TheDef->getLoc(), Err);
- }
-
- SingletonRegisterNames.insert(RegName);
- }
-
- // Compute the require features.
- ListInit *Predicates = CGI.TheDef->getValueAsListInit("Predicates");
- for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
- if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
- // Ignore OptForSize and OptForSpeed, they aren't really requirements,
- // rather they are hints to isel.
- //
- // FIXME: Find better way to model this.
- if (Pred->getDef()->getName() == "OptForSize" ||
- Pred->getDef()->getName() == "OptForSpeed")
- continue;
-
- // FIXME: Total hack; for now, we just limit ourselves to In32BitMode
- // and In64BitMode, because we aren't going to have the right feature
- // masks for SSE and friends. We need to decide what we are going to do
- // about CPU subtypes to implement this the right way.
- if (Pred->getDef()->getName() != "In32BitMode" &&
- Pred->getDef()->getName() != "In64BitMode")
- continue;
-
- II->RequiredFeatures.push_back(getSubtargetFeature(Pred->getDef()));
- }
- }
-
- Instructions.push_back(II.take());
+ II->Initialize(*this, SingletonRegisters);
+
+ // 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->InstrName).startswith("Int_") ||
+ StringRef(II->InstrName).endswith("_Int"))
+ continue;
+
+ 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]);
+
+ OwningPtr<MatchableInfo> II(new MatchableInfo(Alias));
+
+ II->Initialize(*this, SingletonRegisters);
+
+ // Validate the alias definitions.
+ II->Validate(CommentDelimiter, false);
+
+ Matchables.push_back(II.take());
}
// Build info for the register classes.
- BuildRegisterClasses(Target, SingletonRegisterNames);
+ BuildRegisterClasses(SingletonRegisters);
// Build info for the user defined assembly operand classes.
- BuildOperandClasses(Target);
+ BuildOperandClasses();
- // Build the instruction information.
- for (std::vector<InstructionInfo*>::iterator it = Instructions.begin(),
- ie = Instructions.end(); it != ie; ++it) {
- InstructionInfo *II = *it;
+ // Build the information about matchables.
+ for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(),
+ ie = Matchables.end(); it != ie; ++it) {
+ MatchableInfo *II = *it;
// The first token of the instruction is the mnemonic, which must be a
- // simple string.
+ // simple string, not a $foo variable or a singleton register.
assert(!II->Tokens.empty() && "Instruction has no tokens?");
StringRef Mnemonic = II->Tokens[0];
- assert(Mnemonic[0] != '$' &&
- (RegisterPrefix.empty() || !Mnemonic.startswith(RegisterPrefix)));
+ 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];
// Check for singleton registers.
- if (Token.startswith(RegisterPrefix)) {
- StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
- if (Record *RegRecord = getRegisterRecord(Target, RegName)) {
- InstructionInfo::Operand Op;
- Op.Class = RegisterClasses[RegRecord];
- Op.OperandInfo = 0;
- assert(Op.Class && Op.Class->Registers.size() == 1 &&
- "Unexpected class for singleton register");
- II->Operands.push_back(Op);
- continue;
- }
-
- if (!RegisterPrefix.empty()) {
- std::string Err = "unable to find register for '" + RegName.str() +
- "' (which matches register prefix)";
- throw TGError(II->Instr->TheDef->getLoc(), Err);
- }
+ if (Record *RegRecord = II->getSingletonRegisterForToken(i, *this)) {
+ MatchableInfo::Operand Op(RegisterClasses[RegRecord], 0);
+ assert(Op.Class && Op.Class->Registers.size() == 1 &&
+ "Unexpected class for singleton register");
+ II->Operands.push_back(Op);
+ continue;
}
// Check for simple tokens.
if (Token[0] != '$') {
- InstructionInfo::Operand Op;
- Op.Class = getTokenClass(Token);
- Op.OperandInfo = 0;
- II->Operands.push_back(Op);
+ II->Operands.push_back(MatchableInfo::Operand(getTokenClass(Token), 0));
continue;
}
// Map this token to an operand. FIXME: Move elsewhere.
unsigned Idx;
- try {
- Idx = II->Instr->getOperandNamed(OperandName);
- } catch(...) {
- throw std::string("error: unable to find operand: '" +
- OperandName.str() + "'");
- }
+ if (!II->OperandList.hasOperandNamed(OperandName, Idx))
+ throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
+ OperandName.str() + "'");
// FIXME: This is annoying, the named operand may be tied (e.g.,
// XCHG8rm). What we want is the untied operand, which we now have to
// grovel for. Only worry about this for single entry operands, we have to
// clean this up anyway.
- const CodeGenInstruction::OperandInfo *OI = &II->Instr->OperandList[Idx];
+ const CGIOperandList::OperandInfo *OI = &II->OperandList[Idx];
if (OI->Constraints[0].isTied()) {
unsigned TiedOp = OI->Constraints[0].getTiedOperand();
// The tied operand index is an MIOperand index, find the operand that
// contains it.
- for (unsigned i = 0, e = II->Instr->OperandList.size(); i != e; ++i) {
- if (II->Instr->OperandList[i].MIOperandNo == TiedOp) {
- OI = &II->Instr->OperandList[i];
+ for (unsigned i = 0, e = II->OperandList.size(); i != e; ++i) {
+ if (II->OperandList[i].MIOperandNo == TiedOp) {
+ OI = &II->OperandList[i];
break;
}
}
assert(OI && "Unable to find tied operand target!");
}
- InstructionInfo::Operand Op;
- Op.Class = getOperandClass(Token, *OI);
- Op.OperandInfo = OI;
- II->Operands.push_back(Op);
+ II->Operands.push_back(MatchableInfo::Operand(getOperandClass(Token,
+ *OI), OI));
}
}
}
static void EmitConvertToMCInst(CodeGenTarget &Target,
- std::vector<InstructionInfo*> &Infos,
+ std::vector<MatchableInfo*> &Infos,
raw_ostream &OS) {
// Write the convert function to a separate stream, so we can drop it after
// the enum.
// TargetOperandClass - This is the target's operand class, like X86Operand.
std::string TargetOperandClass = Target.getName() + "Operand";
- for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
+ for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
- InstructionInfo &II = **it;
+ MatchableInfo &II = **it;
// Order the (class) operands by the order to convert them into an MCInst.
SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList;
for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[i];
+ MatchableInfo::Operand &Op = II.Operands[i];
if (Op.OperandInfo)
MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i));
}
// Find any tied operands.
SmallVector<std::pair<unsigned, unsigned>, 4> TiedOperands;
- for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
- const CodeGenInstruction::OperandInfo &OpInfo = II.Instr->OperandList[i];
+ for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i];
for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) {
- const CodeGenInstruction::ConstraintInfo &CI = OpInfo.Constraints[j];
+ const CGIOperandList::ConstraintInfo &CI = OpInfo.Constraints[j];
if (CI.isTied())
TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo + j,
CI.getTiedOperand()));
}
}
- std::sort(MIOperandList.begin(), MIOperandList.end());
+ array_pod_sort(MIOperandList.begin(), MIOperandList.end());
// Compute the total number of operands.
unsigned NumMIOperands = 0;
- for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
- const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i];
+ for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &OI = II.OperandList[i];
NumMIOperands = std::max(NumMIOperands,
OI.MIOperandNo + OI.MINumOperands);
}
std::string Signature = "Convert";
unsigned CurIndex = 0;
for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
+ MatchableInfo::Operand &Op = II.Operands[MIOperandList[i].second];
assert(CurIndex <= Op.OperandInfo->MIOperandNo &&
"Duplicate match for instruction operand!");
CvtOS << " case " << Signature << ":\n";
CurIndex = 0;
for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
+ MatchableInfo::Operand &Op = II.Operands[MIOperandList[i].second];
// Add the implicit operands.
for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
}
/// EmitClassifyOperand - Emit the function to classify an operand.
-static void EmitClassifyOperand(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
+static void EmitClassifyOperand(AsmMatcherInfo &Info,
raw_ostream &OS) {
OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n"
- << " " << Target.getName() << "Operand &Operand = *("
- << Target.getName() << "Operand*)GOp;\n";
+ << " " << Info.Target.getName() << "Operand &Operand = *("
+ << Info.Target.getName() << "Operand*)GOp;\n";
// Classify tokens.
OS << " if (Operand.isToken())\n";
for (std::map<Record*, ClassInfo*>::iterator
it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
it != ie; ++it)
- OS << " case " << Target.getName() << "::"
+ OS << " case " << Info.Target.getName() << "::"
<< it->first->getName() << ": return " << it->second->Name << ";\n";
OS << " }\n";
OS << " }\n\n";
/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag
/// definitions.
-static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
+static void EmitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
raw_ostream &OS) {
OS << "// Flags for subtarget features that participate in "
<< "instruction matching.\n";
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
- OS << " " << SFI.EnumName << " = (1 << " << SFI.Index << "),\n";
+ OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n";
}
OS << " Feature_None = 0\n";
OS << "};\n\n";
/// EmitComputeAvailableFeatures - Emit the function to compute the list of
/// available features given a subtarget.
-static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
+static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info,
raw_ostream &OS) {
std::string ClassName =
Info.AsmParser->getValueAsString("AsmParserClassName");
- OS << "unsigned " << Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(const " << Target.getName()
+ OS << "unsigned " << Info.Target.getName() << ClassName << "::\n"
+ << "ComputeAvailableFeatures(const " << Info.Target.getName()
<< "Subtarget *Subtarget) const {\n";
OS << " unsigned Features = 0;\n";
for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
SubtargetFeatureInfo &SFI = *it->second;
OS << " if (" << SFI.TheDef->getValueAsString("CondString")
<< ")\n";
- OS << " Features |= " << SFI.EnumName << ";\n";
+ OS << " Features |= " << SFI.getEnumName() << ";\n";
}
OS << " return Features;\n";
OS << "}\n\n";
}
-static std::string GetAliasRequiredFeatures(Record *R) {
- // FIXME: This is a total hack.
+static std::string GetAliasRequiredFeatures(Record *R,
+ const AsmMatcherInfo &Info) {
std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
-
std::string Result;
unsigned NumFeatures = 0;
for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
- Record *Pred = ReqFeatures[i];
-
- // FIXME: Total hack; for now, we just limit ourselves to In32BitMode
- // and In64BitMode, because we aren't going to have the right feature
- // masks for SSE and friends. We need to decide what we are going to do
- // about CPU subtypes to implement this the right way.
- if (Pred->getName() != "In32BitMode" &&
- Pred->getName() != "In64BitMode")
- continue;
-
+ SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
+
+ if (F == 0)
+ throw TGError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
+ "' is not marked as an AssemblerPredicate!");
+
if (NumFeatures)
Result += '|';
-
- Result += "Feature_" + Pred->getName();
+
+ Result += F->getEnumName();
++NumFeatures;
}
/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
/// emit a function for them and return true, otherwise return false.
-static bool EmitMnemonicAliases(raw_ostream &OS) {
+static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
std::vector<Record*> Aliases =
Records.getAllDerivedDefinitions("MnemonicAlias");
if (Aliases.empty()) return false;
for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
Record *R = ToVec[i];
- std::string FeatureMask = GetAliasRequiredFeatures(R);
+ std::string FeatureMask = GetAliasRequiredFeatures(R, Info);
// If this unconditionally matches, remember it for later and diagnose
// duplicates.
// We can't have two aliases from the same mnemonic with no predicate.
PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
"two MnemonicAliases with the same 'from' mnemonic!");
- PrintError(R->getLoc(), "this is the other MnemonicAliases.");
- throw std::string("ERROR: Invalid MnemonicAliases definitions!");
+ throw TGError(R->getLoc(), "this is the other MnemonicAlias.");
}
AliasWithNoPredicate = i;
continue;
}
+ if (!MatchCode.empty())
+ MatchCode += "else ";
MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n";
MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n";
}
if (AliasWithNoPredicate != -1) {
Record *R = ToVec[AliasWithNoPredicate];
- MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic") + "\";";
+ if (!MatchCode.empty())
+ MatchCode += "else\n ";
+ MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic")+"\";\n";
}
MatchCode += "return;";
std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
// Compute the information on the instructions to match.
- AsmMatcherInfo Info(AsmParser);
- Info.BuildInfo(Target);
+ AsmMatcherInfo Info(AsmParser, Target);
+ Info.BuildInfo();
// Sort the instruction table using the partial order on classes. We use
// stable_sort to ensure that ambiguous instructions are still
// deterministically ordered.
- std::stable_sort(Info.Instructions.begin(), Info.Instructions.end(),
- less_ptr<InstructionInfo>());
+ std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(),
+ less_ptr<MatchableInfo>());
DEBUG_WITH_TYPE("instruction_info", {
- for (std::vector<InstructionInfo*>::iterator
- it = Info.Instructions.begin(), ie = Info.Instructions.end();
+ for (std::vector<MatchableInfo*>::iterator
+ it = Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it)
(*it)->dump();
});
- // Check for ambiguous instructions.
+ // Check for ambiguous matchables.
DEBUG_WITH_TYPE("ambiguous_instrs", {
unsigned NumAmbiguous = 0;
- for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) {
+ for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) {
for (unsigned j = i + 1; j != e; ++j) {
- InstructionInfo &A = *Info.Instructions[i];
- InstructionInfo &B = *Info.Instructions[j];
+ MatchableInfo &A = *Info.Matchables[i];
+ MatchableInfo &B = *Info.Matchables[j];
if (A.CouldMatchAmiguouslyWith(B)) {
- errs() << "warning: ambiguous instruction match:\n";
+ errs() << "warning: ambiguous matchables:\n";
A.dump();
errs() << "\nis incomparable with:\n";
B.dump();
}
if (NumAmbiguous)
errs() << "warning: " << NumAmbiguous
- << " ambiguous instructions!\n";
+ << " ambiguous matchables!\n";
});
// Write the output.
OS << "#undef GET_REGISTER_MATCHER\n\n";
// Emit the subtarget feature enumeration.
- EmitSubtargetFeatureFlagEnumeration(Target, Info, OS);
+ EmitSubtargetFeatureFlagEnumeration(Info, OS);
// Emit the function to match a register name to number.
EmitMatchRegisterName(Target, AsmParser, OS);
OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";
// Generate the function that remaps for mnemonic aliases.
- bool HasMnemonicAliases = EmitMnemonicAliases(OS);
+ bool HasMnemonicAliases = EmitMnemonicAliases(OS, Info);
// Generate the unified function to convert operands into an MCInst.
- EmitConvertToMCInst(Target, Info.Instructions, OS);
+ EmitConvertToMCInst(Target, Info.Matchables, OS);
// Emit the enumeration for classes which participate in matching.
EmitMatchClassEnumeration(Target, Info.Classes, OS);
EmitMatchTokenString(Target, Info.Classes, OS);
// Emit the routine to classify an operand.
- EmitClassifyOperand(Target, Info, OS);
+ EmitClassifyOperand(Info, OS);
// Emit the subclass predicate routine.
EmitIsSubclass(Target, Info.Classes, OS);
// Emit the available features compute function.
- EmitComputeAvailableFeatures(Target, Info, OS);
+ EmitComputeAvailableFeatures(Info, OS);
size_t MaxNumOperands = 0;
- for (std::vector<InstructionInfo*>::const_iterator it =
- Info.Instructions.begin(), ie = Info.Instructions.end();
+ for (std::vector<MatchableInfo*>::const_iterator it =
+ Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it)
MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size());
OS << "} // end anonymous namespace.\n\n";
OS << "static const MatchEntry MatchTable["
- << Info.Instructions.size() << "] = {\n";
+ << Info.Matchables.size() << "] = {\n";
- for (std::vector<InstructionInfo*>::const_iterator it =
- Info.Instructions.begin(), ie = Info.Instructions.end();
+ for (std::vector<MatchableInfo*>::const_iterator it =
+ Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it) {
- InstructionInfo &II = **it;
+ MatchableInfo &II = **it;
OS << " { " << Target.getName() << "::" << II.InstrName
<< ", \"" << II.Tokens[0] << "\""
<< ", " << II.ConversionFnKind << ", { ";
for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[i];
+ MatchableInfo::Operand &Op = II.Operands[i];
if (i) OS << ", ";
OS << Op.Class->Name;
if (!II.RequiredFeatures.empty()) {
for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
if (i) OS << "|";
- OS << II.RequiredFeatures[i]->EnumName;
+ OS << II.RequiredFeatures[i]->getEnumName();
}
} else
OS << "0";
OS << " // Search the table.\n";
OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n";
OS << " std::equal_range(MatchTable, MatchTable+"
- << Info.Instructions.size() << ", Mnemonic, LessOpcode());\n\n";
+ << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n\n";
OS << " // Return a more specific error code if no mnemonics match.\n";
OS << " if (MnemonicRange.first == MnemonicRange.second)\n";