/// it to be resolved by inference in the context it is used.
def unknown;
+/// AsmOperandClass - Representation for the kinds of operands which the target
+/// specific parser can create and the assembly matcher may need to distinguish.
+///
+/// Operand classes are used to define the order in which instructions are
+/// matched, to ensure that the instruction which gets matched for any
+/// particular list of operands is deterministic.
+///
+/// The target specific parser must be able to classify a parsed operand into a
+/// unique class which does not partially overlap with any other classes. It can
+/// match a subset of some other class, in which case the super class field
+/// should be defined.
+class AsmOperandClass {
+ /// The name to use for this class, this should be usable as an enum value,
+ /// and will be used to generated the names for the methods to test whether a
+ /// particular target specific operand matches this class, and the method to
+ /// convert an operand of this class into an MCInst operand.
+ string Name = ?;
+
+ /// The super class of this operand.
+ AsmOperandClass SuperClass = ?;
+}
+
+def ImmAsmOperand : AsmOperandClass {
+ let Name = "Imm";
+}
+
/// Operand Types - These provide the built-in operand types that may be used
/// by a target. Targets can optionally provide their own operand types as
/// needed, though this should not be needed for RISC targets.
// into a unique class, which does not partially overlap with any other
// classes. It can match a subset of some other class, in which case
// ParserMatchSuperClass should be set to the name of that class.
- string ParserMatchClass = "Imm";
-
- // ParserMatchSuperClass - The enclosing super class for this operand (if
- // any). This operand *must* be a subset of the valid operands for the super
- // class; i.e., the match predicate for this super class must return true
- // for all instances of this class.
- string ParserMatchSuperClass = ?;
+ AsmOperandClass ParserMatchClass = ImmAsmOperand;
}
def i1imm : Operand<i1>;
// *mem - Operand definitions for the funky X86 addressing mode operands.
//
+def X86MemAsmOperand : AsmOperandClass {
+ let Name = "Mem";
+ let SuperClass = ImmAsmOperand;
+}
class X86MemOperand<string printMethod> : Operand<iPTR> {
let PrintMethod = printMethod;
let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm);
- let ParserMatchClass = "Mem";
+ let ParserMatchClass = X86MemAsmOperand;
}
def i8mem : X86MemOperand<"printi8mem">;
def i8mem_NOREX : Operand<i64> {
let PrintMethod = "printi8mem";
let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm);
- let ParserMatchClass = "Mem";
+ let ParserMatchClass = X86MemAsmOperand;
}
def lea32mem : Operand<i32> {
let PrintMethod = "printlea32mem";
let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
- let ParserMatchClass = "Mem";
+ let ParserMatchClass = X86MemAsmOperand;
}
def SSECC : Operand<i8> {
let PrintMethod = "printPICLabel";
}
+def ImmSExt8AsmOperand : AsmOperandClass {
+ let Name = "ImmSExt8";
+ let SuperClass = ImmAsmOperand;
+}
+
// A couple of more descriptive operand definitions.
// 16-bits but only 8 bits are significant.
def i16i8imm : Operand<i16> {
- let ParserMatchClass = "ImmSExt8";
- let ParserMatchSuperClass = "Imm";
+ let ParserMatchClass = ImmSExt8AsmOperand;
}
// 32-bits but only 8 bits are significant.
def i32i8imm : Operand<i32> {
- let ParserMatchClass = "ImmSExt8";
- let ParserMatchSuperClass = "Imm";
+ let ParserMatchClass = ImmSExt8AsmOperand;
}
// Branch targets have OtherVT type and print as pc-relative values.
#include <set>
using namespace llvm;
-namespace {
static cl::opt<std::string>
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.
/// Map of token to class information which has already been constructed.
std::map<std::string, ClassInfo*> TokenClasses;
- /// Map of operand name to class information which has already been
- /// constructed.
- std::map<std::string, ClassInfo*> OperandClasses;
+ /// The ClassInfo instance for registers.
+ ClassInfo *TheRegisterClass;
- /// Map of user class names to kind value.
- std::map<std::string, unsigned> UserClasses;
+ /// Map of AsmOperandClass records to their class information.
+ std::map<Record*, ClassInfo*> AsmOperandClasses;
private:
/// getTokenClass - Lookup or create the class for the given token.
ClassInfo *getTokenClass(const StringRef &Token);
- /// getUserClassKind - Lookup or create the kind value for the given class
- /// name.
- unsigned getUserClassKind(const StringRef &Name);
-
/// getOperandClass - Lookup or create the class for the given operand.
ClassInfo *getOperandClass(const StringRef &Token,
const CodeGenInstruction::OperandInfo &OI);
return Entry;
}
-unsigned AsmMatcherInfo::getUserClassKind(const StringRef &Name) {
- unsigned &Entry = UserClasses[Name];
-
- if (!Entry)
- Entry = ClassInfo::UserClass0 + UserClasses.size() - 1;
-
- return Entry;
-}
-
ClassInfo *
AsmMatcherInfo::getOperandClass(const StringRef &Token,
const CodeGenInstruction::OperandInfo &OI) {
- unsigned SuperClass = ClassInfo::Invalid;
- std::string ClassName;
- if (OI.Rec->isSubClassOf("RegisterClass")) {
- ClassName = "Reg";
- } else {
- try {
- ClassName = OI.Rec->getValueAsString("ParserMatchClass");
- assert(ClassName != "Reg" && "'Reg' class name is reserved!");
- } catch(...) {
- PrintError(OI.Rec->getLoc(), "operand has no match class!");
- ClassName = "Invalid";
- }
+ if (OI.Rec->isSubClassOf("RegisterClass"))
+ return TheRegisterClass;
+
+ assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
+ ClassInfo *CI = AsmOperandClasses[MatchClass];
- // Determine the super class.
- try {
- std::string SuperClassName =
- OI.Rec->getValueAsString("ParserMatchSuperClass");
- SuperClass = getUserClassKind(SuperClassName);
- } catch(...) { }
+ if (!CI) {
+ PrintError(OI.Rec->getLoc(), "operand has no match class!");
+ throw std::string("ERROR: Missing match class!");
}
- ClassInfo *&Entry = OperandClasses[ClassName];
-
- if (!Entry) {
- Entry = new ClassInfo();
- if (ClassName == "Reg") {
- Entry->Kind = ClassInfo::Register;
- Entry->SuperClassKind = SuperClass;
+ return CI;
+}
+
+void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
+ // Build the assembly match class information.
+
+ // Construct the "Reg" class.
+ //
+ // FIXME: This needs to dice up the RegisterClass instances.
+ ClassInfo *RegClass = TheRegisterClass = new ClassInfo();
+ RegClass->Kind = ClassInfo::Register;
+ RegClass->SuperClassKind = ClassInfo::Invalid;
+ RegClass->ClassName = "Reg";
+ RegClass->Name = "MCK_Reg";
+ RegClass->ValueName = "<register class>";
+ RegClass->PredicateMethod = "isReg";
+ RegClass->RenderMethod = "addRegOperands";
+ Classes.push_back(RegClass);
+
+ // Build info for the user defined assembly operand classes.
+ std::vector<Record*> AsmOperands;
+ AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+ unsigned Index = 0;
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ ie = AsmOperands.end(); it != ie; ++it, ++Index) {
+ ClassInfo *CI = new ClassInfo();
+ CI->Kind = ClassInfo::UserClass0 + Index;
+
+ Init *Super = (*it)->getValueInit("SuperClass");
+ if (DefInit *DI = dynamic_cast<DefInit*>(Super)) {
+ CI->SuperClass = AsmOperandClasses[DI->getDef()];
+ if (!CI->SuperClass)
+ PrintError((*it)->getLoc(), "Invalid super class reference!");
} else {
- Entry->Kind = getUserClassKind(ClassName);
- Entry->SuperClassKind = SuperClass;
+ assert(dynamic_cast<UnsetInit*>(Super) && "Unexpected SuperClass field!");
+ CI->SuperClass = 0;
}
- Entry->ClassName = ClassName;
- Entry->Name = "MCK_" + ClassName;
- Entry->ValueName = OI.Rec->getName();
- Entry->PredicateMethod = "is" + ClassName;
- Entry->RenderMethod = "add" + ClassName + "Operands";
- Classes.push_back(Entry);
- } else {
- // Verify the super class matches.
- assert(SuperClass == Entry->SuperClassKind &&
- "Cannot redefine super class kind!");
+ CI->ClassName = (*it)->getValueAsString("Name");
+ CI->Name = "MCK_" + CI->ClassName;
+ CI->ValueName = (*it)->getName();
+ CI->PredicateMethod = "is" + CI->ClassName;
+ CI->RenderMethod = "add" + CI->ClassName + "Operands";
+ AsmOperandClasses[*it] = CI;
+ Classes.push_back(CI);
}
-
- return Entry;
-}
-void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
+ // Build the instruction information.
for (std::map<std::string, CodeGenInstruction>::const_iterator
it = Target.getInstructions().begin(),
ie = Target.getInstructions().end();