From 5654613a013b94a92f9ed65e1a2f34e0a8d9cfdf Mon Sep 17 00:00:00 2001 From: David Greene Date: Wed, 22 Apr 2009 22:17:51 +0000 Subject: [PATCH] Allow defm to inherit from multiple multiclasses. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69832 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/TableGenFundamentals.html | 7 +- test/TableGen/DefmInherit.td | 32 ++++++++ utils/TableGen/TGParser.cpp | 144 +++++++++++++++++---------------- 3 files changed, 112 insertions(+), 71 deletions(-) create mode 100644 test/TableGen/DefmInherit.td diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index 42839176cbf..c9d1fa3b3f1 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -632,9 +632,10 @@ Here is an example TableGen fragment that shows this idea:

The name of the resultant definitions has the multidef fragment names appended to them, so this defines ADD_rr, ADD_ri, - SUB_rr, etc. Using a multiclass this way is exactly - equivalent to instantiating the classes multiple times yourself, - e.g. by writing:

+ SUB_rr, 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:

diff --git a/test/TableGen/DefmInherit.td b/test/TableGen/DefmInherit.td
new file mode 100644
index 00000000000..4f37edf056c
--- /dev/null
+++ b/test/TableGen/DefmInherit.td
@@ -0,0 +1,32 @@
+// RUN: tblgen %s | grep {zing = 4} | count 4
+
+class C1 { 
+  int bar = A;
+  string thestr = B;
+  int zing;
+}
+
+def T : C1<4, "blah">;
+
+multiclass t {
+  def S1 : C1 {
+    int foo = 4;
+    let bar = 1;
+  }
+  def S2 : C1;
+}
+
+multiclass s {
+  def S3 : C1 {
+    int moo = 3;
+    let bar = 1;
+  }
+  def S4 : C1;
+}
+
+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 45ad5792f98..d7feb98d2a0 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -1482,78 +1482,86 @@ bool TGParser::ParseDefm() {
 
   TGLoc SubClassLoc = Lex.getLoc();
   SubClassReference Ref = ParseSubClassReference(0, true);
-  if (Ref.Rec == 0) return true;
-  
+
+  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 &TemplateVals = Ref.TemplateArgs;   
+
+    // Verify that the correct number of template arguments were specified.
+    const std::vector &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(),
+                       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 (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();
   
-  // 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 &TemplateVals = Ref.TemplateArgs;
-  
-  // Verify that the correct number of template arguments were specified.
-  const std::vector &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(),
-                     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();
-  }
-  
   return false;
 }