}
};
-/// 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 CGIOperandList::OperandInfo *OperandInfo;
+
+ Operand(ClassInfo *C, const CGIOperandList::OperandInfo *OpInfo)
+ : Class(C), OperandInfo(OpInfo) {}
};
/// InstrName - The target name for this instruction.
/// function.
std::string ConversionFnKind;
- InstructionInfo(const CodeGenInstruction &CGI, StringRef CommentDelimiter)
- : TheDef(CGI.TheDef), OperandList(CGI.Operands) {
+ MatchableInfo(const CodeGenInstruction &CGI)
+ : TheDef(CGI.TheDef), OperandList(CGI.Operands), AsmString(CGI.AsmString) {
InstrName = TheDef->getName();
- // TODO: Eventually support asmparser for Variant != 0.
- AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, 0);
-
- // Remove comments from the asm string. We know that the asmstring only
- // has one line.
- if (!CommentDelimiter.empty()) {
- size_t Idx = StringRef(AsmString).find(CommentDelimiter);
- if (Idx != StringRef::npos)
- AsmString = AsmString.substr(0, Idx);
- }
-
- TokenizeAsmString(AsmString, Tokens);
}
- /// isAssemblerInstruction - Return true if this matchable is a valid thing to
- /// match against.
- bool isAssemblerInstruction() 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 instructions.
- bool operator<(const InstructionInfo &RHS) 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;
/// Target - The target information.
CodeGenTarget &Target;
- /// The AsmParser "CommentDelimiter" value.
- std::string CommentDelimiter;
-
/// 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;
}
-void InstructionInfo::dump() {
+void MatchableInfo::dump() {
errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
<< ", tokens:[";
for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
}
}
+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) {
return 0;
}
-bool InstructionInfo::isAssemblerInstruction() const {
- StringRef Name = InstrName;
-
- // Reject instructions with no .s string.
+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 instructions with a newline in them, they should be marked
+ // 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");
- // Reject instructions with attributes, these aren't something we can handle,
- // the target should be refactored to use operands instead of modifiers.
+ // 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.
for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
if (Tokens[i][0] == '$' && Tokens[i].find(':') != StringRef::npos)
throw TGError(TheDef->getLoc(),
- "instruction with operand modifier '" + Tokens[i].str() +
+ "matchable with operand modifier '" + Tokens[i].str() +
"' not supported by asm matcher. Mark isCodeGenOnly!");
- // FIXME: Should reject these. The ARM backend hits this with $lane in a
- // bunch of instructions. It is unclear what the right answer is for this.
+ // 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: '" << Name << "': "
- << "ignoring instruction with tied operand '"
- << Tokens[i].str() << "'\n";
+ errs() << "warning: '" << InstrName << "': "
+ << "ignoring instruction with tied operand '"
+ << Tokens[i].str() << "'\n";
});
return false;
}
/// getSingletonRegisterForToken - If the specified token is a singleton
/// register, return the register name, otherwise return a null StringRef.
-Record *InstructionInfo::
+Record *MatchableInfo::
getSingletonRegisterForToken(unsigned i, const AsmMatcherInfo &Info) const {
StringRef Tok = Tokens[i];
if (!Tok.startswith(Info.RegisterPrefix))
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::BuildOperandClasses() {
- std::vector<Record*> AsmOperands;
- AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+ std::vector<Record*> AsmOperands =
+ Records.getAllDerivedDefinitions("AsmOperandClass");
// Pre-populate AsmOperandClasses map.
for (std::vector<Record*>::iterator it = AsmOperands.begin(),
AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, CodeGenTarget &target)
: AsmParser(asmParser), Target(target),
- CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")),
- RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix"))
-{
+ RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) {
}
+
void AsmMatcherInfo::BuildInfo() {
// Build information about all of the AssemblerPredicates.
std::vector<Record*> AllPredicates =
if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
continue;
- if (Pred->getName().empty()) {
- PrintError(Pred->getLoc(), "Predicate has no name!");
- throw std::string("ERROR: Predicate defs must be named");
- }
+ 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!");
}
+ 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;
if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
continue;
- OwningPtr<InstructionInfo> II(new InstructionInfo(CGI, CommentDelimiter));
+ OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
+ II->Initialize(*this, SingletonRegisters);
+
// Ignore instructions which shouldn't be matched and diagnose invalid
// instruction definitions with an error.
- if (!II->isAssemblerInstruction())
+ if (!II->Validate(CommentDelimiter, true))
continue;
// Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
StringRef(II->InstrName).endswith("_Int"))
continue;
- // Collect singleton registers, if used.
- for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
- if (Record *Reg = II->getSingletonRegisterForToken(i, *this))
- SingletonRegisters.insert(Reg);
- }
-
- // Compute the require features.
- std::vector<Record*> Predicates =
- CGI.TheDef->getValueAsListOfDefs("Predicates");
- for (unsigned i = 0, e = Predicates.size(); i != e; ++i)
- if (SubtargetFeatureInfo *Feature = getSubtargetFeature(Predicates[i]))
- II->RequiredFeatures.push_back(Feature);
-
- Instructions.push_back(II.take());
+ Matchables.push_back(II.take());
}
- // Parse all of the InstAlias definitions.
+ // 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);
- (void)Alias;
+ // Validate the alias definitions.
+ II->Validate(CommentDelimiter, false);
+
+ Matchables.push_back(II.take());
}
// Build info for the register classes.
// Build info for the user defined assembly operand classes.
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, not a $foo variable or a singleton register.
// Check for singleton registers.
if (Record *RegRecord = II->getSingletonRegisterForToken(i, *this)) {
- InstructionInfo::Operand Op;
- Op.Class = RegisterClasses[RegRecord];
- Op.OperandInfo = 0;
+ MatchableInfo::Operand Op(RegisterClasses[RegRecord], 0);
assert(Op.Class && Op.Class->Registers.size() == 1 &&
"Unexpected class for singleton register");
II->Operands.push_back(Op);
// 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;
if (!II->OperandList.hasOperandNamed(OperandName, Idx))
- throw std::string("error: unable to find operand: '" +
- OperandName.str() + "'");
+ 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
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));
}
}
}
- std::sort(MIOperandList.begin(), MIOperandList.end());
+ array_pod_sort(MIOperandList.begin(), MIOperandList.end());
// Compute the total number of operands.
unsigned NumMIOperands = 0;
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) {
// 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 MnemonicAlias.");
- throw std::string("ERROR: Invalid MnemonicAlias definitions!");
+ throw TGError(R->getLoc(), "this is the other MnemonicAlias.");
}
AliasWithNoPredicate = i;
// 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.
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);
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;
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";