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,15 @@ :| "." `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. +.. 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 @@ -43,6 +43,7 @@ comma, period, // , . equal, question, // = ? paste, // # + range, // .. // 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,15 @@ return tgtok::paste; + // The period is a separate case so we can recognize the ".." + // range punctuator. + case '.': + if (peekNextChar(0) == '.') { + ++CurPtr; // Eat second period. + return tgtok::range; + } + return tgtok::period; + 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::range: case tgtok::minus: { Lex.Lex(); // eat Index: llvm/test/TableGen/range-lists.td =================================================================== --- /dev/null +++ llvm/test/TableGen/range-lists.td @@ -0,0 +1,77 @@ +// 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_dotdot { + 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 dotdot_field1_ok = !eq(field1, 0xABCD); +} + +if !eq(bit_range_hyphen.field1, bit_range_dotdot.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_dotdot { + 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 dotdot_subfields_ok = !and(!eq(subfieldb[0], "quux"), !eq(subfieldd[1], "flarp")); +} + +if !eq(!head(list_range_hyphen.subfieldd), !head(list_range_dotdot.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 dotdot_field1_ok = 1 +//CHECK: bit hyphen_field1_ok = 1 +//CHECK: def bit_range_ok { + +//CHECK: def eachrec04 { +//CHECK: def eachrec35 { + +//CHECK: bit dotdot_subfields_ok = 1 +//CHECK: bit hyphen_subfields_ok = 1 +//CHECK: def list_range_ok { +