summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TableGenFundamentals.html41
-rw-r--r--test/TableGen/defmclass.td36
-rw-r--r--utils/TableGen/TGParser.cpp50
3 files changed, 127 insertions, 0 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html
index f7a082d705..81f3cfe044 100644
--- a/docs/TableGenFundamentals.html
+++ b/docs/TableGenFundamentals.html
@@ -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
index 0000000000..ef8e8f794b
--- /dev/null
+++ b/test/TableGen/defmclass.td
@@ -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;
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index 49ff0b0c4c..3770848702 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -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();