summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2009-08-10 18:41:10 +0000
committerDaniel Dunbar <daniel@zuster.org>2009-08-10 18:41:10 +0000
commit338825c1928b956b2cbcc2c165a60afddd100398 (patch)
treeff202062dddcfe90ec2c604d1094571c44d91902
parentb2d555b25bee4df71b33bbf9a3d730339b6a4081 (diff)
downloadllvm-338825c1928b956b2cbcc2c165a60afddd100398.tar.gz
llvm-338825c1928b956b2cbcc2c165a60afddd100398.tar.bz2
llvm-338825c1928b956b2cbcc2c165a60afddd100398.tar.xz
llvm-mc/AsmMatcher: Change assembler parser match classes to their own record
structure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78581 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Target/Target.td34
-rw-r--r--lib/Target/X86/X86Instr64bit.td4
-rw-r--r--lib/Target/X86/X86InstrInfo.td21
-rw-r--r--lib/Target/X86/X86InstrSSE.td4
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp117
5 files changed, 101 insertions, 79 deletions
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 3ca7567b78..a30d40f97d 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<ValueType ty> {
// 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>;
diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td
index 34a77282c9..ef52785d5d 100644
--- a/lib/Target/X86/X86Instr64bit.td
+++ b/lib/Target/X86/X86Instr64bit.td
@@ -33,14 +33,14 @@ def i64i8imm : Operand<i64>;
def lea64mem : Operand<i64> {
let PrintMethod = "printlea64mem";
let MIOperandInfo = (ops GR64, i8imm, GR64_NOSP, i32imm);
- let ParserMatchClass = "Mem";
+ let ParserMatchClass = X86MemAsmOperand;
}
def lea64_32mem : Operand<i32> {
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 80f03e8318..202757ba7c 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<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">;
@@ -193,13 +197,13 @@ def f256mem : X86MemOperand<"printf256mem">;
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> {
@@ -210,16 +214,19 @@ def piclabel: Operand<i32> {
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.
diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td
index 99d193c23c..a0dbe620b8 100644
--- a/lib/Target/X86/X86InstrSSE.td
+++ b/lib/Target/X86/X86InstrSSE.td
@@ -87,12 +87,12 @@ def sse_load_f64 : ComplexPattern<v2f64, 5, "SelectScalarSSELoad", [],
def ssmem : Operand<v4f32> {
let PrintMethod = "printf32mem";
let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm);
- let ParserMatchClass = "Mem";
+ let ParserMatchClass = X86MemAsmOperand;
}
def sdmem : Operand<v2f64> {
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 08353a4243..0356cb8363 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -87,11 +87,9 @@
#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.
@@ -455,21 +453,16 @@ private:
/// 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);
@@ -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;
+
+ 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();