[llvm-commits] [llvm] r78530 - in /llvm/trunk: lib/Target/X86/AsmParser/X86AsmParser.cpp lib/Target/X86/X86InstrInfo.td test/MC/AsmParser/x86_instructions.s utils/TableGen/AsmMatcherEmitter.cpp

Daniel Dunbar daniel at zuster.org
Sun Aug 9 00:20:21 PDT 2009


Author: ddunbar
Date: Sun Aug  9 02:20:21 2009
New Revision: 78530

URL: http://llvm.org/viewvc/llvm-project?rev=78530&view=rev
Log:
llvm-mc/AsmParser: Implement user defined super classes.
 - We can now discriminate SUB32ri8 from SUB32ri, for example.

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

Modified: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp?rev=78530&r1=78529&r2=78530&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp Sun Aug  9 02:20:21 2009
@@ -137,6 +137,19 @@
 
   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 @@
     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!");
 

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=78530&r1=78529&r2=78530&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Sun Aug  9 02:20:21 2009
@@ -212,9 +212,15 @@
 
 // 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> {

Modified: llvm/trunk/test/MC/AsmParser/x86_instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/x86_instructions.s?rev=78530&r1=78529&r2=78530&view=diff

==============================================================================
--- llvm/trunk/test/MC/AsmParser/x86_instructions.s (original)
+++ llvm/trunk/test/MC/AsmParser/x86_instructions.s Sun Aug  9 02:20:21 2009
@@ -16,3 +16,17 @@
         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
+
+        

Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=78530&r1=78529&r2=78530&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Sun Aug  9 02:20:21 2009
@@ -289,6 +289,12 @@
   /// 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 @@
   /// 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 @@
 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 @@
       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 @@
 
     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 @@
     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";





More information about the llvm-commits mailing list