Index: llvm/docs/ReleaseNotes.rst =================================================================== --- llvm/docs/ReleaseNotes.rst +++ llvm/docs/ReleaseNotes.rst @@ -65,6 +65,14 @@ Changes to building LLVM ------------------------ +Changes to TableGen +------------------- + +* The syntax for specifying an integer range in a range list has changed. + The old syntax used a hyphen in the range (e.g., ``{0-9}``). The new syntax + uses the "`...`" range punctuator (e.g., ``{0...9}``). The hyphen syntax + is deprecated. The "TableGen Language Reference" document has been updated. + Changes to the ARM Backend -------------------------- Index: llvm/docs/TableGen/LangRef.rst =================================================================== --- llvm/docs/TableGen/LangRef.rst +++ llvm/docs/TableGen/LangRef.rst @@ -197,16 +197,16 @@ :| "." `TokIdentifier` RangeList: `RangePiece` ("," `RangePiece`)* RangePiece: `TokInteger` - :| `TokInteger` "-" `TokInteger` - :| `TokInteger` `TokInteger` + :| `TokInteger` "..." `TokInteger` -The peculiar last form of :token:`RangePiece` is due to the fact that the -"``-``" is included in the :token:`TokInteger`, hence ``1-5`` gets lexed as -two consecutive :token:`TokInteger`'s, with values ``1`` and ``-5``, -instead of "1", "-", and "5". The :token:`RangeList` can be thought of as specifying "list slice" in some -contexts. +contexts. When an integer range is specified with the ``...`` punctuation, +the range is inclusive. +.. warning:: + A :token:`RangePiece` can also be specified with a hyphen (``-``) instead of the + range indicator ``...``. In this case, the integers should not have signs. + This hyphen form of ranges is deprecated. :token:`SimpleValue` has a number of forms: Index: llvm/lib/TableGen/TGLexer.h =================================================================== --- llvm/lib/TableGen/TGLexer.h +++ llvm/lib/TableGen/TGLexer.h @@ -40,9 +40,10 @@ l_paren, r_paren, // ( ) less, greater, // < > colon, semi, // : ; - comma, period, // , . + comma, dot, // , . equal, question, // = ? paste, // # + dotdotdot, // ... // Keywords. ('ElseKW' is named to distinguish it from the existing 'Else' // that means the preprocessor #else.) Index: llvm/lib/TableGen/TGLexer.cpp =================================================================== --- llvm/lib/TableGen/TGLexer.cpp +++ llvm/lib/TableGen/TGLexer.cpp @@ -161,7 +161,6 @@ case ':': return tgtok::colon; case ';': return tgtok::semi; - case '.': return tgtok::period; case ',': return tgtok::comma; case '<': return tgtok::less; case '>': return tgtok::greater; @@ -181,6 +180,19 @@ return tgtok::paste; + // The period is a separate case so we can recognize the "..." + // range punctuator. + case '.': + if (peekNextChar(0) == '.') { + ++CurPtr; // Eat second dot. + if (peekNextChar(0) == '.') { + ++CurPtr; // Eat third dot. + return tgtok::dotdotdot; + } + return ReturnError(TokStart, "Invalid '..' punctuation"); + } + return tgtok::dot; + case '\r': PrintFatalError("getNextChar() must never return '\r'"); return tgtok::Error; Index: llvm/lib/TableGen/TGParser.cpp =================================================================== --- llvm/lib/TableGen/TGParser.cpp +++ llvm/lib/TableGen/TGParser.cpp @@ -671,8 +671,10 @@ /// ParseRangePiece - Parse a bit/value range. /// RangePiece ::= INTVAL +/// RangePiece ::= INTVAL '...' INTVAL /// RangePiece ::= INTVAL '-' INTVAL -/// RangePiece ::= INTVAL INTVAL +/// RangePiece ::= INTVAL INTVAL +// The last two forms are deprecated. bool TGParser::ParseRangePiece(SmallVectorImpl &Ranges, TypedInit *FirstItem) { Init *CurVal = FirstItem; @@ -693,6 +695,8 @@ default: Ranges.push_back(Start); return false; + + case tgtok::dotdotdot: case tgtok::minus: { Lex.Lex(); // eat @@ -2167,7 +2171,7 @@ } break; } - case tgtok::period: { + case tgtok::dot: { if (Lex.Lex() != tgtok::Id) { // eat the . TokError("expected field identifier after '.'"); return nullptr; Index: llvm/test/TableGen/range-lists.td =================================================================== --- /dev/null +++ llvm/test/TableGen/range-lists.td @@ -0,0 +1,80 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +// This file has tests for range lists and range pieces. + +// These are tests for bits ranges. + +def bit_range_hyphen { + bits<16> field1; + let field1{15, 14, 13, 12} = {1, 0, 1, 0}; + let field1{11-8} = {1, 0, 1, 1}; + let field1{+7-4} = {1, 1, 0, 0}; + let field1{+3-+0} = {1, 1, 0, 1}; + bit hyphen_field1_ok = !eq(field1, 0xABCD); +} + +def bit_range_dotdotdot { + bits<16> field1; + let field1{15, 14, 13, 12} = {1, 0, 1, 0}; + let field1{11...8} = {1, 0, 1, 1}; + let field1{+7...4} = {1, 1, 0, 0}; + let field1{+3...+0} = {1, 1, 0, 1}; + bit dotdotdot_field1_ok = !eq(field1, 0xABCD); +} + +if !eq(bit_range_hyphen.field1, bit_range_dotdotdot.field1) then + def bit_range_ok {} +else + def bit_range_not_ok {} + +// These are tests for lists. + +def list_range_hyphen { + list field1 = ["foo", "bar", "baz", "snork", "quux", "quuux", + "bazola", "ztesch", "bletch", "flarp"]; + list subfielda = field1[0, 1, 2, 3]; + list subfieldb = field1[4-5]; + list subfieldc = field1[+6-7]; + list subfieldd = field1[+8-+9]; + bit hyphen_subfields_ok = !and(!eq(subfieldb[0], "quux"), + !eq(subfieldd[1], "flarp")); +} + +def list_range_dotdotdot { + list field1 = ["foo", "bar", "baz", "snork", "quux", "quuux", + "bazola", "ztesch", "bletch", "flarp"]; + list subfielda = field1[0, 1, 2, 3]; + list subfieldb = field1[4...5]; + list subfieldc = field1[+6...7]; + list subfieldd = field1[+8...+9]; + bit dotdotdot_subfields_ok = !and(!eq(subfieldb[0], "quux"), + !eq(subfieldd[1], "flarp")); +} + +if !eq(!head(list_range_hyphen.subfieldd), + !head(list_range_dotdotdot.subfieldd)) then + def list_range_ok {} +else + def list_range_not_ok {} + +// This is a test of foreach. + +foreach i = {0-3} in + foreach j = {4...5} in + def eachrec#i#j { + int fi = i; + int fj = j; + } + +//CHECK: bit dotdotdot_field1_ok = 1 +//CHECK: bit hyphen_field1_ok = 1 +//CHECK: def bit_range_ok { + +//CHECK: def eachrec04 { +//CHECK: def eachrec35 { + +//CHECK: bit dotdotdot_subfields_ok = 1 +//CHECK: bit hyphen_subfields_ok = 1 +//CHECK: def list_range_ok { +