[llvm] r327120 - TableGen: Allow arbitrary list values as ranges of foreach

Nicolai Haehnle via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 9 04:24:30 PST 2018


Author: nha
Date: Fri Mar  9 04:24:30 2018
New Revision: 327120

URL: http://llvm.org/viewvc/llvm-project?rev=327120&view=rev
Log:
TableGen: Allow arbitrary list values as ranges of foreach

The changes to FieldInit are required to make field references (Def.field)
work inside a ForeachDeclaration: previously, Def.field wasn't resolved
immediately when Def was already a fully resolved DefInit.

Change-Id: I9875baec2fc5aac8c2b249e45b9cf18c65ae699b

Modified:
    llvm/trunk/docs/TableGen/LangRef.rst
    llvm/trunk/include/llvm/TableGen/Record.h
    llvm/trunk/lib/TableGen/Record.cpp
    llvm/trunk/lib/TableGen/TGParser.cpp
    llvm/trunk/test/TableGen/ForeachList.td

Modified: llvm/trunk/docs/TableGen/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TableGen/LangRef.rst?rev=327120&r1=327119&r2=327120&view=diff
==============================================================================
--- llvm/trunk/docs/TableGen/LangRef.rst (original)
+++ llvm/trunk/docs/TableGen/LangRef.rst Fri Mar  9 04:24:30 2018
@@ -360,13 +360,17 @@ precede any ``class``'s that appear.
 -----------
 
 .. productionlist::
-   Foreach: "foreach" `Declaration` "in" "{" `Object`* "}"
-          :| "foreach" `Declaration` "in" `Object`
+   Foreach: "foreach" `ForeachDeclaration` "in" "{" `Object`* "}"
+          :| "foreach" `ForeachDeclaration` "in" `Object`
+   ForeachDeclaration: ID "=" ( "{" `RangeList` "}" | `RangePiece` | `Value` )
 
 The value assigned to the variable in the declaration is iterated over and
 the object or object list is reevaluated with the variable set at each
 iterated value.
 
+Note that the productions involving RangeList and RangePiece have precedence
+over the more generic value parsing based on the first token.
+
 Top-Level ``let``
 -----------------
 

Modified: llvm/trunk/include/llvm/TableGen/Record.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/Record.h?rev=327120&r1=327119&r2=327120&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/Record.h (original)
+++ llvm/trunk/include/llvm/TableGen/Record.h Fri Mar  9 04:24:30 2018
@@ -1203,6 +1203,7 @@ public:
   Init *getBit(unsigned Bit) const override;
 
   Init *resolveReferences(Resolver &R) const override;
+  Init *Fold() const;
 
   std::string getAsString() const override {
     return Rec->getAsString() + "." + FieldName->getValue().str();

Modified: llvm/trunk/lib/TableGen/Record.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/Record.cpp?rev=327120&r1=327119&r2=327120&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/Record.cpp (original)
+++ llvm/trunk/lib/TableGen/Record.cpp Fri Mar  9 04:24:30 2018
@@ -1633,16 +1633,17 @@ Init *FieldInit::getBit(unsigned Bit) co
 
 Init *FieldInit::resolveReferences(Resolver &R) const {
   Init *NewRec = Rec->resolveReferences(R);
+  if (NewRec != Rec)
+    return FieldInit::get(NewRec, FieldName)->Fold();
+  return const_cast<FieldInit *>(this);
+}
 
-  if (DefInit *DI = dyn_cast<DefInit>(NewRec)) {
+Init *FieldInit::Fold() const {
+  if (DefInit *DI = dyn_cast<DefInit>(Rec)) {
     Init *FieldVal = DI->getDef()->getValue(FieldName)->getValue();
-    Init *BVR = FieldVal->resolveReferences(R);
-    if (BVR->isComplete())
-      return BVR;
+    if (FieldVal->isComplete())
+      return FieldVal;
   }
-
-  if (NewRec != Rec)
-    return FieldInit::get(NewRec, FieldName);
   return const_cast<FieldInit *>(this);
 }
 

Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=327120&r1=327119&r2=327120&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Fri Mar  9 04:24:30 2018
@@ -1819,7 +1819,7 @@ Init *TGParser::ParseValue(Record *CurRe
                  Result->getAsString() + "'");
         return nullptr;
       }
-      Result = FieldInit::get(Result, FieldName);
+      Result = FieldInit::get(Result, FieldName)->Fold();
       Lex.Lex();  // eat field name
       break;
     }
@@ -2038,9 +2038,9 @@ Init *TGParser::ParseDeclaration(Record
 /// the name of the declared object or a NULL Init on error.  Return
 /// the name of the parsed initializer list through ForeachListName.
 ///
-///  ForeachDeclaration ::= ID '=' '[' ValueList ']'
 ///  ForeachDeclaration ::= ID '=' '{' RangeList '}'
 ///  ForeachDeclaration ::= ID '=' RangePiece
+///  ForeachDeclaration ::= ID '=' Value
 ///
 VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
   if (Lex.getCode() != tgtok::Id) {
@@ -2062,24 +2062,6 @@ VarInit *TGParser::ParseForeachDeclarati
   SmallVector<unsigned, 16> Ranges;
 
   switch (Lex.getCode()) {
-  default: TokError("Unknown token when expecting a range list"); return nullptr;
-  case tgtok::l_square: { // '[' ValueList ']'
-    Init *List = ParseSimpleValue(nullptr);
-    ForeachListValue = dyn_cast<ListInit>(List);
-    if (!ForeachListValue) {
-      TokError("Expected a Value list");
-      return nullptr;
-    }
-    RecTy *ValueType = ForeachListValue->getType();
-    ListRecTy *ListType = dyn_cast<ListRecTy>(ValueType);
-    if (!ListType) {
-      TokError("Value list is not of list type");
-      return nullptr;
-    }
-    IterType = ListType->getElementType();
-    break;
-  }
-
   case tgtok::IntVal: { // RangePiece.
     if (ParseRangePiece(Ranges))
       return nullptr;
@@ -2096,6 +2078,21 @@ VarInit *TGParser::ParseForeachDeclarati
     Lex.Lex();
     break;
   }
+
+  default: {
+    SMLoc ValueLoc = Lex.getLoc();
+    Init *I = ParseValue(nullptr);
+    if (!isa<ListInit>(I)) {
+      std::string Type;
+      if (TypedInit *TI = dyn_cast<TypedInit>(I))
+        Type = (Twine("' of type '") + TI->getType()->getAsString()).str();
+      Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'");
+      return nullptr;
+    }
+    ForeachListValue = dyn_cast<ListInit>(I);
+    IterType = ForeachListValue->getElementType();
+    break;
+  }
   }
 
   if (!Ranges.empty()) {

Modified: llvm/trunk/test/TableGen/ForeachList.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/ForeachList.td?rev=327120&r1=327119&r2=327120&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/ForeachList.td (original)
+++ llvm/trunk/test/TableGen/ForeachList.td Fri Mar  9 04:24:30 2018
@@ -10,6 +10,18 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in
   def F#i : Register<"F"#i, i>;
 }
 
+def Defs {
+  list<int> a = [0, 1];
+  list<int> b = [2, 3];
+}
+
+foreach i = Defs.a in {
+  def X#i;
+}
+
+foreach i = !listconcat(Defs.a, Defs.b) in
+def Y#i;
+
 // CHECK: def F0
 // CHECK: string Name = "F0";
 // CHECK: int Index = 0;
@@ -73,3 +85,10 @@ foreach i = [0, 1, 2, 3, 4, 5, 6, 7] in
 // CHECK: def R7
 // CHECK: string Name = "R7";
 // CHECK: int Index = 7;
+
+// CHECK: def X0
+// CHECK: def X1
+// CHECK: def Y0
+// CHECK: def Y1
+// CHECK: def Y2
+// CHECK: def Y3




More information about the llvm-commits mailing list