diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 3ca7567b783..a30d40f97d6 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -278,6 +278,32 @@ def ptr_rc : PointerLikeRegClass<0>; /// 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. @@ -295,13 +321,7 @@ class 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 // 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; diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 34a77282c9c..ef52785d5d0 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -33,14 +33,14 @@ def i64i8imm : Operand; def lea64mem : Operand { let PrintMethod = "printlea64mem"; let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } def lea64_32mem : Operand { let PrintMethod = "printlea64_32mem"; let AsmOperandLowerMethod = "lower_lea64_32mem"; let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 80f03e8318c..202757ba7cf 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -170,10 +170,14 @@ def ptr_rc_nosp : PointerLikeRegClass<1>; // *mem - Operand definitions for the funky X86 addressing mode operands. // +def X86MemAsmOperand : AsmOperandClass { + let Name = "Mem"; + let SuperClass = ImmAsmOperand; +} class X86MemOperand : Operand { let PrintMethod = printMethod; let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } def i8mem : X86MemOperand<"printi8mem">; @@ -193,13 +197,13 @@ def f256mem : X86MemOperand<"printf256mem">; def i8mem_NOREX : Operand { let PrintMethod = "printi8mem"; let MIOperandInfo = (ops GR64_NOREX, i8imm, GR64_NOREX_NOSP, i32imm, i8imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } def lea32mem : Operand { let PrintMethod = "printlea32mem"; let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } def SSECC : Operand { @@ -210,16 +214,19 @@ def piclabel: Operand { 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 { - let ParserMatchClass = "ImmSExt8"; - let ParserMatchSuperClass = "Imm"; + let ParserMatchClass = ImmSExt8AsmOperand; } // 32-bits but only 8 bits are significant. def i32i8imm : Operand { - let ParserMatchClass = "ImmSExt8"; - let ParserMatchSuperClass = "Imm"; + let ParserMatchClass = ImmSExt8AsmOperand; } // Branch targets have OtherVT type and print as pc-relative values. diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index 99d193c23c0..a0dbe620b86 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -87,12 +87,12 @@ def sse_load_f64 : ComplexPattern { let PrintMethod = "printf32mem"; let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } def sdmem : Operand { let PrintMethod = "printf64mem"; let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm); - let ParserMatchClass = "Mem"; + let ParserMatchClass = X86MemAsmOperand; } //===----------------------------------------------------------------------===// diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 08353a4243b..0356cb8363b 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -87,11 +87,9 @@ #include using namespace llvm; -namespace { static cl::opt 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. @@ -455,21 +453,16 @@ private: /// Map of token to class information which has already been constructed. std::map TokenClasses; - /// Map of operand name to class information which has already been - /// constructed. - std::map OperandClasses; + /// The ClassInfo instance for registers. + ClassInfo *TheRegisterClass; - /// Map of user class names to kind value. - std::map UserClasses; + /// Map of AsmOperandClass records to their class information. + std::map 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); @@ -543,66 +536,68 @@ ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) { 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; - // Determine the super class. - try { - std::string SuperClassName = - OI.Rec->getValueAsString("ParserMatchSuperClass"); - SuperClass = getUserClassKind(SuperClassName); - } catch(...) { } + assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!"); + 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!"); } - ClassInfo *&Entry = OperandClasses[ClassName]; - - if (!Entry) { - Entry = new ClassInfo(); - if (ClassName == "Reg") { - Entry->Kind = ClassInfo::Register; - Entry->SuperClassKind = SuperClass; - } else { - Entry->Kind = getUserClassKind(ClassName); - Entry->SuperClassKind = SuperClass; - } - 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!"); - } - - return Entry; + 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 = ""; + RegClass->PredicateMethod = "isReg"; + RegClass->RenderMethod = "addRegOperands"; + Classes.push_back(RegClass); + + // Build info for the user defined assembly operand classes. + std::vector AsmOperands; + AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass"); + unsigned Index = 0; + for (std::vector::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(Super)) { + CI->SuperClass = AsmOperandClasses[DI->getDef()]; + if (!CI->SuperClass) + PrintError((*it)->getLoc(), "Invalid super class reference!"); + } else { + assert(dynamic_cast(Super) && "Unexpected SuperClass field!"); + CI->SuperClass = 0; + } + 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); + } + + // Build the instruction information. for (std::map::const_iterator it = Target.getInstructions().begin(), ie = Target.getInstructions().end();