llvm-mc/AsmParser: Implement user defined super classes.
authorDaniel Dunbar <daniel@zuster.org>
Sun, 9 Aug 2009 07:20:21 +0000 (07:20 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Sun, 9 Aug 2009 07:20:21 +0000 (07:20 +0000)
 - We can now discriminate SUB32ri8 from SUB32ri, for example.

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

lib/Target/X86/AsmParser/X86AsmParser.cpp
lib/Target/X86/X86InstrInfo.td
test/MC/AsmParser/x86_instructions.s
utils/TableGen/AsmMatcherEmitter.cpp

index ea5528a951a00b08ce18c40f640a0cbc667ec24a..5a42683a4948a8bbaebf9af7e472eb97169839be 100644 (file)
@@ -137,6 +137,19 @@ struct X86Operand {
 
   bool isImm() const { return Kind == Immediate; }
   
+  bool isImmSExt8() const { 
+    // Accept immediates which fit in 8 bits when sign extended, and
+    // non-absolute immediates.
+    if (!isImm())
+      return false;
+
+    if (!getImm().isAbsolute())
+      return true;
+
+    int64_t Value = getImm().getConstant();
+    return Value == (int64_t) (int8_t) Value;
+  }
+  
   bool isMem() const { return Kind == Memory; }
 
   bool isReg() const { return Kind == Register; }
@@ -151,6 +164,12 @@ struct X86Operand {
     Inst.addOperand(MCOperand::CreateMCValue(getImm()));
   }
 
+  void addImmSExt8Operands(MCInst &Inst, unsigned N) {
+    // FIXME: Support user customization of the render method.
+    assert(N == 1 && "Invalid number of operands!");
+    Inst.addOperand(MCOperand::CreateMCValue(getImm()));
+  }
+
   void addMemOperands(MCInst &Inst, unsigned N) {
     assert((N == 4 || N == 5) && "Invalid number of operands!");
 
index c21cad98df01d1df583a37f2491517e0ac478278..80f03e8318c33b08df10f9de3fdef4f80de27099 100644 (file)
@@ -212,9 +212,15 @@ def piclabel: Operand<i32> {
 
 // A couple of more descriptive operand definitions.
 // 16-bits but only 8 bits are significant.
-def i16i8imm  : Operand<i16>;
+def i16i8imm  : Operand<i16> {
+  let ParserMatchClass = "ImmSExt8";
+  let ParserMatchSuperClass = "Imm";
+}
 // 32-bits but only 8 bits are significant.
-def i32i8imm  : Operand<i32>;
+def i32i8imm  : Operand<i32> {
+  let ParserMatchClass = "ImmSExt8";
+  let ParserMatchSuperClass = "Imm";
+}
 
 // Branch targets have OtherVT type and print as pc-relative values.
 def brtarget : Operand<OtherVT> {
index ffd2dde0f1fdbfae815993a0fcdf9738db8b9097..57d9decaf232c4829960b806e195b41cfb764a99 100644 (file)
         movl %eax, 10(%ebp, %ebx, 4)
 // RUN: grep {MCInst(opcode=.*, operands=.reg:0, imm:4, reg:21, val:10, reg:0, reg:19.)} %t
         movl %eax, 10(, %ebx, 4)
+
+// FIXME: Check that this matches SUB32ri8
+// RUN: grep {MCInst(opcode=.*, operands=.reg:19, reg:0, val:1.)} %t
+        subl $1, %eax
+        
+// FIXME: Check that this matches SUB32ri8
+// RUN: grep {MCInst(opcode=.*, operands=.reg:19, reg:0, val:-1.)} %t
+        subl $-1, %eax
+        
+// FIXME: Check that this matches SUB32ri
+// RUN: grep {MCInst(opcode=.*, operands=.reg:19, reg:0, val:256.)} %t
+        subl $256, %eax
+
+        
index aafc09fcd6ebae7df06915a4fbe2ee615097a6b7..f6458541105f8ce29784a785e64118d3b236a2e2 100644 (file)
@@ -289,6 +289,12 @@ struct ClassInfo {
   /// N) for the Nth user defined class.
   unsigned Kind;
 
+  /// SuperClassKind - The super class kind for user classes.
+  unsigned SuperClassKind;
+
+  /// SuperClass - The super class, or 0.
+  ClassInfo *SuperClass;
+
   /// Name - The full class name, suitable for use in an enum.
   std::string Name;
 
@@ -308,27 +314,40 @@ struct ClassInfo {
   /// MCInst; this is not valid for Token kinds.
   std::string RenderMethod;
 
+  /// isUserClass() - Check if this is a user defined class.
+  bool isUserClass() const {
+    return Kind >= UserClass0;
+  }
+
+  /// getRootClass - Return the root class of this one.
+  const ClassInfo *getRootClass() const {
+    const ClassInfo *CI = this;
+    while (CI->SuperClass)
+      CI = CI->SuperClass;
+    return CI;
+  }
+
   /// operator< - Compare two classes.
   bool operator<(const ClassInfo &RHS) const {
-    // Incompatible kinds are comparable.
-    if (Kind != RHS.Kind)
+    // Incompatible kinds are comparable for classes in disjoint hierarchies.
+    if (Kind != RHS.Kind && getRootClass() != RHS.getRootClass())
       return Kind < RHS.Kind;
 
     switch (Kind) {
     case Invalid:
       assert(0 && "Invalid kind!");
     case Token:
-      // Tokens are always comparable.
+      // Tokens are comparable by value.
       //
       // FIXME: Compare by enum value.
       return ValueName < RHS.ValueName;
 
-    case Register:
-      // FIXME: Compare by subset relation.
-      return false;
-
     default:
-      // FIXME: Allow user defined relation.
+      // This class preceeds the RHS if the RHS is a super class.
+      for (ClassInfo *Parent = SuperClass; Parent; Parent = Parent->SuperClass)
+        if (Parent == &RHS)
+          return true;
+
       return false;
     }
   }
@@ -525,6 +544,7 @@ unsigned AsmMatcherInfo::getUserClassKind(const StringRef &Name) {
 ClassInfo *
 AsmMatcherInfo::getOperandClass(const StringRef &Token,
                                 const CodeGenInstruction::OperandInfo &OI) {
+  unsigned SuperClass = ClassInfo::Invalid;
   std::string ClassName;
   if (OI.Rec->isSubClassOf("RegisterClass")) {
     ClassName = "Reg";
@@ -536,17 +556,24 @@ AsmMatcherInfo::getOperandClass(const StringRef &Token,
       PrintError(OI.Rec->getLoc(), "operand has no match class!");
       ClassName = "Invalid";
     }
+
+    // Determine the super class.
+    try {
+      std::string SuperClassName =
+        OI.Rec->getValueAsString("ParserMatchSuperClass");
+      SuperClass = getUserClassKind(SuperClassName);
+    } catch(...) { }
   }
 
   ClassInfo *&Entry = OperandClasses[ClassName];
   
   if (!Entry) {
     Entry = new ClassInfo();
-    // FIXME: Hack.
     if (ClassName == "Reg") {
       Entry->Kind = ClassInfo::Register;
     } else {
       Entry->Kind = getUserClassKind(ClassName);
+      Entry->SuperClassKind = SuperClass;
     }
     Entry->ClassName = ClassName;
     Entry->Name = "MCK_" + ClassName;
@@ -622,6 +649,27 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
 
     Instructions.push_back(II.take());
   }
+
+  // Bind user super classes.
+  std::map<unsigned, ClassInfo*> UserClasses;
+  for (unsigned i = 0, e = Classes.size(); i != e; ++i) {
+    ClassInfo &CI = *Classes[i];
+    if (CI.isUserClass())
+      UserClasses[CI.Kind] = &CI;
+  }
+
+  for (unsigned i = 0, e = Classes.size(); i != e; ++i) {
+    ClassInfo &CI = *Classes[i];
+    if (CI.isUserClass() && CI.SuperClassKind != ClassInfo::Invalid) {
+      CI.SuperClass = UserClasses[CI.SuperClassKind];
+      assert(CI.SuperClass && "Missing super class definition!");
+    } else {
+      CI.SuperClass = 0;
+    }
+  }
+
+  // Reorder classes so that classes preceed super classes.
+  std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
 }
 
 static void EmitConvertToMCInst(CodeGenTarget &Target,
@@ -790,8 +838,22 @@ static void EmitClassifyOperand(CodeGenTarget &Target,
     ClassInfo &CI = **it;
 
     if (CI.Kind != ClassInfo::Token) {
-      OS << "  if (Operand." << CI.PredicateMethod << "())\n";
+      OS << "  // '" << CI.ClassName << "' class";
+      if (CI.SuperClass) {
+        OS << ", subclass of '" << CI.SuperClass->ClassName << "'";
+        assert(CI < *CI.SuperClass && "Invalid class relation!");
+      }
+      OS << "\n";
+
+      OS << "  if (Operand." << CI.PredicateMethod << "()) {\n";
+      
+      // Validate subclass relationships.
+      if (CI.SuperClass)
+        OS << "    assert(Operand." << CI.SuperClass->PredicateMethod
+           << "() && \"Invalid class relationship!\");\n";
+
       OS << "    return " << CI.Name << ";\n\n";
+      OS << "  }";
     }
   }
   OS << "  return InvalidMatchClass;\n";