summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TableGenFundamentals.html7
-rw-r--r--test/TableGen/DefmInherit.td32
-rw-r--r--utils/TableGen/TGParser.cpp144
3 files changed, 112 insertions, 71 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html
index 42839176cb..c9d1fa3b3f 100644
--- a/docs/TableGenFundamentals.html
+++ b/docs/TableGenFundamentals.html
@@ -632,9 +632,10 @@ Here is an example TableGen fragment that shows this idea:
<p>The name of the resultant definitions has the multidef fragment names
appended to them, so this defines <tt>ADD_rr</tt>, <tt>ADD_ri</tt>,
- <tt>SUB_rr</tt>, etc. Using a multiclass this way is exactly
- equivalent to instantiating the classes multiple times yourself,
- e.g. by writing:</p>
+ <tt>SUB_rr</tt>, etc. A defm may inherit from multiple multiclasses,
+ instantiating definitions from each multiclass. Using a multiclass
+ this way is exactly equivalent to instantiating the classes multiple
+ times yourself, e.g. by writing:</p>
<div class="doc_code">
<pre>
diff --git a/test/TableGen/DefmInherit.td b/test/TableGen/DefmInherit.td
new file mode 100644
index 0000000000..4f37edf056
--- /dev/null
+++ b/test/TableGen/DefmInherit.td
@@ -0,0 +1,32 @@
+// RUN: tblgen %s | grep {zing = 4} | count 4
+
+class C1<int A, string B> {
+ int bar = A;
+ string thestr = B;
+ int zing;
+}
+
+def T : C1<4, "blah">;
+
+multiclass t<int a> {
+ def S1 : C1<a, "foo"> {
+ int foo = 4;
+ let bar = 1;
+ }
+ def S2 : C1<a, "bar">;
+}
+
+multiclass s<int a> {
+ def S3 : C1<a, "moo"> {
+ int moo = 3;
+ let bar = 1;
+ }
+ def S4 : C1<a, "baz">;
+}
+
+defm FOO : t<42>, s<24>;
+
+def T4 : C1<6, "foo">;
+
+let zing = 4 in
+ defm BAZ : t<3>, s<4>;
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index 45ad5792f9..d7feb98d2a 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -1482,77 +1482,85 @@ bool TGParser::ParseDefm() {
TGLoc SubClassLoc = Lex.getLoc();
SubClassReference Ref = ParseSubClassReference(0, true);
- if (Ref.Rec == 0) return true;
-
- if (Lex.getCode() != tgtok::semi)
- return TokError("expected ';' at end of defm");
- Lex.Lex();
-
- // To instantiate a multiclass, we need to first get the multiclass, then
- // instantiate each def contained in the multiclass with the SubClassRef
- // template parameters.
- MultiClass *MC = MultiClasses[Ref.Rec->getName()];
- assert(MC && "Didn't lookup multiclass correctly?");
- std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
-
- // Verify that the correct number of template arguments were specified.
- const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs();
- if (TArgs.size() < TemplateVals.size())
- return Error(SubClassLoc,
- "more template args specified than multiclass expects");
-
- // Loop over all the def's in the multiclass, instantiating each one.
- for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
- Record *DefProto = MC->DefPrototypes[i];
-
- // Add the suffix to the defm name to get the new name.
- Record *CurRec = new Record(DefmPrefix + DefProto->getName(),DefmPrefixLoc);
-
- SubClassReference Ref;
- Ref.RefLoc = DefmPrefixLoc;
- Ref.Rec = DefProto;
- AddSubClass(CurRec, Ref);
-
- // Loop over all of the template arguments, setting them to the specified
- // value or leaving them as the default if necessary.
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- if (i < TemplateVals.size()) { // A value is specified for this temp-arg?
- // Set it now.
- if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(),
- TemplateVals[i]))
- return true;
-
- // Resolve it next.
- CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
-
- // Now remove it.
- CurRec->removeValue(TArgs[i]);
-
- } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
- return Error(SubClassLoc, "value not specified for template argument #"+
- utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" +
- MC->Rec.getName() + "'");
+
+ while (1) {
+ if (Ref.Rec == 0) return true;
+
+ // To instantiate a multiclass, we need to first get the multiclass, then
+ // instantiate each def contained in the multiclass with the SubClassRef
+ // template parameters.
+ MultiClass *MC = MultiClasses[Ref.Rec->getName()];
+ assert(MC && "Didn't lookup multiclass correctly?");
+ std::vector<Init*> &TemplateVals = Ref.TemplateArgs;
+
+ // Verify that the correct number of template arguments were specified.
+ const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs();
+ if (TArgs.size() < TemplateVals.size())
+ return Error(SubClassLoc,
+ "more template args specified than multiclass expects");
+
+ // Loop over all the def's in the multiclass, instantiating each one.
+ for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) {
+ Record *DefProto = MC->DefPrototypes[i];
+
+ // Add the suffix to the defm name to get the new name.
+ Record *CurRec = new Record(DefmPrefix + DefProto->getName(), DefmPrefixLoc);
+
+ SubClassReference Ref;
+ Ref.RefLoc = DefmPrefixLoc;
+ Ref.Rec = DefProto;
+ AddSubClass(CurRec, Ref);
+
+ // Loop over all of the template arguments, setting them to the specified
+ // value or leaving them as the default if necessary.
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ if (i < TemplateVals.size()) { // A value is specified for this temp-arg?
+ // Set it now.
+ if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(),
+ TemplateVals[i]))
+ return true;
+
+ // Resolve it next.
+ CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i]));
+
+ // Now remove it.
+ CurRec->removeValue(TArgs[i]);
+
+ } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) {
+ return Error(SubClassLoc, "value not specified for template argument #"+
+ utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" +
+ MC->Rec.getName() + "'");
+ }
}
+
+ // If the mdef is inside a 'let' expression, add to each def.
+ 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)) {
+ Error(DefmPrefixLoc, "when instantiating this defm");
+ return true;
+ }
+
+ // Ensure redefinition doesn't happen.
+ if (Records.getDef(CurRec->getName()))
+ return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
+ "' already defined, instantiating defm with subdef '" +
+ DefProto->getName() + "'");
+ Records.addDef(CurRec);
+ CurRec->resolveReferences();
}
-
- // If the mdef is inside a 'let' expression, add to each def.
- 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)) {
- Error(DefmPrefixLoc, "when instantiating this defm");
- return true;
- }
-
-
- // Ensure redefinition doesn't happen.
- if (Records.getDef(CurRec->getName()))
- return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
- "' already defined, instantiating defm with subdef '" +
- DefProto->getName() + "'");
- Records.addDef(CurRec);
- CurRec->resolveReferences();
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+
+ SubClassLoc = Lex.getLoc();
+ Ref = ParseSubClassReference(0, true);
}
+
+ if (Lex.getCode() != tgtok::semi)
+ return TokError("expected ';' at end of defm");
+ Lex.Lex();
return false;
}