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

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Wed Jun 9 19:42:59 PDT 2010


Author: bruno
Date: Wed Jun  9 21:42:59 2010
New Revision: 105776

URL: http://llvm.org/viewvc/llvm-project?rev=105776&view=rev
Log:
Teach tablegen to allow "let" expressions inside multiclasses,
providing more ways to factor out commonality from the records.

Added:
    llvm/trunk/test/TableGen/LetInsideMultiClasses.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=105776&r1=105775&r2=105776&view=diff
==============================================================================
--- llvm/trunk/docs/TableGenFundamentals.html (original)
+++ llvm/trunk/docs/TableGenFundamentals.html Wed Jun  9 21:42:59 2010
@@ -798,6 +798,32 @@
 need to be added to several records, and the records do not otherwise need to be
 opened, as in the case with the <tt>CALL*</tt> instructions above.</p>
 
+<p>It's also possible to use "let" expressions inside multiclasses, providing
+more ways to factor out commonality from the records, specially if using
+several levels of multiclass instanciations. This also avoids the need of using
+"let" expressions within subsequent records inside a multiclass.</p> 
+
+<div class="doc_code">
+<pre>
+<b>multiclass </b>basic_r<bits<4> opc> {
+  <b>let </b>Predicates = [HasSSE2] in {
+    <b>def </b>rr : Instruction<opc, "rr">;
+    <b>def </b>rm : Instruction<opc, "rm">;
+  }
+  <b>let </b>Predicates = [HasSSE3] in
+    <b>def </b>rx : Instruction<opc, "rx">;
+}
+
+<b>multiclass </b>basic_ss<bits<4> opc> {
+  <b>let </b>IsDouble = 0 in
+    <b>defm </b>SS : basic_r<opc>;
+
+  <b>let </b>IsDouble = 1 in
+    <b>defm </b>SD : basic_r<opc>;
+}
+
+<b>defm </b>ADD : basic_ss<0xf>;
+</pre>
 </div>
 
 <!-- *********************************************************************** -->

Added: llvm/trunk/test/TableGen/LetInsideMultiClasses.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/LetInsideMultiClasses.td?rev=105776&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/LetInsideMultiClasses.td (added)
+++ llvm/trunk/test/TableGen/LetInsideMultiClasses.td Wed Jun  9 21:42:59 2010
@@ -0,0 +1,29 @@
+// RUN: tblgen %s | grep "bit IsDouble = 1;" | count 3
+// XFAIL: vg_leak
+
+class Instruction<bits<4> opc, string Name> {
+  bits<4> opcode = opc;
+  string name = Name;
+  bit IsDouble = 0;
+}
+
+multiclass basic_r<bits<4> opc> {
+  let name = "newname" in {
+    def rr : Instruction<opc, "rr">;
+    def rm : Instruction<opc, "rm">;
+  }
+
+  let name = "othername" in
+    def rx : Instruction<opc, "rx">;
+}
+
+multiclass basic_ss<bits<4> opc> {
+  let IsDouble = 0 in
+    defm SS : basic_r<opc>;
+
+  let IsDouble = 1 in
+    defm SD : basic_r<opc>;
+}
+
+defm ADD : basic_ss<0xf>;
+

Modified: llvm/trunk/utils/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=105776&r1=105775&r2=105776&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.cpp (original)
+++ llvm/trunk/utils/TableGen/TGParser.cpp Wed Jun  9 21:42:59 2010
@@ -1640,7 +1640,7 @@
 ///
 ///   DefInst ::= DEF ObjectName ObjectBody
 ///
-llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
+bool TGParser::ParseDef(MultiClass *CurMultiClass) {
   SMLoc DefLoc = Lex.getLoc();
   assert(Lex.getCode() == tgtok::Def && "Unknown tok");
   Lex.Lex();  // Eat the 'def' token.
@@ -1654,7 +1654,7 @@
     // Ensure redefinition doesn't happen.
     if (Records.getDef(CurRec->getName())) {
       Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
-      return 0;
+      return true;
     }
     Records.addDef(CurRec);
   } else {
@@ -1663,20 +1663,33 @@
       if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
         Error(DefLoc, "def '" + CurRec->getName() +
               "' already defined in this multiclass!");
-        return 0;
+        return true;
       }
     CurMultiClass->DefPrototypes.push_back(CurRec);
   }
 
   if (ParseObjectBody(CurRec))
-    return 0;
+    return true;
 
   if (CurMultiClass == 0)  // Def's in multiclasses aren't really defs.
     CurRec->resolveReferences();
 
   // If ObjectBody has template arguments, it's an error.
   assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
-  return CurRec;
+
+  if (CurMultiClass) {
+    // Copy the template arguments for the multiclass into the def.
+    const std::vector<std::string> &TArgs =
+                                CurMultiClass->Rec.getTemplateArgs();
+
+    for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+      const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+      assert(RV && "Template arg doesn't exist?");
+      CurRec->addValue(*RV);
+    }
+  }
+
+  return false;
 }
 
 
@@ -1757,12 +1770,12 @@
 }
 
 /// ParseTopLevelLet - Parse a 'let' at top level.  This can be a couple of
-/// different related productions.
+/// different related productions. This works inside multiclasses too.
 ///
 ///   Object ::= LET LetList IN '{' ObjectList '}'
 ///   Object ::= LET LetList IN Object
 ///
-bool TGParser::ParseTopLevelLet() {
+bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
   assert(Lex.getCode() == tgtok::Let && "Unexpected token");
   Lex.Lex();
 
@@ -1778,7 +1791,7 @@
   // If this is a scalar let, just handle it now
   if (Lex.getCode() != tgtok::l_brace) {
     // LET LetList IN Object
-    if (ParseObject())
+    if (ParseObject(CurMultiClass))
       return true;
   } else {   // Object ::= LETCommand '{' ObjectList '}'
     SMLoc BraceLoc = Lex.getLoc();
@@ -1786,7 +1799,7 @@
     Lex.Lex();  // eat the '{'.
 
     // Parse the object list.
-    if (ParseObjectList())
+    if (ParseObjectList(CurMultiClass))
       return true;
 
     if (Lex.getCode() != tgtok::r_brace) {
@@ -1801,27 +1814,6 @@
   return false;
 }
 
-/// ParseMultiClassDef - Parse a def in a multiclass context.
-///
-///  MultiClassDef ::= DefInst
-///
-bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
-
-  Record *D = ParseDef(CurMC);
-  if (D == 0) return true;
-
-  // Copy the template arguments for the multiclass into the def.
-  const std::vector<std::string> &TArgs = CurMC->Rec.getTemplateArgs();
-
-  for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
-    const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]);
-    assert(RV && "Template arg doesn't exist?");
-    D->addValue(*RV);
-  }
-
-  return false;
-}
-
 /// ParseMultiClass - Parse a multiclass definition.
 ///
 ///  MultiClassInst ::= MULTICLASS ID TemplateArgList?
@@ -1883,18 +1875,17 @@
       return TokError("multiclass must contain at least one def");
 
     while (Lex.getCode() != tgtok::r_brace) {
-      if (Lex.getCode() != tgtok::Defm && Lex.getCode() != tgtok::Def)
-        return TokError("expected 'def' or 'defm' in multiclass body");
-
-      if (Lex.getCode() == tgtok::Def)
-        if (ParseMultiClassDef(CurMultiClass))
-          return true;
-
-      if (Lex.getCode() == tgtok::Defm)
-        if (ParseDefm(CurMultiClass))
-          return true;
+      switch (Lex.getCode()) {
+        default:
+          return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+        case tgtok::Let:
+        case tgtok::Def:
+        case tgtok::Defm:
+          if (ParseObject(CurMultiClass))
+            return true;
+         break;
+      }
     }
-
     Lex.Lex();  // eat the '}'.
   }
 
@@ -2048,12 +2039,12 @@
 ///   Object ::= DefMInst
 ///   Object ::= LETCommand '{' ObjectList '}'
 ///   Object ::= LETCommand Object
-bool TGParser::ParseObject() {
+bool TGParser::ParseObject(MultiClass *MC) {
   switch (Lex.getCode()) {
   default: assert(0 && "This is not an object");
-  case tgtok::Let:   return ParseTopLevelLet();
-  case tgtok::Def:   return ParseDef(0) == 0;
-  case tgtok::Defm:  return ParseDefm();
+  case tgtok::Let:   return ParseTopLevelLet(MC);
+  case tgtok::Def:   return ParseDef(MC);
+  case tgtok::Defm:  return ParseDefm(MC);
   case tgtok::Class: return ParseClass();
   case tgtok::MultiClass: return ParseMultiClass();
   }
@@ -2061,9 +2052,9 @@
 
 /// ParseObjectList
 ///   ObjectList :== Object*
-bool TGParser::ParseObjectList() {
+bool TGParser::ParseObjectList(MultiClass *MC) {
   while (isObjectStart(Lex.getCode())) {
-    if (ParseObject())
+    if (ParseObject(MC))
       return true;
   }
   return false;

Modified: llvm/trunk/utils/TableGen/TGParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.h?rev=105776&r1=105775&r2=105776&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/TGParser.h (original)
+++ llvm/trunk/utils/TableGen/TGParser.h Wed Jun  9 21:42:59 2010
@@ -69,16 +69,15 @@
                         SubMultiClassReference &SubMultiClass);
 
 private:  // Parser methods.
-  bool ParseObjectList();
-  bool ParseObject();
+  bool ParseObjectList(MultiClass *MC = 0);
+  bool ParseObject(MultiClass *MC);
   bool ParseClass();
   bool ParseMultiClass();
-  bool ParseMultiClassDef(MultiClass *CurMC);
-  bool ParseDefm(MultiClass *CurMultiClass = 0);
-  bool ParseTopLevelLet();
+  bool ParseDefm(MultiClass *CurMultiClass);
+  bool ParseDef(MultiClass *CurMultiClass);
+  bool ParseTopLevelLet(MultiClass *CurMultiClass);
   std::vector<LetRecord> ParseLetList();
 
-  Record *ParseDef(MultiClass *CurMultiClass);
   bool ParseObjectBody(Record *CurRec);
   bool ParseBody(Record *CurRec);
   bool ParseBodyItem(Record *CurRec);





More information about the llvm-commits mailing list