Skip to content

Commit cd7280b

Browse files
zsrkmynMaskRay
authored andcommitted
[TableGen] Fix wrong lex result on 64-bit integer boundaries
Binary and decimal values were reconginzed by strtoll, which returns error when the msb is 1, and the error was ignored, resulting to wrong results. This patch fixes the issue. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D157079
1 parent 2c3ded6 commit cd7280b

File tree

2 files changed

+82
-40
lines changed

2 files changed

+82
-40
lines changed

llvm/lib/TableGen/TGLexer.cpp

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -462,56 +462,62 @@ bool TGLexer::SkipCComment() {
462462
/// 0x[0-9a-fA-F]+
463463
/// 0b[01]+
464464
tgtok::TokKind TGLexer::LexNumber() {
465+
unsigned Base = 0;
466+
const char *NumStart;
467+
468+
// Check if it's a hex or a binary value.
465469
if (CurPtr[-1] == '0') {
470+
NumStart = CurPtr + 1;
466471
if (CurPtr[0] == 'x') {
467-
++CurPtr;
468-
const char *NumStart = CurPtr;
469-
while (isxdigit(CurPtr[0]))
472+
Base = 16;
473+
do
470474
++CurPtr;
471-
472-
// Requires at least one hex digit.
473-
if (CurPtr == NumStart)
474-
return ReturnError(TokStart, "Invalid hexadecimal number");
475-
476-
errno = 0;
477-
CurIntVal = strtoll(NumStart, nullptr, 16);
478-
if (errno == EINVAL)
479-
return ReturnError(TokStart, "Invalid hexadecimal number");
480-
if (errno == ERANGE) {
481-
errno = 0;
482-
CurIntVal = (int64_t)strtoull(NumStart, nullptr, 16);
483-
if (errno == EINVAL)
484-
return ReturnError(TokStart, "Invalid hexadecimal number");
485-
if (errno == ERANGE)
486-
return ReturnError(TokStart, "Hexadecimal number out of range");
487-
}
488-
return tgtok::IntVal;
475+
while (isxdigit(CurPtr[0]));
489476
} else if (CurPtr[0] == 'b') {
490-
++CurPtr;
491-
const char *NumStart = CurPtr;
492-
while (CurPtr[0] == '0' || CurPtr[0] == '1')
477+
Base = 2;
478+
do
493479
++CurPtr;
494-
495-
// Requires at least one binary digit.
496-
if (CurPtr == NumStart)
497-
return ReturnError(CurPtr-2, "Invalid binary number");
498-
CurIntVal = strtoll(NumStart, nullptr, 2);
499-
return tgtok::BinaryIntVal;
480+
while (CurPtr[0] == '0' || CurPtr[0] == '1');
500481
}
501482
}
502483

503-
// Check for a sign without a digit.
504-
if (!isdigit(CurPtr[0])) {
505-
if (CurPtr[-1] == '-')
506-
return tgtok::minus;
507-
else if (CurPtr[-1] == '+')
508-
return tgtok::plus;
484+
// For a hex or binary value, we always convert it to an unsigned value.
485+
bool IsMinus = false;
486+
487+
// Check if it's a decimal value.
488+
if (Base == 0) {
489+
// Check for a sign without a digit.
490+
if (!isdigit(CurPtr[0])) {
491+
if (CurPtr[-1] == '-')
492+
return tgtok::minus;
493+
else if (CurPtr[-1] == '+')
494+
return tgtok::plus;
495+
}
496+
497+
Base = 10;
498+
NumStart = TokStart;
499+
IsMinus = CurPtr[-1] == '-';
500+
501+
while (isdigit(CurPtr[0]))
502+
++CurPtr;
509503
}
510504

511-
while (isdigit(CurPtr[0]))
512-
++CurPtr;
513-
CurIntVal = strtoll(TokStart, nullptr, 10);
514-
return tgtok::IntVal;
505+
// Requires at least one digit.
506+
if (CurPtr == NumStart)
507+
return ReturnError(TokStart, "Invalid number");
508+
509+
errno = 0;
510+
if (IsMinus)
511+
CurIntVal = strtoll(NumStart, nullptr, Base);
512+
else
513+
CurIntVal = strtoull(NumStart, nullptr, Base);
514+
515+
if (errno == EINVAL)
516+
return ReturnError(TokStart, "Invalid number");
517+
if (errno == ERANGE)
518+
return ReturnError(TokStart, "Number out of range");
519+
520+
return Base == 2 ? tgtok::BinaryIntVal : tgtok::IntVal;
515521
}
516522

517523
/// LexBracket - We just read '['. If this is a code block, return it,

llvm/test/TableGen/64-bit-int.td

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: llvm-tblgen -print-records %s | FileCheck %s
2+
// RUN: not llvm-tblgen -DOOR1 -print-records %s 2>&1 | FileCheck %s --check-prefix=CHECK-OOR
3+
// RUN: not llvm-tblgen -DOOR2 -print-records %s 2>&1 | FileCheck %s --check-prefix=CHECK-OOR
4+
// RUN: not llvm-tblgen -DOOR3 -print-records %s 2>&1 | FileCheck %s --check-prefix=CHECK-OOR
5+
6+
def {
7+
8+
#ifdef OOR1
9+
bits<64> Val = -9223372036854775809;
10+
#endif
11+
12+
#ifdef OOR2
13+
bits<64> Val = 0b10000000000000000000000000000000000000000000000000000000000000000;
14+
#endif
15+
16+
#ifdef OOR3
17+
bits<64> Val = 0x10000000000000000;
18+
#endif
19+
// CHECK-OOR: error: Number out of range
20+
21+
bits<64> BinVal0 = 0x8000000000000000;
22+
bits<64> HexVal0 = 0b1000000000000000000000000000000000000000000000000000000000000000;
23+
bits<64> DecVal0_0 = 9223372036854775808;
24+
bits<64> DecVal0_1 = -9223372036854775808;
25+
26+
bits<64> HexVal1 = 0x8000000000000001;
27+
bits<64> DecVal1 = 9223372036854775809;
28+
29+
// CHECK: bits<64> BinVal0 = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
30+
// CHECK: bits<64> HexVal0 = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
31+
// CHECK: bits<64> DecVal0_0 = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
32+
// CHECK: bits<64> DecVal0_1 = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
33+
34+
// CHECK: bits<64> HexVal1 = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
35+
// CHECK: bits<64> DecVal1 = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
36+
}

0 commit comments

Comments
 (0)