[llvm] r361434 - TableGen: Handle nontrivial foreach range bounds

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed May 22 14:28:20 PDT 2019


Author: arsenm
Date: Wed May 22 14:28:20 2019
New Revision: 361434

URL: http://llvm.org/viewvc/llvm-project?rev=361434&view=rev
Log:
TableGen: Handle nontrivial foreach range bounds

This allows using anything that isn't a literal integer as the bounds
for a foreach. Some of the diagnostics aren't perfect, but nobody ever
accused tablegen of having good errors. For example, the existing
wording suggests a bitrange is valid, but as far as I can tell this
has never worked.

Fixes bug 41958.

Added:
    llvm/trunk/test/TableGen/foreach-range-parse-errors0.td
    llvm/trunk/test/TableGen/foreach-range-parse-errors1.td
    llvm/trunk/test/TableGen/foreach-range-parse-errors2.td
    llvm/trunk/test/TableGen/foreach-range-parse-errors3.td
    llvm/trunk/test/TableGen/foreach-range-parse-errors4.td
    llvm/trunk/test/TableGen/foreach-range-parse-errors5.td
    llvm/trunk/test/TableGen/foreach-variable-range.td
Modified:
    llvm/trunk/lib/TableGen/TGParser.cpp
    llvm/trunk/lib/TableGen/TGParser.h

Modified: llvm/trunk/lib/TableGen/TGParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?rev=361434&r1=361433&r2=361434&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.cpp (original)
+++ llvm/trunk/lib/TableGen/TGParser.cpp Wed May 22 14:28:20 2019
@@ -666,35 +666,47 @@ ParseSubMultiClassReference(MultiClass *
 ///   RangePiece ::= INTVAL
 ///   RangePiece ::= INTVAL '-' INTVAL
 ///   RangePiece ::= INTVAL INTVAL
-bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges) {
-  if (Lex.getCode() != tgtok::IntVal) {
-    TokError("expected integer or bitrange");
-    return true;
-  }
-  int64_t Start = Lex.getCurIntVal();
+bool TGParser::ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,
+                               TypedInit *FirstItem) {
+  Init *CurVal = FirstItem;
+  if (!CurVal)
+    CurVal = ParseValue(nullptr);
+
+  IntInit *II = dyn_cast_or_null<IntInit>(CurVal);
+  if (!II)
+    return TokError("expected integer or bitrange");
+
+  int64_t Start = II->getValue();
   int64_t End;
 
   if (Start < 0)
     return TokError("invalid range, cannot be negative");
 
-  switch (Lex.Lex()) {  // eat first character.
+  switch (Lex.getCode()) {
   default:
     Ranges.push_back(Start);
     return false;
-  case tgtok::minus:
-    if (Lex.Lex() != tgtok::IntVal) {
+  case tgtok::minus: {
+    Lex.Lex(); // eat
+
+    Init *I_End = ParseValue(nullptr);
+    IntInit *II_End = dyn_cast_or_null<IntInit>(I_End);
+    if (!II_End) {
       TokError("expected integer value as end of range");
       return true;
     }
-    End = Lex.getCurIntVal();
+
+    End = II_End->getValue();
     break;
-  case tgtok::IntVal:
+  }
+  case tgtok::IntVal: {
     End = -Lex.getCurIntVal();
+    Lex.Lex();
     break;
   }
+  }
   if (End < 0)
     return TokError("invalid range, cannot be negative");
-  Lex.Lex();
 
   // Add to the range.
   if (Start < End)
@@ -2439,12 +2451,6 @@ VarInit *TGParser::ParseForeachDeclarati
   SmallVector<unsigned, 16> Ranges;
 
   switch (Lex.getCode()) {
-  case tgtok::IntVal: { // RangePiece.
-    if (ParseRangePiece(Ranges))
-      return nullptr;
-    break;
-  }
-
   case tgtok::l_brace: { // '{' RangeList '}'
     Lex.Lex(); // eat the '{'
     ParseRangeList(Ranges);
@@ -2459,23 +2465,35 @@ VarInit *TGParser::ParseForeachDeclarati
   default: {
     SMLoc ValueLoc = Lex.getLoc();
     Init *I = ParseValue(nullptr);
-    TypedInit *TI = dyn_cast<TypedInit>(I);
-    if (!TI || !isa<ListRecTy>(TI->getType())) {
-      std::string Type;
-      if (TI)
-        Type = (Twine("' of type '") + TI->getType()->getAsString()).str();
-      Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'");
-      if (CurMultiClass)
-        PrintNote({}, "references to multiclass template arguments cannot be "
-                      "resolved at this time");
+    if (!I)
       return nullptr;
+
+    TypedInit *TI = dyn_cast<TypedInit>(I);
+    if (TI && isa<ListRecTy>(TI->getType())) {
+      ForeachListValue = I;
+      IterType = cast<ListRecTy>(TI->getType())->getElementType();
+      break;
     }
-    ForeachListValue = I;
-    IterType = cast<ListRecTy>(TI->getType())->getElementType();
-    break;
+
+    if (TI) {
+      if (ParseRangePiece(Ranges, TI))
+        return nullptr;
+      break;
+    }
+
+    std::string Type;
+    if (TI)
+      Type = (Twine("' of type '") + TI->getType()->getAsString()).str();
+    Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'");
+    if (CurMultiClass) {
+      PrintNote({}, "references to multiclass template arguments cannot be "
+                "resolved at this time");
+    }
+    return nullptr;
   }
   }
 
+
   if (!Ranges.empty()) {
     assert(!IterType && "Type already initialized?");
     IterType = IntRecTy::get();

Modified: llvm/trunk/lib/TableGen/TGParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.h?rev=361434&r1=361433&r2=361434&view=diff
==============================================================================
--- llvm/trunk/lib/TableGen/TGParser.h (original)
+++ llvm/trunk/lib/TableGen/TGParser.h Wed May 22 14:28:20 2019
@@ -190,7 +190,8 @@ private:  // Parser methods.
   bool ParseOptionalRangeList(SmallVectorImpl<unsigned> &Ranges);
   bool ParseOptionalBitList(SmallVectorImpl<unsigned> &Ranges);
   void ParseRangeList(SmallVectorImpl<unsigned> &Result);
-  bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges);
+  bool ParseRangePiece(SmallVectorImpl<unsigned> &Ranges,
+                       TypedInit *FirstItem = nullptr);
   RecTy *ParseType();
   Init *ParseOperation(Record *CurRec, RecTy *ItemType);
   Init *ParseOperationCond(Record *CurRec, RecTy *ItemType);

Added: llvm/trunk/test/TableGen/foreach-range-parse-errors0.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-range-parse-errors0.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-range-parse-errors0.td (added)
+++ llvm/trunk/test/TableGen/foreach-range-parse-errors0.td Wed May 22 14:28:20 2019
@@ -0,0 +1,19 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck -DFILE=%s %s
+
+class ConstantsImpl {
+  int Zero = 0;
+  int One = 1;
+  int Two = 2;
+  int Three = 3;
+  int Five = 5;
+}
+
+def Constants : ConstantsImpl;
+
+// CHECK-NOT:  error: Unknown token when parsing a value
+// CHECK: [[FILE]]:[[@LINE+3]]:22: error: Unknown token when parsing a value
+// CHECK: [[FILE]]:[[@LINE+2]]:22: error: expected integer value as end of range
+// CHECK: [[FILE]]:[[@LINE+1]]:22: error: expected declaration in for
+foreach Index = 0 -  in {
+
+}

Added: llvm/trunk/test/TableGen/foreach-range-parse-errors1.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-range-parse-errors1.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-range-parse-errors1.td (added)
+++ llvm/trunk/test/TableGen/foreach-range-parse-errors1.td Wed May 22 14:28:20 2019
@@ -0,0 +1,8 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck -DFILE=%s %s
+
+// CHECK: [[FILE]]:[[@LINE+2]]:20: error: invalid range, cannot be negative
+// CHECK: [[FILE]]:[[@LINE+1]]:20: error: expected declaration in for
+foreach Index = -1 - 0 in {
+
+}
+

Added: llvm/trunk/test/TableGen/foreach-range-parse-errors2.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-range-parse-errors2.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-range-parse-errors2.td (added)
+++ llvm/trunk/test/TableGen/foreach-range-parse-errors2.td Wed May 22 14:28:20 2019
@@ -0,0 +1,13 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck -DFILE=%s %s
+
+class ConstantsImpl {
+  int NegOne = -1;
+}
+
+def Constants : ConstantsImpl;
+
+// CHECK: [[FILE]]:[[@LINE+2]]:38: error: invalid range, cannot be negative
+// CHECK: [[FILE]]:[[@LINE+1]]:38: error: expected declaration in for
+foreach Index = 0 - Constants.NegOne in {
+
+}

Added: llvm/trunk/test/TableGen/foreach-range-parse-errors3.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-range-parse-errors3.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-range-parse-errors3.td (added)
+++ llvm/trunk/test/TableGen/foreach-range-parse-errors3.td Wed May 22 14:28:20 2019
@@ -0,0 +1,8 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck -DFILE=%s %s
+
+// CHECK: [[FILE]]:[[@LINE+2]]:21: error: expected integer or bitrange
+// CHECK: [[FILE]]:[[@LINE+1]]:21: error: expected declaration in for
+foreach Index = "0" - 1 in {
+
+}
+

Added: llvm/trunk/test/TableGen/foreach-range-parse-errors4.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-range-parse-errors4.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-range-parse-errors4.td (added)
+++ llvm/trunk/test/TableGen/foreach-range-parse-errors4.td Wed May 22 14:28:20 2019
@@ -0,0 +1,9 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck -DFILE=%s %s
+// Make sure there is no crash on undefined variable
+
+// CHECK: [[FILE]]:[[@LINE+2]]:17: error: Variable not defined: 'foo'
+// CHECK: [[FILE]]:[[@LINE+1]]:21: error: expected declaration in for
+foreach Index = foo in {
+  def arst#Index;
+}
+

Added: llvm/trunk/test/TableGen/foreach-range-parse-errors5.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-range-parse-errors5.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-range-parse-errors5.td (added)
+++ llvm/trunk/test/TableGen/foreach-range-parse-errors5.td Wed May 22 14:28:20 2019
@@ -0,0 +1,8 @@
+// RUN: not llvm-tblgen %s 2>&1 | FileCheck -DFILE=%s %s
+
+// CHECK: [[FILE]]:[[@LINE+2]]:23: error: expected integer or bitrange
+// CHECK: [[FILE]]:[[@LINE+1]]:23: error: expected declaration in for
+foreach Index = 0b110 - 0b111 in {
+
+}
+

Added: llvm/trunk/test/TableGen/foreach-variable-range.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/foreach-variable-range.td?rev=361434&view=auto
==============================================================================
--- llvm/trunk/test/TableGen/foreach-variable-range.td (added)
+++ llvm/trunk/test/TableGen/foreach-variable-range.td Wed May 22 14:28:20 2019
@@ -0,0 +1,128 @@
+// RUN: llvm-tblgen %s
+
+class ConstantsImpl {
+  int Zero = 0;
+  int One = 1;
+  int Two = 2;
+  int Three = 3;
+  int Five = 5;
+}
+
+def Constants : ConstantsImpl;
+
+// CHECK-DAG: def var_bound_whitespaceA0
+// CHECK-DAG: def var_bound_whitespaceA1
+// CHECK-DAG: def var_bound_whitespaceA2
+foreach Index = Constants.Zero - Constants.Two in {
+  def var_bound_whitespaceA#Index;
+}
+
+// CHECK-DAG: def var_bound_whitespaceB0
+// CHECK-DAG: def var_bound_whitespaceB1
+// CHECK-DAG: def var_bound_whitespaceB2
+foreach Index = Constants.Zero-Constants.Two in {
+  def var_bounds_whitespaceB#Index;
+}
+
+// CHECK-DAG: def var_bound_whitespaceC0
+// CHECK-DAG: def var_bound_whitespaceC1
+// CHECK-DAG: def var_bound_whitespaceC2
+foreach Index = Constants.Zero -Constants.Two in {
+  def var_bounds_whitespaceC#Index;
+}
+
+// CHECK-DAG: def var_bound_whitespaceD0
+// CHECK-DAG: def var_bound_whitespaceD1
+// CHECK-DAG: def var_bound_whitespaceD2
+foreach Index = Constants.Zero- Constants.Two in {
+  def var_bounds_whitespaceD#Index;
+}
+
+// CHECK-DAG: def const_lower_whitespaceA0
+// CHECK-DAG: def const_lower_whitespaceA1
+// CHECK-DAG: def const_lower_whitespaceA2
+foreach Index = 0 - Constants.Two in {
+  def const_lower_whitespaceA#Index;
+}
+
+// CHECK-DAG: def const_lower_whitespaceB0
+// CHECK-DAG: def const_lower_whitespaceB1
+// CHECK-DAG: def const_lower_whitespaceB2
+foreach Index = 0-Constants.Two in {
+  def const_lower_whitespaceB#Index;
+}
+
+// CHECK-DAG: def const_lower_whitespaceC0
+// CHECK-DAG: def const_lower_whitespaceC1
+// CHECK-DAG: def const_lower_whitespaceC2
+foreach Index = 0 -Constants.Two in {
+  def const_lower_whitespaceC#Index;
+}
+
+// CHECK-DAG: def const_lower_whitespaceD0
+// CHECK-DAG: def const_lower_whitespaceD1
+// CHECK-DAG: def const_lower_whitespaceD2
+foreach Index = 0- Constants.Two in {
+  def const_lower_whitespaceD#Index;
+}
+
+// CHECK-DAG: def const_upper_whitespaceA0
+// CHECK-DAG: def const_upper_whitespaceA1
+// CHECK-DAG: def const_upper_whitespaceA2
+foreach Index = Constants.Zero - 2 in {
+  def const_upper_whitespaceA#Index;
+}
+
+// CHECK-DAG: def const_upper_whitespaceB0
+// CHECK-DAG: def const_upper_whitespaceB1
+// CHECK-DAG: def const_upper_whitespaceB2
+foreach Index = Constants.Zero-2 in {
+  def const_upper_whitespaceB#Index;
+}
+
+// CHECK-DAG: def const_upper_whitespaceC0
+// CHECK-DAG: def const_upper_whitespaceC1
+// CHECK-DAG: def const_upper_whitespaceC2
+foreach Index = Constants.Zero -2 in {
+  def const_upper_whitespaceC#Index;
+}
+
+// CHECK-DAG: def const_upper_whitespaceD0
+// CHECK-DAG: def const_upper_whitespaceD1
+// CHECK-DAG: def const_upper_whitespaceD2
+foreach Index = Constants.Zero- 2 in {
+  def const_upper_whitespaceD#Index;
+}
+
+// CHECK-DAG: def multi_rangeA0
+// CHECK-DAG: def multi_rangeA1
+// CHECK-DAG: def multi_rangeA2
+// CHECK-DAG: def multi_rangeA3
+foreach Index = {Constants.Zero-Constants.One, Constants.Two-Constants.Three} in {
+  def multi_rangeA#Index;
+}
+
+// CHECK-DAG: def multi_rangeB0
+// CHECK-DAG: def multi_rangeB1
+// CHECK-DAG: def multi_rangeB3
+// CHECK-DAG: def multi_rangeB4
+// CHECK-DAG: def multi_rangeB5
+foreach Index = {0-Constants.One, Constants.Three-Constants.Five} in {
+  def multi_rangeB#Index;
+}
+
+// CHECK-DAG: def multi_rangeC0
+// CHECK-DAG: def multi_rangeC1
+// CHECK-DAG: def multi_rangeC2
+// CHECK-DAG: def multi_rangeC3
+foreach Index = {0-Constants.One, 2-Constants.Three} in {
+  def multi_rangeC#Index;
+}
+
+// CHECK-DAG: def multi_rangeD0
+// CHECK-DAG: def multi_rangeD1
+// CHECK-DAG: def multi_rangeD2
+// CHECK-DAG: def multi_rangeD3
+foreach Index = {0-1, Constants.Two-3} in {
+  def multi_rangeD#Index;
+}




More information about the llvm-commits mailing list