llvm-mc/AsmParser: Define match classes in the .td file.
authorDaniel Dunbar <daniel@zuster.org>
Sun, 9 Aug 2009 05:18:30 +0000 (05:18 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Sun, 9 Aug 2009 05:18:30 +0000 (05:18 +0000)
 -2 FIXMEs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78523 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/Target.td
lib/Target/X86/X86InstrInfo.td
utils/TableGen/AsmMatcherEmitter.cpp

index 5262cce694335c1b1fd2737b9bd4869c38e47017..98b41254fc7c0f335221bad9677f87201aca2f73 100644 (file)
@@ -286,6 +286,17 @@ class Operand<ValueType ty> {
   string PrintMethod = "printOperand";
   string AsmOperandLowerMethod = ?;
   dag MIOperandInfo = (ops);
+
+  // ParserMatchClass - The "match class" that operands of this type fit
+  // in. Match classes are used to define the order in which instructions are
+  // match, to ensure that which instructions gets matched is deterministic.
+  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 = ?;
 }
 
 def i1imm  : Operand<i1>;
index 8263b2795a7b156036e0112db5c47d316892708d..c21cad98df01d1df583a37f2491517e0ac478278 100644 (file)
@@ -173,6 +173,7 @@ def ptr_rc_nosp : PointerLikeRegClass<1>;
 class X86MemOperand<string printMethod> : Operand<iPTR> {
   let PrintMethod = printMethod;
   let MIOperandInfo = (ops ptr_rc, i8imm, ptr_rc_nosp, i32imm, i8imm);
+  let ParserMatchClass = "Mem";
 }
 
 def i8mem   : X86MemOperand<"printi8mem">;
@@ -192,11 +193,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";
 }
 
 def lea32mem : Operand<i32> {
   let PrintMethod = "printlea32mem";
   let MIOperandInfo = (ops GR32, i8imm, GR32_NOSP, i32imm);
+  let ParserMatchClass = "Mem";
 }
 
 def SSECC : Operand<i8> {
index 9b12927521f77fcb67dec59c265a1d66b6417dd4..cbe214d3f31a3e41b7c8643c558734518aa8d7f2 100644 (file)
@@ -278,19 +278,23 @@ namespace {
 /// class of operands which can be matched.
 struct ClassInfo {
   enum ClassInfoKind {
-    Token, ///< The class for a particular token.
-    Register, ///< A register class.
-    UserClass0 ///< The (first) user defined class, subsequent user defined
-               /// classes are UserClass0+1, and so on.
+    Invalid = 0, ///< Invalid kind, for use as a sentinel value.
+    Token,       ///< The class for a particular token.
+    Register,    ///< A register class.
+    UserClass0   ///< The (first) user defined class, subsequent user defined
+                 /// classes are UserClass0+1, and so on.
   };
 
   /// Kind - The class kind, which is either a predefined kind, or (UserClass0 +
   /// N) for the Nth user defined class.
   unsigned Kind;
 
-  /// Name - The class name, suitable for use as an enum.
+  /// Name - The full class name, suitable for use in an enum.
   std::string Name;
 
+  /// ClassName - The unadorned generic name for this class (e.g., Token).
+  std::string ClassName;
+
   /// ValueName - The name of the value this class represents; for a token this
   /// is the literal token string, for an operand it is the TableGen class (or
   /// empty if this is a derived class).
@@ -311,6 +315,8 @@ struct ClassInfo {
       return Kind < RHS.Kind;
 
     switch (Kind) {
+    case Invalid:
+      assert(0 && "Invalid kind!");
     case Token:
       // Tokens are always comparable.
       //
@@ -412,10 +418,17 @@ private:
   /// constructed.
   std::map<std::string, ClassInfo*> OperandClasses;
 
+  /// Map of user class names to kind value.
+  std::map<std::string, unsigned> UserClasses;
+
 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);
@@ -439,7 +452,7 @@ void InstructionInfo::dump() {
 
   for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
     Operand &Op = Operands[i];
-    errs() << "  op[" << i << "] = ";
+    errs() << "  op[" << i << "] = " << Op.Class->ClassName << " - ";
     if (Op.Class->Kind == ClassInfo::Token) {
       errs() << '\"' << Tokens[i] << "\"\n";
       continue;
@@ -478,6 +491,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) {
   if (!Entry) {
     Entry = new ClassInfo();
     Entry->Kind = ClassInfo::Token;
+    Entry->ClassName = "Token";
     Entry->Name = "MCK_" + getEnumNameForToken(Token);
     Entry->ValueName = Token;
     Entry->PredicateMethod = "<invalid>";
@@ -488,28 +502,28 @@ 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) {
   std::string ClassName;
   if (OI.Rec->isSubClassOf("RegisterClass")) {
     ClassName = "Reg";
-  } else if (OI.Rec->isSubClassOf("Operand")) {
-    // FIXME: This should not be hard coded.
-    const RecordVal *RV = OI.Rec->getValue("Type");
-    
-    // FIXME: Yet another total hack.
-    if (RV->getValue()->getAsString() == "iPTR" ||
-        OI.Rec->getName() == "i8mem_NOREX" ||
-        OI.Rec->getName() == "lea32mem" ||
-        OI.Rec->getName() == "lea64mem" ||
-        OI.Rec->getName() == "i128mem" ||
-        OI.Rec->getName() == "sdmem" ||
-        OI.Rec->getName() == "ssmem" ||
-        OI.Rec->getName() == "lea64_32mem") {
-      ClassName = "Mem";
-    } else {
-      ClassName = "Imm";
+  } 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";
     }
   }
 
@@ -521,11 +535,9 @@ AsmMatcherInfo::getOperandClass(const StringRef &Token,
     if (ClassName == "Reg") {
       Entry->Kind = ClassInfo::Register;
     } else {
-      if (ClassName == "Mem")
-        Entry->Kind = ClassInfo::UserClass0;
-      else
-        Entry->Kind = ClassInfo::UserClass0 + 1;        
+      Entry->Kind = getUserClassKind(ClassName);
     }
+    Entry->ClassName = ClassName;
     Entry->Name = "MCK_" + ClassName;
     Entry->ValueName = OI.Rec->getName();
     Entry->PredicateMethod = "is" + ClassName;
@@ -665,7 +677,7 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
       for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
         Signature += "Imp";
 
-      Signature += Op.Class->Name;
+      Signature += Op.Class->ClassName;
       Signature += utostr(Op.OperandInfo->MINumOperands);
       Signature += "_" + utostr(MIOperandList[i].second);