[llvm-commits] [llvm] r69810 - in /llvm/trunk: docs/TableGenFundamentals.html test/TableGen/MultiClassInherit.td utils/TableGen/TGParser.cpp utils/TableGen/TGParser.h

David Greene greened at obbligato.org
Wed Apr 22 09:42:55 PDT 2009


Author: greened
Date: Wed Apr 22 11:42:54 2009
New Revision: 69810

URL: http://llvm.org/viewvc/llvm-project?rev=69810&view=rev
Log:
Implement multiclass inheritance.


Added:
    llvm/trunk/test/TableGen/MultiClassInherit.td
Modified:
    llvm/trunk/docs/TableGenFundamentals.html
    llvm/trunk/utils/TableGen/TGParser.cpp
    llvm/trunk/utils/TableGen/TGParser.h

Modified: llvm/trunk/docs/TableGenFundamentals.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGenFundamentals.html?rev=69810&r1=69809&r2=69810&view=diff

==============================================================================
--- llvm/trunk/docs/TableGenFundamentals.html (original)
+++ llvm/trunk/docs/TableGenFundamentals.html Wed Apr 22 11:42:54 2009
@@ -104,8 +104,10 @@
 as "Instruction".</p>
 
 <p><b>TableGen multiclasses</b> are groups of abstract records that are
-instantiated all at once.  Each instantiation can result in multiple TableGen
-definitions.</p>
+instantiated all at once.  Each instantiation can result in multiple
+TableGen definitions.  If a multiclass inherits from another multiclass,
+the definitions in the sub-multiclass become part of the current
+multiclass, as if they were declared in the current multiclass.</p>
 
 </div>
 

Added: llvm/trunk/test/TableGen/MultiClassInherit.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/MultiClassInherit.td?rev=69810&view=auto

==============================================================================
--- llvm/trunk/test/TableGen/MultiClassInherit.td (added)
+++ llvm/trunk/test/TableGen/MultiClassInherit.td Wed Apr 22 11:42:54 2009
@@ -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, int b> : t<a> {
+  def S3 : C1<b, "moo"> {
+    int moo = 3;
+    let bar = 1;
+  }
+  def S4 : C1<b, "baz">;
+}
+
+defm FOO : s<42, 24>;
+
+def T4 : C1<6, "foo">;
+
+let zing = 4 in
+  defm BAZ : s<3, 4>;

Modified: llvm/trunk/utils/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=69810&r1=69809&r2=69810&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.cpp (original)
+++ llvm/trunk/utils/TableGen/TGParser.cpp Wed Apr 22 11:42:54 2009
@@ -25,7 +25,8 @@
 namespace llvm {
 struct MultiClass {
   Record Rec;  // Placeholder for template args and Name.
-  std::vector<Record*> DefPrototypes;
+  typedef std::vector<Record*> RecordVector;
+  RecordVector DefPrototypes;
     
   MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
 };
@@ -38,6 +39,15 @@
   
   bool isInvalid() const { return Rec == 0; }
 };
+
+struct SubMultiClassReference {
+  TGLoc RefLoc;
+  MultiClass *MC;
+  std::vector<Init*> TemplateArgs;
+  SubMultiClassReference() : MC(0) {}
+  
+  bool isInvalid() const { return MC == 0; }
+};
   
 } // end namespace llvm
 
@@ -177,6 +187,85 @@
   return false;
 }
 
+/// AddSubMultiClass - Add SubMultiClass as a subclass to
+/// CurMultiClass, resolving its template args as SubMultiClass's
+/// template arguments.
+bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassReference &SubMultiClass) {
+  MultiClass *SMC = SubMultiClass.MC;
+  Record *CurRec = &CurMultiClass->Rec;
+
+  const std::vector<RecordVal> &MCVals = CurMultiClass->Rec.getValues();
+
+  // Add all of the values in the subclass into the current class.
+  const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
+  for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
+    if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i]))
+      return true;
+
+  // Add all of the defs in the subclass into the current multiclass.
+  for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(),
+         iend = SMC->DefPrototypes.end();
+       i != iend;
+       ++i) {
+    // Clone the def and add it to the current multiclass
+    Record *NewDef = new Record(**i);
+
+    // Add all of the values in the superclass into the current def.
+    for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
+      if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i]))
+        return true;
+
+    CurMultiClass->DefPrototypes.push_back(NewDef);
+  }
+  
+  const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs();
+
+  // Ensure that an appropriate number of template arguments are specified.
+  if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size())
+    return Error(SubMultiClass.RefLoc, "More template args specified than expected");
+  
+  // 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 = SMCTArgs.size(); i != e; ++i) {
+    if (i < SubMultiClass.TemplateArgs.size()) {
+      // If a value is specified for this template arg, set it in the superclass now.
+      if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], std::vector<unsigned>(), 
+                   SubMultiClass.TemplateArgs[i]))
+        return true;
+
+      // Resolve it next.
+      CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
+      
+      // Now remove it.
+      CurRec->removeValue(SMCTArgs[i]);
+
+      // If a value is specified for this template arg, set it in the defs now.
+      for (MultiClass::RecordVector::iterator j = CurMultiClass->DefPrototypes.begin(),
+             jend = CurMultiClass->DefPrototypes.end();
+           j != jend;
+           ++j) {
+        Record *Def = *j;
+
+        if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], std::vector<unsigned>(), 
+                     SubMultiClass.TemplateArgs[i]))
+          return true;
+
+        // Resolve it next.
+        Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
+
+        // Now remove it
+        Def->removeValue(SMCTArgs[i]);
+      }
+    } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
+      return Error(SubMultiClass.RefLoc,"Value not specified for template argument #"
+                   + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" + 
+                   SMC->Rec.getName() + "'!");
+    }
+  }
+
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 // Parser Code
 //===----------------------------------------------------------------------===//
@@ -223,6 +312,25 @@
   return Result;
 }
 
+/// ParseMultiClassID - Parse and resolve a reference to a multiclass name.  This returns
+/// null on error.
+///
+///    MultiClassID ::= ID
+///
+MultiClass *TGParser::ParseMultiClassID() {
+  if (Lex.getCode() != tgtok::Id) {
+    TokError("expected name for ClassID");
+    return 0;
+  }
+  
+  MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
+  if (Result == 0)
+    TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
+  
+  Lex.Lex();
+  return Result;
+}
+
 Record *TGParser::ParseDefmID() {
   if (Lex.getCode() != tgtok::Id) {
     TokError("expected multiclass name");
@@ -285,6 +393,47 @@
   return Result;
 }
 
+/// ParseSubMultiClassReference - Parse a reference to a subclass or to a templated
+/// submulticlass.  This returns a SubMultiClassRefTy with a null Record* on error.
+///
+///  SubMultiClassRef ::= MultiClassID
+///  SubMultiClassRef ::= MultiClassID '<' ValueList '>'
+///
+SubMultiClassReference TGParser::
+ParseSubMultiClassReference(MultiClass *CurMC) {
+  SubMultiClassReference Result;
+  Result.RefLoc = Lex.getLoc();
+  
+  Result.MC = ParseMultiClassID();
+  if (Result.MC == 0) return Result;
+  
+  // If there is no template arg list, we're done.
+  if (Lex.getCode() != tgtok::less)
+    return Result;
+  Lex.Lex();  // Eat the '<'
+  
+  if (Lex.getCode() == tgtok::greater) {
+    TokError("subclass reference requires a non-empty list of template values");
+    Result.MC = 0;
+    return Result;
+  }
+  
+  Result.TemplateArgs = ParseValueList(&CurMC->Rec);
+  if (Result.TemplateArgs.empty()) {
+    Result.MC = 0;   // Error parsing value list.
+    return Result;
+  }
+    
+  if (Lex.getCode() != tgtok::greater) {
+    TokError("expected '>' in template value list");
+    Result.MC = 0;
+    return Result;
+  }
+  Lex.Lex();
+
+  return Result;
+}
+
 /// ParseRangePiece - Parse a bit/value range.
 ///   RangePiece ::= INTVAL
 ///   RangePiece ::= INTVAL '-' INTVAL
@@ -1231,7 +1380,7 @@
 
 /// ParseMultiClass - Parse a multiclass definition.
 ///
-///  MultiClassInst ::= MULTICLASS ID TemplateArgList? '{' MultiClassDef+ '}'
+///  MultiClassInst ::= MULTICLASS ID TemplateArgList? ':' BaseMultiClassList '{' MultiClassDef+ '}'
 ///
 bool TGParser::ParseMultiClass() {
   assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
@@ -1252,6 +1401,26 @@
     if (ParseTemplateArgList(0))
       return true;
 
+  // If there are submulticlasses, parse them.
+  if (Lex.getCode() == tgtok::colon) {
+    Lex.Lex();
+    
+    // Read all of the submulticlasses.
+    SubMultiClassReference SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
+    while (1) {
+      // Check for error.
+      if (SubMultiClass.MC == 0) return true;
+     
+      // Add it.
+      if (AddSubMultiClass(CurMultiClass, SubMultiClass))
+        return true;
+      
+      if (Lex.getCode() != tgtok::comma) break;
+      Lex.Lex(); // eat ','.
+      SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
+    }
+  }
+
   if (Lex.getCode() != tgtok::l_brace)
     return TokError("expected '{' in multiclass definition");
 

Modified: llvm/trunk/utils/TableGen/TGParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.h?rev=69810&r1=69809&r2=69810&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.h (original)
+++ llvm/trunk/utils/TableGen/TGParser.h Wed Apr 22 11:42:54 2009
@@ -25,6 +25,7 @@
   struct Init;
   struct MultiClass;
   struct SubClassReference;
+  struct SubMultiClassReference;
   
   struct LetRecord {
     std::string Name;
@@ -46,7 +47,6 @@
   /// current value.
   MultiClass *CurMultiClass;
 public:
-  
   TGParser(TGSourceMgr &SrcMgr) : Lex(SrcMgr), CurMultiClass(0) {}
   
   void setIncludeDirs(const std::vector<std::string> &D){Lex.setIncludeDirs(D);}
@@ -67,6 +67,7 @@
   bool SetValue(Record *TheRec, TGLoc Loc, const std::string &ValName, 
                 const std::vector<unsigned> &BitList, Init *V);
   bool AddSubClass(Record *Rec, SubClassReference &SubClass);
+  bool AddSubMultiClass(MultiClass *MV, class SubMultiClassReference &SubMultiClass);
 
 private:  // Parser methods.
   bool ParseObjectList();
@@ -87,6 +88,7 @@
   std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
 
   SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
+  SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMultiClass);
 
   Init *ParseIDValue(Record *CurRec);
   Init *ParseIDValue(Record *CurRec, const std::string &Name, TGLoc NameLoc);
@@ -101,6 +103,7 @@
   RecTy *ParseType();
   std::string ParseObjectName();
   Record *ParseClassID();
+  MultiClass *ParseMultiClassID();
   Record *ParseDefmID();
 };
   





More information about the llvm-commits mailing list