Teach tablegen how to inherit from classes in 'defm' definitions.
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 18 Jun 2010 19:53:41 +0000 (19:53 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Fri, 18 Jun 2010 19:53:41 +0000 (19:53 +0000)
The rule is simple: only inherit from a class list if they come
in the end, after the last multiclass.

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

docs/TableGenFundamentals.html
test/TableGen/defmclass.td [new file with mode: 0644]
utils/TableGen/TGParser.cpp

index f7a082d7050e9ed3fe018947e03a4caabf555549..81f3cfe0448d8d735811572b1c52d5749ae9e389 100644 (file)
@@ -732,6 +732,47 @@ multiclass instanciations.
 </pre>
 </div>
 
+<p>
+defm declarations can inherit from classes too, the
+rule to follow is that the class list must start after the
+last multiclass, and there must be at least one multiclass
+before them.
+</p>
+
+<div class="doc_code">
+<pre>
+<b>class</b> XD { bits&lt;4&gt; Prefix = 11; }
+<b>class</b> XS { bits&lt;4&gt; Prefix = 12; }
+
+<b>class</b> I&lt;bits<4&gt; op> {
+  bits&lt;4&gt; opcode = op;
+}
+
+<b>multiclass</b> R {
+  <b>def</b> rr : I&lt;4&gt;;
+  <b>def</b> rm : I&lt;2&gt;;
+}
+
+<b>multiclass</b> Y {
+  <b>defm</b> SS : R, XD;
+  <b>defm</b> SD : R, XS;
+}
+
+<b>defm</b> Instr : Y;
+
+<i>// Results</i>
+<b>def</b> InstrSDrm {
+  bits&lt;4&gt; opcode = { 0, 0, 1, 0 };
+  bits&lt;4&gt; Prefix = { 1, 1, 0, 0 };
+}
+...
+<b>def</b> InstrSSrr {
+  bits&lt;4&gt; opcode = { 0, 1, 0, 0 };
+  bits&lt;4&gt; Prefix = { 1, 0, 1, 1 };
+}
+</pre>
+</div>
+
 </div>
 
 <!-- ======================================================================= -->
diff --git a/test/TableGen/defmclass.td b/test/TableGen/defmclass.td
new file mode 100644 (file)
index 0000000..ef8e8f7
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: tblgen %s | FileCheck %s
+// XFAIL: vg_leak
+
+class XD { bits<4> Prefix = 11; }
+// CHECK: Prefix = { 1, 1, 0, 0 };
+class XS { bits<4> Prefix = 12; }
+class VEX { bit hasVEX_4VPrefix = 1; }
+
+def xd : XD;
+
+class BaseI {
+  bits<4> Prefix = 0;
+  bit hasVEX_4VPrefix = 0;
+}
+
+class I<bits<4> op> : BaseI {
+  bits<4> opcode = op;
+  int val = !if(!eq(Prefix, xd.Prefix), 7, 21);
+}
+
+multiclass R {
+  def rr : I<4>;
+}
+
+multiclass M {
+  def rm : I<2>;
+}
+
+multiclass Y {
+  defm SS : R, M, XD;
+// CHECK: Prefix = { 1, 1, 0, 0 };
+// CHECK: Prefix = { 1, 1, 0, 0 };
+  defm SD : R, M, XS;
+}
+
+defm Instr : Y, VEX;
index 49ff0b0c4cd112aea98ff9becebd72e650b05763..3770848702c151e79eeae1746de570a527855903 100644 (file)
@@ -1907,6 +1907,12 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
   if (Lex.Lex() != tgtok::colon)
     return TokError("expected ':' after defm identifier");
 
+  // Keep track of the new generated record definitions.
+  std::vector<Record*> NewRecDefs;
+
+  // This record also inherits from a regular class (non-multiclass)?
+  bool InheritFromClass = false;
+
   // eat the colon.
   Lex.Lex();
 
@@ -2016,15 +2022,59 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
         Records.addDef(CurRec);
         CurRec->resolveReferences();
       }
+
+      NewRecDefs.push_back(CurRec);
     }
 
     if (Lex.getCode() != tgtok::comma) break;
     Lex.Lex(); // eat ','.
 
     SubClassLoc = Lex.getLoc();
+
+    // A defm can inherit from regular classes (non-multiclass) as
+    // long as they come in the end of the inheritance list.
+    InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
+
+    if (InheritFromClass)
+      break;
+
     Ref = ParseSubClassReference(0, true);
   }
 
+  if (InheritFromClass) {
+    // Process all the classes to inherit as if they were part of a
+    // regular 'def' and inherit all record values.
+    SubClassReference SubClass = ParseSubClassReference(0, false);
+    while (1) {
+      // Check for error.
+      if (SubClass.Rec == 0) return true;
+
+      // Get the expanded definition prototypes and teach them about
+      // the record values the current class to inherit has
+      for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
+        Record *CurRec = NewRecDefs[i];
+
+        // Add it.
+        if (AddSubClass(CurRec, SubClass))
+          return true;
+
+        // Process any variables on the let stack.
+        for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+          for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+            if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
+                         LetStack[i][j].Bits, LetStack[i][j].Value))
+              return true;
+
+        if (!CurMultiClass)
+          CurRec->resolveReferences();
+      }
+
+      if (Lex.getCode() != tgtok::comma) break;
+      Lex.Lex(); // eat ','.
+      SubClass = ParseSubClassReference(0, false);
+    }
+  }
+
   if (Lex.getCode() != tgtok::semi)
     return TokError("expected ';' at end of defm");
   Lex.Lex();