[llvm] cd7280b - [TableGen] Fix wrong lex result on 64-bit integer boundaries
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 20 21:46:40 PDT 2023
Author: Senran Zhang
Date: 2023-08-20T21:46:36-07:00
New Revision: cd7280b6e6c43e3c236200bc026f45d33f54f059
URL: https://github.com/llvm/llvm-project/commit/cd7280b6e6c43e3c236200bc026f45d33f54f059
DIFF: https://github.com/llvm/llvm-project/commit/cd7280b6e6c43e3c236200bc026f45d33f54f059.diff
LOG: [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
Added:
llvm/test/TableGen/64-bit-int.td
Modified:
llvm/lib/TableGen/TGLexer.cpp
Removed:
################################################################################
diff --git a/llvm/lib/TableGen/TGLexer.cpp b/llvm/lib/TableGen/TGLexer.cpp
index 98f0e8c1149c07..484f840dc4fc32 100644
--- a/llvm/lib/TableGen/TGLexer.cpp
+++ b/llvm/lib/TableGen/TGLexer.cpp
@@ -462,56 +462,62 @@ bool TGLexer::SkipCComment() {
/// 0x[0-9a-fA-F]+
/// 0b[01]+
tgtok::TokKind TGLexer::LexNumber() {
+ unsigned Base = 0;
+ const char *NumStart;
+
+ // Check if it's a hex or a binary value.
if (CurPtr[-1] == '0') {
+ NumStart = CurPtr + 1;
if (CurPtr[0] == 'x') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (isxdigit(CurPtr[0]))
+ Base = 16;
+ do
++CurPtr;
-
- // Requires at least one hex digit.
- if (CurPtr == NumStart)
- return ReturnError(TokStart, "Invalid hexadecimal number");
-
- errno = 0;
- CurIntVal = strtoll(NumStart, nullptr, 16);
- if (errno == EINVAL)
- return ReturnError(TokStart, "Invalid hexadecimal number");
- if (errno == ERANGE) {
- errno = 0;
- CurIntVal = (int64_t)strtoull(NumStart, nullptr, 16);
- if (errno == EINVAL)
- return ReturnError(TokStart, "Invalid hexadecimal number");
- if (errno == ERANGE)
- return ReturnError(TokStart, "Hexadecimal number out of range");
- }
- return tgtok::IntVal;
+ while (isxdigit(CurPtr[0]));
} else if (CurPtr[0] == 'b') {
- ++CurPtr;
- const char *NumStart = CurPtr;
- while (CurPtr[0] == '0' || CurPtr[0] == '1')
+ Base = 2;
+ do
++CurPtr;
-
- // Requires at least one binary digit.
- if (CurPtr == NumStart)
- return ReturnError(CurPtr-2, "Invalid binary number");
- CurIntVal = strtoll(NumStart, nullptr, 2);
- return tgtok::BinaryIntVal;
+ while (CurPtr[0] == '0' || CurPtr[0] == '1');
}
}
- // Check for a sign without a digit.
- if (!isdigit(CurPtr[0])) {
- if (CurPtr[-1] == '-')
- return tgtok::minus;
- else if (CurPtr[-1] == '+')
- return tgtok::plus;
+ // For a hex or binary value, we always convert it to an unsigned value.
+ bool IsMinus = false;
+
+ // Check if it's a decimal value.
+ if (Base == 0) {
+ // Check for a sign without a digit.
+ if (!isdigit(CurPtr[0])) {
+ if (CurPtr[-1] == '-')
+ return tgtok::minus;
+ else if (CurPtr[-1] == '+')
+ return tgtok::plus;
+ }
+
+ Base = 10;
+ NumStart = TokStart;
+ IsMinus = CurPtr[-1] == '-';
+
+ while (isdigit(CurPtr[0]))
+ ++CurPtr;
}
- while (isdigit(CurPtr[0]))
- ++CurPtr;
- CurIntVal = strtoll(TokStart, nullptr, 10);
- return tgtok::IntVal;
+ // Requires at least one digit.
+ if (CurPtr == NumStart)
+ return ReturnError(TokStart, "Invalid number");
+
+ errno = 0;
+ if (IsMinus)
+ CurIntVal = strtoll(NumStart, nullptr, Base);
+ else
+ CurIntVal = strtoull(NumStart, nullptr, Base);
+
+ if (errno == EINVAL)
+ return ReturnError(TokStart, "Invalid number");
+ if (errno == ERANGE)
+ return ReturnError(TokStart, "Number out of range");
+
+ return Base == 2 ? tgtok::BinaryIntVal : tgtok::IntVal;
}
/// LexBracket - We just read '['. If this is a code block, return it,
diff --git a/llvm/test/TableGen/64-bit-int.td b/llvm/test/TableGen/64-bit-int.td
new file mode 100644
index 00000000000000..2d2bdb8b560e2c
--- /dev/null
+++ b/llvm/test/TableGen/64-bit-int.td
@@ -0,0 +1,36 @@
+// RUN: llvm-tblgen -print-records %s | FileCheck %s
+// RUN: not llvm-tblgen -DOOR1 -print-records %s 2>&1 | FileCheck %s --check-prefix=CHECK-OOR
+// RUN: not llvm-tblgen -DOOR2 -print-records %s 2>&1 | FileCheck %s --check-prefix=CHECK-OOR
+// RUN: not llvm-tblgen -DOOR3 -print-records %s 2>&1 | FileCheck %s --check-prefix=CHECK-OOR
+
+def {
+
+#ifdef OOR1
+ bits<64> Val = -9223372036854775809;
+#endif
+
+#ifdef OOR2
+ bits<64> Val = 0b10000000000000000000000000000000000000000000000000000000000000000;
+#endif
+
+#ifdef OOR3
+ bits<64> Val = 0x10000000000000000;
+#endif
+// CHECK-OOR: error: Number out of range
+
+ bits<64> BinVal0 = 0x8000000000000000;
+ bits<64> HexVal0 = 0b1000000000000000000000000000000000000000000000000000000000000000;
+ bits<64> DecVal0_0 = 9223372036854775808;
+ bits<64> DecVal0_1 = -9223372036854775808;
+
+ bits<64> HexVal1 = 0x8000000000000001;
+ bits<64> DecVal1 = 9223372036854775809;
+
+// 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 };
+// 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 };
+// 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 };
+// 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 };
+
+// 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 };
+// 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 };
+}
More information about the llvm-commits
mailing list