diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp index 6a460870aa9..a9ace152d59 100644 --- a/lib/TableGen/TGParser.cpp +++ b/lib/TableGen/TGParser.cpp @@ -666,35 +666,47 @@ ParseSubMultiClassReference(MultiClass *CurMC) { /// RangePiece ::= INTVAL /// RangePiece ::= INTVAL '-' INTVAL /// RangePiece ::= INTVAL INTVAL -bool TGParser::ParseRangePiece(SmallVectorImpl &Ranges) { - if (Lex.getCode() != tgtok::IntVal) { - TokError("expected integer or bitrange"); - return true; - } - int64_t Start = Lex.getCurIntVal(); +bool TGParser::ParseRangePiece(SmallVectorImpl &Ranges, + TypedInit *FirstItem) { + Init *CurVal = FirstItem; + if (!CurVal) + CurVal = ParseValue(nullptr); + + IntInit *II = dyn_cast_or_null(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(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::ParseForeachDeclaration(Init *&ForeachListValue) { SmallVector 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::ParseForeachDeclaration(Init *&ForeachListValue) { default: { SMLoc ValueLoc = Lex.getLoc(); Init *I = ParseValue(nullptr); - TypedInit *TI = dyn_cast(I); - if (!TI || !isa(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(I); + if (TI && isa(TI->getType())) { + ForeachListValue = I; + IterType = cast(TI->getType())->getElementType(); + break; } - ForeachListValue = I; - IterType = cast(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(); diff --git a/lib/TableGen/TGParser.h b/lib/TableGen/TGParser.h index 38b782461bd..af2b639f8d5 100644 --- a/lib/TableGen/TGParser.h +++ b/lib/TableGen/TGParser.h @@ -190,7 +190,8 @@ private: // Parser methods. bool ParseOptionalRangeList(SmallVectorImpl &Ranges); bool ParseOptionalBitList(SmallVectorImpl &Ranges); void ParseRangeList(SmallVectorImpl &Result); - bool ParseRangePiece(SmallVectorImpl &Ranges); + bool ParseRangePiece(SmallVectorImpl &Ranges, + TypedInit *FirstItem = nullptr); RecTy *ParseType(); Init *ParseOperation(Record *CurRec, RecTy *ItemType); Init *ParseOperationCond(Record *CurRec, RecTy *ItemType); diff --git a/test/TableGen/foreach-range-parse-errors0.td b/test/TableGen/foreach-range-parse-errors0.td new file mode 100644 index 00000000000..a3e6a9eb975 --- /dev/null +++ b/test/TableGen/foreach-range-parse-errors0.td @@ -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 { + +} diff --git a/test/TableGen/foreach-range-parse-errors1.td b/test/TableGen/foreach-range-parse-errors1.td new file mode 100644 index 00000000000..5461a77703b --- /dev/null +++ b/test/TableGen/foreach-range-parse-errors1.td @@ -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 { + +} + diff --git a/test/TableGen/foreach-range-parse-errors2.td b/test/TableGen/foreach-range-parse-errors2.td new file mode 100644 index 00000000000..7717c10aaf6 --- /dev/null +++ b/test/TableGen/foreach-range-parse-errors2.td @@ -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 { + +} diff --git a/test/TableGen/foreach-range-parse-errors3.td b/test/TableGen/foreach-range-parse-errors3.td new file mode 100644 index 00000000000..0a282c36099 --- /dev/null +++ b/test/TableGen/foreach-range-parse-errors3.td @@ -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 { + +} + diff --git a/test/TableGen/foreach-range-parse-errors4.td b/test/TableGen/foreach-range-parse-errors4.td new file mode 100644 index 00000000000..6072b9b589d --- /dev/null +++ b/test/TableGen/foreach-range-parse-errors4.td @@ -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; +} + diff --git a/test/TableGen/foreach-range-parse-errors5.td b/test/TableGen/foreach-range-parse-errors5.td new file mode 100644 index 00000000000..835bb7a74be --- /dev/null +++ b/test/TableGen/foreach-range-parse-errors5.td @@ -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 { + +} + diff --git a/test/TableGen/foreach-variable-range.td b/test/TableGen/foreach-variable-range.td new file mode 100644 index 00000000000..3ddb2c08ff2 --- /dev/null +++ b/test/TableGen/foreach-variable-range.td @@ -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; +}