[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/96240 >From 659107442e6202b2c4e30ea1a9a5292f99c696e3 Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Fri, 24 May 2024 11:39:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman Co-authored-by: Paul Kirth --- clang/lib/CodeGen/CGExpr.cpp | 59 +- clang/test/CodeGen/bit-int-ubsan.c| 96 ++ compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 33 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 42 + .../test/ubsan/TestCases/Integer/bit-int.c| 170 ++ 6 files changed, 404 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGen/bit-int-ubsan.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 534f46da74862..060ab84992a7e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from discussion of issue 64100. +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert(getContext().getTypeSize(T) > 0 && + " non positive amount of bits in __BitInt type"); + assert(getContext().getTypeSize(T) <= 0x && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/96240 >From 98d3d539c84c917ba7369f688ba26ff172c9d89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?E=C3=A4nolituri=20L=C3=B3mitaur=C3=AB?= Date: Wed, 7 Aug 2024 17:29:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman Co-authored-by: Paul Kirth --- clang/lib/CodeGen/CGExpr.cpp | 59 +- clang/test/CodeGen/bit-int-ubsan.c| 96 ++ compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 33 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 42 + .../test/ubsan/TestCases/Integer/bit-int.c| 170 ++ 6 files changed, 404 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGen/bit-int-ubsan.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 534f46da748627..060ab84992a7e5 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from discussion of issue 64100. +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert(getContext().getTypeSize(T) > 0 && + " non positive amount of bits in __BitInt type"); + assert(getContext().getTypeSize(T) <= 0x && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intp
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol closed https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-clang-x86_64-sie-ubuntu-fast` running on `sie-linux-worker` while building `clang,compiler-rt` at step 6 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/144/builds/4702 Here is the relevant piece of the build log for the reference: ``` Step 6 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang :: CodeGen/bit-int-ubsan.c' FAILED Exit Code: 2 Command Output (stderr): -- RUN: at line 2: /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/bit-int-ubsan.c | /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/bit-int-ubsan.c + /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/bit-int-ubsan.c + /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/bit-int-ubsan.c /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/bit-int-ubsan.c:7:10: fatal error: 'stdio.h' file not found 7 | #include | ^ 1 error generated. FileCheck error: '' is empty. FileCheck command line: /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/bit-int-ubsan.c -- ``` https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-clang-x86_64-sie-win` running on `sie-win-worker` while building `clang,compiler-rt` at step 7 "test-build-unified-tree-check-all". Full details are available at: https://lab.llvm.org/buildbot/#/builders/46/builds/3307 Here is the relevant piece of the build log for the reference: ``` Step 7 (test-build-unified-tree-check-all) failure: test (failure) TEST 'Clang :: CodeGen/bit-int-ubsan.c' FAILED Exit Code: 2 Command Output (stdout): -- # RUN: at line 2 z:\b\llvm-clang-x86_64-sie-win\build\bin\clang.exe -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - Z:\b\llvm-clang-x86_64-sie-win\llvm-project\clang\test\CodeGen\bit-int-ubsan.c | z:\b\llvm-clang-x86_64-sie-win\build\bin\filecheck.exe Z:\b\llvm-clang-x86_64-sie-win\llvm-project\clang\test\CodeGen\bit-int-ubsan.c # executed command: 'z:\b\llvm-clang-x86_64-sie-win\build\bin\clang.exe' -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - 'Z:\b\llvm-clang-x86_64-sie-win\llvm-project\clang\test\CodeGen\bit-int-ubsan.c' # .---command stderr # | Z:\b\llvm-clang-x86_64-sie-win\llvm-project\clang\test\CodeGen\bit-int-ubsan.c:7:10: fatal error: 'stdio.h' file not found # | 7 | #include # | | ^ # | 1 error generated. # `- # error: command failed with exit status: 1 # executed command: 'z:\b\llvm-clang-x86_64-sie-win\build\bin\filecheck.exe' 'Z:\b\llvm-clang-x86_64-sie-win\llvm-project\clang\test\CodeGen\bit-int-ubsan.c' # .---command stderr # | FileCheck error: '' is empty. # | FileCheck command line: z:\b\llvm-clang-x86_64-sie-win\build\bin\filecheck.exe Z:\b\llvm-clang-x86_64-sie-win\llvm-project\clang\test\CodeGen\bit-int-ubsan.c # `- # error: command failed with exit status: 2 -- ``` https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,96 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s + +// The runtime test checking the _BitInt ubsan feature is located in compiler-rt/test/ubsan/TestCases/Integer/bit-int.c + +#include +#include AaronBallman wrote: Please replace these includes with the declarations needed from them -- this makes the tests more stable because they won't be relying on whatever system CRT headers are installed. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
thurstond wrote: One of the tests is failing: ``` compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c:31:15: error: CHECK-NOT: excluded string found in input // CHECK-NOT: runtime error: ^ :1:110: note: found here compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c:11:10: runtime error: implicit conversion from type '_BitInt(37)' of value 60129542145 (64-bit, signed) to type 'uint32_t' (aka 'unsigned int') changed the value to 1 (32-bit, unsigned) ^~ ``` https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: On what platform this failure is observed? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: > One of the tests is failing: > > ``` > $ LIT_FILTER=bit-int-pass ninja check-ubsan > > compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c:31:15: error: > CHECK-NOT: excluded string found in input > // CHECK-NOT: runtime error: > ^ > :1:110: note: found here > compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c:11:10: runtime error: > implicit conversion from type '_BitInt(37)' of value 60129542145 (64-bit, > signed) to type 'uint32_t' (aka 'unsigned int') changed the value to 1 > (32-bit, unsigned) > >^~ > ``` On what target you observe the failure? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
thurstond wrote: > > One of the tests is failing: > > ``` > > $ LIT_FILTER=bit-int-pass ninja check-ubsan > > > > compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c:31:15: error: > > CHECK-NOT: excluded string found in input > > // CHECK-NOT: runtime error: > > ^ > > :1:110: note: found here > > compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c:11:10: runtime > > error: implicit conversion from type '_BitInt(37)' of value 60129542145 > > (64-bit, signed) to type 'uint32_t' (aka 'unsigned int') changed the value > > to 1 (32-bit, unsigned) > > > > ^~ > > ``` > > On what target you observe the failure? x86-64 Linux https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
rorth wrote: The patch also broke the [Solaris/sparcv9 buildbot](https://lab.llvm.org/buildbot/#/builders/13/builds/1579). https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,25 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +DCHECK(isBitIntTy()); +DCHECK(isSignedBitIntTy()); +// Scan Name for zero and return the next address +const char *p = getTypeName(); +while (*p != '\0') + ++p; +// Return the next address +return p + 1; + } + + unsigned getIntegerBitCount() const { +DCHECK(isIntegerTy()); +if (isSignedBitIntTy()) + return *reinterpret_cast(getBitIntBitCountPointer()); earnol wrote: Well. I do agree with this statement, however do we have a way to know whether target has a strict alignment or not? Preferably on the define level or you would suggest use always use memcpy? I considered this option, but was really reluctant to add memcpy dependency into libubsan. So may be the better option is gather it byte by byte a strict alignment platform. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -103,6 +103,13 @@ class TypeDescriptor { /// representation is that of bitcasting the floating-point value to an /// integer type. TK_Float = 0x0001, +/// An _BitInt(N) type. Lowest bit is 1 for a signed value, 0 for an +/// unsigned value. Remaining bits are log_2(bit_width). The value earnol wrote: It's interesting problem. I have not changed the way _BitInts are encoded in the memory. My understanding is that might not be right approach to have too many meanings embedded into one field depending on the context. Please note we have only 15 bits here (lowest bit is a sign). Standard requires us to support N up to BITINT_MAXWIDTH which is quite high. The standard says: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2709.pdf _The macro BITINT_MAXWIDTH represents the maximum width N supported in the declaration of a bit-precise integer type (6.2.5) in the type specifier _BitInt(N). The value BITINT_MAXWIDTH shall expand to a value that is greater than or equal to the value of ULLONG_WIDTH._ It means it will not fit :( Also why we do need endianess? Cannot we always use endianess of the target platform? We always know it at the moment of code generation. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,25 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +DCHECK(isBitIntTy()); +DCHECK(isSignedBitIntTy()); +// Scan Name for zero and return the next address +const char *p = getTypeName(); +while (*p != '\0') + ++p; +// Return the next address +return p + 1; + } + + unsigned getIntegerBitCount() const { +DCHECK(isIntegerTy()); +if (isSignedBitIntTy()) + return *reinterpret_cast(getBitIntBitCountPointer()); bjope wrote: For example Value::getFloatValue() in ubsan_value.cpp is using internal_memcpy from sanitizer_libc. Maybe that is an option here. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -103,6 +103,13 @@ class TypeDescriptor { /// representation is that of bitcasting the floating-point value to an /// integer type. TK_Float = 0x0001, +/// An _BitInt(N) type. Lowest bit is 1 for a signed value, 0 for an +/// unsigned value. Remaining bits are log_2(bit_width). The value bjope wrote: The new thing in this patch is that the size of the _BitInt type being described is stored after the type string. It can be read using `getIntegerBitCount()`. Thus, to get the size of the type being described one should no longer use `getIntegerBitWidth()` but instead `getIntegerBitCount()`. The latter would give correct result for both TK_Integer and TK_BitInt, while the former doesn't work for BitInt. IMHO it had been better to keep the name `getIntegerBitWidth()` for this purpose. Now I figure most/all old uses of `getIntegerBitWidth()` actually should be replaced with calls to `getIntegerBitCount()`, but that has not happened as far as I can tell. The new behavior of `getIntegerBitWidth()` is merely to indicate the size used to store the Value being represented when it does not fit inside the ValueHandle. So there shouldn't really be any need to use that function outside `Value::getSIntValue()` (assuming that `getIntegerBitCount()` would know how to get the size of TK_Integer via the TypeInfo field by itself). And unfortunatly there isn't much information about how those non-inlined values are store. The `Value::getSIntValue()` functions is just reading an s64 or s128 from memory (and that is what it traditionally has been doing for TK_Integer). But then I think the IR emitted by clang should cast the value to i64/i128 instead of doing ``` RawAddress Ptr = CreateDefaultAlignTempAlloca(V->getType()); Builder.CreateStore(V, Ptr); ``` Now we for example get things like `store i66 %x, ptr %tmp` which is storing a non byte-sized value to memory, which then is loaded by the runtime as a 128-bit value. Worth noting is that after commit 9ad72df55cb74b2919327 (#91364) the frontend emits byte-sized loads/stores for _BitInt. So I really think the store emitted by CodeGenFunction::EmitCheckValue for the BitInt values should zero/sign extended similarly (as if they were casted to "s64" or "s128" before being stored). That would at least make the code a bit more consistent (even though the question about supporting values larger than 128-bits would remain). https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,25 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +DCHECK(isBitIntTy()); +DCHECK(isSignedBitIntTy()); +// Scan Name for zero and return the next address +const char *p = getTypeName(); +while (*p != '\0') + ++p; +// Return the next address +return p + 1; + } + + unsigned getIntegerBitCount() const { +DCHECK(isIntegerTy()); +if (isSignedBitIntTy()) + return *reinterpret_cast(getBitIntBitCountPointer()); jakubjelinek wrote: If it isn't performance critical, guess using internal_memcpy is an option as well. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
jakubjelinek wrote: I'm not suggesting to encode the number of limbs anywhere, I'm suggesting encoding the bit precision of a limb somewhere. And the limb ordering. On little endian of bits in a limb and little endian ordering of limbs in the limb array, at least if the limbs are sane (have precision multiple of char precision and there are no padding bits in between), the actual limb precision might seem to be irrelevant, all you care about is the N from {,{un,}signed }_BitInt(N) and whether it is unsigned or signed, so you can treat the passed pointer say as an array of 8-bit limbs, N / 8 limbs with full 8 bits and if N % 8, the last limb containing some further bits (in some ABIs that will be required to be sign or zero extended, in other ABIs the padding bits will be undefined, but on the libubsan side you can always treat them as undefined and always manually extend). Or treat it as 16-bit limbs, or 32-bit limbs, or 64-bit limbs, or 128-bit limbs, for the higher perhaps with doing the limb reads again using internal_memcpy so that you don't impose some alignment requirement perhaps the target doesn't have. But on big-endian, I think knowing the limb precision/size is already essential (sure, just a theory for now, GCC right only only supports _BitInt on little-endian targets because those are the only ones that have specified their ABI). E.g. I believe _BitInt(513) big-endian with big-endian limb ordering would be for 32-bit limbs 17 limbs, the first one containing just one bit (the most significant of the whole number) and the remaining ones each 32 bits, while for 64-bit limbs 9 limbs, the first one containing just one bit and the remaining ones 64 bits each; and for 128-bit limbs 5 limbs, the first one just one bit, the remaining 128 bits each. You can't decode these without knowing the limb size, the data looks different in memory. And then there is the possibility of big-endian limbs with little-endian ordering of the limbs in the array. As the 15 bits of the current precision used e.g. for normal integers is clearly insufficient to express supported BITINT_MAXWIDTH (8388608 in clang, 65535 right now in GCC), my suggestion is to use another bit for the limb ordering (say 0 little endian, 1 big endian) and the reaming 14 bits for the limb precision (whether log2 or not doesn't matter that much). As for the actual _BitInt precision after the type name, one option is what you currently implemented, i.e. always use 32-bit integer in memory there, plus the extra '\0' termination if you really think it is needed, IMHO it is just a waste, and another option is to use say uleb128 encoding of it. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: Added https://github.com/llvm/llvm-project/pull/104494 to address failures with non-x86 targets as those platforms might produce failures. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
thurstond wrote: > Added #104494 to address failures with non-x86 targets as those platforms > might produce failures. Thank you! https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,26 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +CHECK(isBitIntTy()); +CHECK(isSignedBitIntTy()); +// Scan Name for zero and return the next address +const char *p = getTypeName(); +while (*p != '\0') { earnol wrote: Accepted. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,42 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s earnol wrote: Not sure. Previous reviewer asked me to move those cases into separate file and it makes sense to keep positive and negative cases separated. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 earnol wrote: Accepted. I have no strong opinion here. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(), StringRef(), std::nullopt, Buffer, std::nullopt); + if (IsBitInt) { +// The Structure is: 0 to end the string, 32 bit unsigned integer in target +// endianness, zero. +char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'}; earnol wrote: It is not used explicitly and serves as a guard byte. The idea is to have 2 consecutive zero bytes at the end of the line. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,96 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s + +// The runtime test checking the _BitInt ubsan feature is located in compiler-rt/test/ubsan/TestCases/Integer/bit-int.c + +#include +#include earnol wrote: Yes. Already working on it. Those are not really needed for non compiler-rt tests. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,26 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +CHECK(isBitIntTy()); earnol wrote: Since it's a runtime: accepted. It makes sense to make it as small as possible. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && earnol wrote: Accepted. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,96 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s + +// The runtime test checking the _BitInt ubsan feature is located in compiler-rt/test/ubsan/TestCases/Integer/bit-int.c + +#include +#include earnol wrote: Created https://github.com/llvm/llvm-project/pull/104462. Testing it. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
nikic wrote: The clang test also fails on s390x (big endian): ``` RUN: at line 2: /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/llvm/s390x-redhat-linux-gnu/bin/clang -cc1 -internal-isystem /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/llvm/s390x-redhat-linux-gnu/bin/../lib/clang/20/include -nostdsysteminc -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -emit-llvm -o - /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c | /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/llvm/s390x-redhat-linux-gnu/bin/FileCheck /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c + /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/llvm/s390x-redhat-linux-gnu/bin/clang -cc1 -internal-isystem /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/llvm/s390x-redhat-linux-gnu/bin/../lib/clang/20/include -nostdsysteminc -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -emit-llvm -o - /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c + /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/llvm/s390x-redhat-linux-gnu/bin/FileCheck /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c:11:12: error: CHECK: expected string not found in input // CHECK: constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(37)'\00%\00\00\00\00\00" } ^ :7:100: note: scanning from here @0 = private unnamed_addr constant { i16, i16, [8 x i8] } { i16 1, i16 32, [8 x i8] c"'float'\00" } ^ :8:27: note: possible intended match here @1 = private unnamed_addr constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(37)'\00\00\00\00%\00\00" } ^ Input file: Check file: /builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c -dump-input=help explains the following input dump. Input was: << 1: ; ModuleID = '/builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c' 2: source_filename = "/builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c" 3: target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64" 4: target triple = "s390x-redhat-linux-gnu" 5: 6: @.src = private unnamed_addr constant [111 x i8] c"/builddir/build/BUILD/llvm-project-ec29660c44e5e73d3b78f4884f9178036563fb25/clang/test/CodeGen/bit-int-ubsan.c\00", align 2 7: @0 = private unnamed_addr constant { i16, i16, [8 x i8] } { i16 1, i16 32, [8 x i8] c"'float'\00" } check:11'0 X error: no match found 8: @1 = private unnamed_addr constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(37)'\00\00\00\00%\00\00" } check:11'0 check:11'1 ? possible intended match 9: @2 = private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr } { { ptr, i32, i32 } { ptr @.src, i32 10, i32 19 }, ptr @0, ptr @1 } check:11'0 ~ 10: @3 = private unnamed_addr constant { i16, i16, [32 x i8] } { i16 0, i16 10, [32 x i8] c"'uint32_t' (aka 'unsigned int')\00" } check:11'0 ~~~
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
AaronBallman wrote: @earnol -- given the amount of breakage, can you revert the changes to get all bots back to green, then we can re-land once you have everything fixed up? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: How i can see the full amount of breakage on different platforms proactively? I have created a PR: https://github.com/llvm/llvm-project/pull/104607 to address the big endian issue with the test as my // REQUIRES: x86-registered-target turned out not to be enough to exclude running test in the big endian platforms. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
ilovepi wrote: Unfortunately, I don't think we have a way to run a patch on post-submit bots before it lands. I think everyone has been frustrated by that limitation at one time or another. I usually ask the reporters/bot owners if its possible. If they're able to help, most contributors are more than willing to help you test a patch. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: Since automatic revert is not working i have applied https://github.com/llvm/llvm-project/pull/104607 and monitoring builders. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: > Please pass an explicit `-triple` to `%clang_cc1` if the test is not supposed > to be big endian compatible. This had been done in https://github.com/llvm/llvm-project/pull/104607. Please check. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
AaronBallman wrote: > How i can see the full amount of breakage on different platforms proactively? > I have created a PR: #104607 to address the big endian issue with the test as > my // REQUIRES: x86-registered-target turned out not to be enough to exclude > running test in the big endian platforms. If you insisting on reverting PR > completely it is also fine, but it would be useful to see the full list of > errors on different platforms so i would be able to address those. Ah, if that's resolving the issues, then that's totally fine to fix forward rather than revert. Thank you! https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
vitalybuka wrote: > > How i can see the full amount of breakage on different platforms > > proactively? I have created a PR: #104607 to address the big endian issue > > with the test as my // REQUIRES: x86-registered-target turned out not to be > > enough to exclude running test in the big endian platforms. If you > > insisting on reverting PR completely it is also fine, but it would be > > useful to see the full list of errors on different platforms so i would be > > able to address those. > > Ah, if that's resolving the issues, then that's totally fine to fix forward > rather than revert. Thank you! Also it's totally fine to revert/reland multiple times, incrementally detecting and fixing breakages related to the patch. Broken build bot will more likely hide other breakages, making it harder to restore bots into green state. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: As i see the fedora build is fine: https://github.com/fedora-llvm-team/llvm-snapshots/issues/649. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(), StringRef(), std::nullopt, Buffer, std::nullopt); + if (IsBitInt) { +// The Structure is: 0 to end the string, 32 bit unsigned integer in target +// endianness, zero. +char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'}; AdamMagierFOSS wrote: Probably a bit too late to the party and I struggle with following discussion history on GitHub, but what was the reasoning behind storing the bit width encoded in the name of the type versus parsing out the bit width from the name of the type itself in the runtime (e.g. parsing out the value 37 from '_BitInt(37)' instead of extracting the literal 37 from '_BitInt(37)\x00\x25\x00\x00\x00' )? I would imagine that the former would be easier since there wouldn't be any platform dependence when traversing the string, and I don't think it would incur too much of an extra performance hit (the solution might look a bit kludgey though) https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(), StringRef(), std::nullopt, Buffer, std::nullopt); + if (IsBitInt) { +// The Structure is: 0 to end the string, 32 bit unsigned integer in target +// endianness, zero. +char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'}; earnol wrote: This was initial idea proposed in https://github.com/llvm/llvm-project/issues/64100. Parsing from the string is a reasonable idea, but 1. It will put additional performance burden on the runtime as we will need to do parsing in the runtime. It will require either regexp or FSM for parsing. Please read comments above when i have been requested to change CHECK to DCHECK for the performance reasons. And using sscanf or regexp will definitely put much serious burden on runtime compared to icmp. 2. This string is not used for anything but for diagnostics currently. Probably putting additional meaning for it is fine, but ... (see next point) 3. It will go against already implemented principles where we using pre-parsed data. If we are allowed to parse the type we do not need Type and Kind members of the TypeDescriptor. All this information can be extracted from the type string as it will become the single source of truth. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from discussion of issue 64100. +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { bjope wrote: Is this whole patch limited to fixing the non-power-of-2 problem for signed BitInt? I couldn't see any test involving unsigned BitInt, and the check for signed here makes me think that we still got the same bug for type descriptors for unsigned BitInt. If that is true, was there any specific reason for not fixing the type descriptors for unsigned BitInt as well directly? If for example the reasoning is that the runtimes currently do not try to print the size anyway for any failures involving unsigned BitInt, maybe it had been worth mentioning that here. Because now it just looks broken to me that we still can't provide a correct type descriptor for unsigned BitInt. Right? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from discussion of issue 64100. +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { earnol wrote: The whole patch is limited to signed non-power-of-2 _BitInt only. Unsigned BitInts are not affected by the patch and did not have an issue to begin with. Please see the issue: https://github.com/llvm/llvm-project/issues/64100. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,25 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +DCHECK(isBitIntTy()); +DCHECK(isSignedBitIntTy()); +// Scan Name for zero and return the next address +const char *p = getTypeName(); +while (*p != '\0') + ++p; +// Return the next address +return p + 1; + } + + unsigned getIntegerBitCount() const { +DCHECK(isIntegerTy()); +if (isSignedBitIntTy()) + return *reinterpret_cast(getBitIntBitCountPointer()); jakubjelinek wrote: This will not work on strict alignment targets. I'd suggest instead of trying to reinterpret the bits memcpy them into u32 and return that, the compilers will optimize that properly. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -103,6 +103,13 @@ class TypeDescriptor { /// representation is that of bitcasting the floating-point value to an /// integer type. TK_Float = 0x0001, +/// An _BitInt(N) type. Lowest bit is 1 for a signed value, 0 for an +/// unsigned value. Remaining bits are log_2(bit_width). The value jakubjelinek wrote: bit_width of what? The main problem is that the _BitInt ABI is only defined in the x86-64 and aarch64 psABIs, for i686 the word was that the ABI should be whatever GCC implemented, but nobody updated the ia32 psABI yet. I think ARM 32-bit is defined too, some other targets are working on it. As documented in LLVM, it implements _BitInt everywhere but notes that the ABI can change (GCC took a different approach, only implementing it for arches which agree on an ABI). So, if compiler-rt implements _BitInt support, it better be able to encode the various ABIs which will be used for _BitInt on various arches. The current ABIs usually have some special cases for smaller number of bits, but those generally can be encoded as normal integer (sign or zero extended say to long long or __int128). For the large _BitInts, x86_64 uses little endian ordered array of 64-bit limbs, aarch64 little or big endian ordered array of 128-bit limbs, ia32 little endian ordered array of 32-bit limbs. But I was told the powerpc folks are considering little endian ordering of limbs on both ppc64le and ppc64 big-endian. So, I think you certainly want to encode the limb size and the N from _BitInt(N) and whether it is signed or unsigned and possibly (e.g. for ppc64) also whether the limbs are ordered from least significant to most or vice versa (bit ordering within limb would be normally dependent on endianity). So, I think that bit_width in the bits above sign should be the limb size, not _BitInt size rounded up or whatever you're implementing right now. And encode somewhere the endianity too. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,174 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=RUNTIME +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=IR earnol wrote: Anyways, the test was duplicated. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: Ping! Any additional suggestions for the improvements? Selfishly want to move it forward :) https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,170 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s MaskRay wrote: The -fsanitize= option lists a lot of unused checks. Clean up them to list only used checks https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,42 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s MaskRay wrote: You can merge these tests into `bit-int.c` by utilizing `--implicit-check-not="runtime error:"` https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/MaskRay edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/MaskRay requested changes to this pull request. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(), StringRef(), std::nullopt, Buffer, std::nullopt); + if (IsBitInt) { +// The Structure is: 0 to end the string, 32 bit unsigned integer in target +// endianness, zero. +char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'}; MaskRay wrote: How is the trailing zero byte used? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && MaskRay wrote: The prevailing style uses `A > B && `, not `(A > B) && ` another choice is `assert(("", A > B))` https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 MaskRay wrote: Consider removing this link. Authority resides in code or formal documentation, not an /issues/ link. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,26 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +CHECK(isBitIntTy()); MaskRay wrote: CHECK unconditionally compiles to additional code. perhaps DCHECK https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -125,6 +137,26 @@ class TypeDescriptor { return 1 << (TypeInfo >> 1); } + const char *getBitIntBitCountPointer() const { +CHECK(isBitIntTy()); +CHECK(isSignedBitIntTy()); +// Scan Name for zero and return the next address +const char *p = getTypeName(); +while (*p != '\0') { MaskRay wrote: drop braces https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
earnol wrote: One more ping as week passed from the previous one. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/AaronBallman commented: The changes seem reasonable to me, but I don't have a lot of expertise with compiler-rt. Should the changes come with a release note though? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,42 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s + +#include +#include + +// In this test there is an expectation of assignment of _BitInt not producing any output. +uint32_t nullability_arg(_BitInt(37) *_Nonnull x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + _BitInt(37) y = *(_BitInt(37) *)&x; + return (y > 0) ? y : 0; +} + +// In this test there is an expectation of ubsan not triggeting on returning random address which is inside address space of the process. +_BitInt(37) nonnull_attribute(__attribute__((nonnull)) _BitInt(37) * x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + return *(_BitInt(37) *)&x; +} + +// In this test there is an expectation of assignment of uint32_t from "invalid" _BitInt is not producing any output. +uint32_t nullability_assign(_BitInt(7) * x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + _BitInt(7) *_Nonnull y = x; + int32_t r = *(_BitInt(7) *)&y; + return (r > 0) ? r : 0; +} + +// In those examples the file is expected to compile&run with no diagnostics earnol wrote: What typo you are talking about? 'compile & run' vs 'compile&run'? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,42 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s + +#include +#include + +// In this test there is an expectation of assignment of _BitInt not producing any output. +uint32_t nullability_arg(_BitInt(37) *_Nonnull x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + _BitInt(37) y = *(_BitInt(37) *)&x; + return (y > 0) ? y : 0; +} + +// In this test there is an expectation of ubsan not triggeting on returning random address which is inside address space of the process. +_BitInt(37) nonnull_attribute(__attribute__((nonnull)) _BitInt(37) * x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + return *(_BitInt(37) *)&x; +} + +// In this test there is an expectation of assignment of uint32_t from "invalid" _BitInt is not producing any output. +uint32_t nullability_assign(_BitInt(7) * x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + _BitInt(7) *_Nonnull y = x; + int32_t r = *(_BitInt(7) *)&y; + return (r > 0) ? r : 0; +} + +// In those examples the file is expected to compile&run with no diagnostics ilovepi wrote: yes. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,42 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s + +#include +#include + +// In this test there is an expectation of assignment of _BitInt not producing any output. +uint32_t nullability_arg(_BitInt(37) *_Nonnull x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + _BitInt(37) y = *(_BitInt(37) *)&x; + return (y > 0) ? y : 0; +} + +// In this test there is an expectation of ubsan not triggeting on returning random address which is inside address space of the process. +_BitInt(37) nonnull_attribute(__attribute__((nonnull)) _BitInt(37) * x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + return *(_BitInt(37) *)&x; +} + +// In this test there is an expectation of assignment of uint32_t from "invalid" _BitInt is not producing any output. +uint32_t nullability_assign(_BitInt(7) * x) +__attribute__((no_sanitize("address"))) +__attribute__((no_sanitize("memory"))) { + _BitInt(7) *_Nonnull y = x; + int32_t r = *(_BitInt(7) *)&y; + return (r > 0) ? r : 0; +} + +// In those examples the file is expected to compile&run with no diagnostics earnol wrote: It did not look like a typo for me because i always used '&' without surrounding spaces. So it was "intentional" typo. Unfortunately for me, googling showed 'compile & run' is more widespread compared to 'compile&run'. Thus ==> accepted. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol created https://github.com/llvm/llvm-project/pull/96240 Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previously called _ExtInt) type. This patch affects affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. This patch fixes issue https://github.com/llvm/llvm-project/issues/64100. >From e060cb92d92024ae1e148b3f04456de351800466 Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Fri, 24 May 2024 11:39:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman --- clang/lib/CodeGen/CGExpr.cpp | 59 +- compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 34 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 39 .../test/ubsan/TestCases/Integer/bit-int.c| 174 ++ 5 files changed, 310 insertions(+), 13 deletions(-) create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d6478cc6835d8..415c3696b717e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3292,22 +3309,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && + " non positive amount of bits in __BitInt type"); + assert((getContext().getTypeSize(T) <= 0x) && + " too many bits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
llvmbot wrote: @llvm/pr-subscribers-compiler-rt-sanitizer @llvm/pr-subscribers-clang-codegen Author: None (earnol) Changes Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previously called _ExtInt) type. This patch affects affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. This patch fixes issue https://github.com/llvm/llvm-project/issues/64100. --- Full diff: https://github.com/llvm/llvm-project/pull/96240.diff 5 Files Affected: - (modified) clang/lib/CodeGen/CGExpr.cpp (+54-5) - (modified) compiler-rt/lib/ubsan/ubsan_value.cpp (+10-7) - (modified) compiler-rt/lib/ubsan/ubsan_value.h (+33-1) - (added) compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c (+39) - (added) compiler-rt/test/ubsan/TestCases/Integer/bit-int.c (+174) ``diff diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d6478cc6835d8..415c3696b717e 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3292,22 +3309,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && + " non positive amount of bits in __BitInt type"); + assert((getContext().getTypeSize(T) <= 0x) && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3318,6 +3353,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(), StringRef(), std::nullopt, Buffer, std::nullopt); + if (IsBitInt) { +// The Structure is: 0 to end the string, 32 bit unsigned integer in target +// endianness, zero. +char S[6] = {'\0', '\0', '\0', '\0', '\0', '\0'}; +const auto *EIT = T->castAs(); +uint32_t Bits = EIT->getNumBits(); +
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,174 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=RUNTIME +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=IR + +#include +#include + +uint32_t float_divide_by_zero() { + float f = 1.0f / 0.0f; + // IR: constant { i16, i16, [8 x i8] } { i16 1, i16 32, [8 x i8] c"'float'\00" } + _BitInt(37) r = (_BitInt(37))f; + // RUNTIME: {{.*}}bit-int.c:[[@LINE-1]]:19: runtime error: inf is outside the range of representable values of type + // IR: constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(37)'\00%\00\00\00\00\00" } + return r; +} + +uint32_t integer_divide_by_zero() __attribute__((no_sanitize("memory"))) { + _BitInt(37) x = 1 / 0; + // RUNTIME: {{.*}}bit-int.c:[[@LINE-1]]:21: runtime error: division by zero MaskRay wrote: `[[@LINE]]` is legacy. Prefer `[[#@LINE]]` for new code https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-pseudo-numeric-variables https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,174 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=RUNTIME +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=IR MaskRay wrote: compiler-rt/test is for runtime tests. IR tests, if related to clang, are placed in clang/test/, usually CodeGen or CodeGenCXX. This means that sometimes we have to duplicate tests. If useful, you can add a comment to tell future readers how to find related tests. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,174 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=RUNTIME +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=IR earnol wrote: Duplication looks really ugly. Is there is a way to run IR test and runtime test on the same code? https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
@@ -0,0 +1,174 @@ +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -O0 -fsanitize=alignment,array-bounds,bool,float-cast-overflow,implicit-integer-sign-change,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,integer-divide-by-zero,nonnull-attribute,null,nullability-arg,nullability-assign,nullability-return,pointer-overflow,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,unsigned-integer-overflow,unsigned-shift-base,vla-bound %s -o %t1 && %run %t1 2>&1 | FileCheck %s --check-prefix=RUNTIME +// RUN: %clang -Wno-constant-conversion -Wno-array-bounds -Wno-division-by-zero -Wno-shift-negative-value -Wno-shift-count-negative -Wno-int-to-pointer-cast -fsanitize=array-bounds,enum,float-cast-overflow,integer-divide-by-zero,implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change,unsigned-integer-overflow,signed-integer-overflow,shift-base,shift-exponent -O0 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=IR + +#include +#include + +uint32_t float_divide_by_zero() { + float f = 1.0f / 0.0f; + // IR: constant { i16, i16, [8 x i8] } { i16 1, i16 32, [8 x i8] c"'float'\00" } + _BitInt(37) r = (_BitInt(37))f; + // RUNTIME: {{.*}}bit-int.c:[[@LINE-1]]:19: runtime error: inf is outside the range of representable values of type + // IR: constant { i16, i16, [20 x i8] } { i16 2, i16 13, [20 x i8] c"'_BitInt(37)'\00%\00\00\00\00\00" } + return r; +} + +uint32_t integer_divide_by_zero() __attribute__((no_sanitize("memory"))) { + _BitInt(37) x = 1 / 0; + // RUNTIME: {{.*}}bit-int.c:[[@LINE-1]]:21: runtime error: division by zero earnol wrote: Accepted. https://github.com/llvm/llvm-project/pull/96240 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/96240 >From 00fb56c674f26f6d3455d77e37f8cad35d4aa95c Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Fri, 24 May 2024 11:39:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman --- clang/lib/CodeGen/CGExpr.cpp | 59 ++- clang/test/CodeGen/bit-int-ubsan.c| 95 +++ compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 34 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 42 + .../test/ubsan/TestCases/Integer/bit-int.c| 161 ++ 6 files changed, 395 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGen/bit-int-ubsan.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d6478cc6835d8..a1a8755fd91e8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3292,22 +3309,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && + " non positive amount of bits in __BitInt type"); + assert((getContext().getTypeSize(T) <= 0x) && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3318,6 +3353,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRe
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/96240 >From a6b6a1cf8ded271e1b1f29ad67daf77e135e0a7b Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Fri, 24 May 2024 11:39:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman --- clang/lib/CodeGen/CGExpr.cpp | 59 +- clang/test/CodeGen/bit-int-ubsan.c| 95 ++ compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 34 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 42 + .../test/ubsan/TestCases/Integer/bit-int.c| 170 ++ 6 files changed, 404 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGen/bit-int-ubsan.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d6478cc6835d8..a1a8755fd91e8 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3292,22 +3309,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && + " non positive amount of bits in __BitInt type"); + assert((getContext().getTypeSize(T) <= 0x) && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3318,6 +3353,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/96240 >From d01c49f85902d2ec660db2cb32dc2d1e0d04c393 Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Fri, 24 May 2024 11:39:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman --- clang/lib/CodeGen/CGExpr.cpp | 59 +- clang/test/CodeGen/bit-int-ubsan.c| 95 ++ compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 34 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 42 + .../test/ubsan/TestCases/Integer/bit-int.c| 170 ++ 6 files changed, 404 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGen/bit-int-ubsan.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 534f46da74862..cebfe98eda97f 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && + " non positive amount of bits in __BitInt type"); + assert((getContext().getTypeSize(T) <= 0x) && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(
[clang] [compiler-rt] [ubsan] Display correct runtime messages for negative _BitInt (PR #96240)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/96240 >From 6e0294e5debf0fe694fcf56c8cd2d35e7225d639 Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Fri, 24 May 2024 11:39:35 -0400 Subject: [PATCH] [ubsan] Display correct runtime messages for negative _BitInt Without this patch compiler-rt ubsan library has a bug displaying incorrect values for variables of the _BitInt (previousely called _ExtInt) type. This patch affects both: generation of metadata inside code generator and runtime part. The runtime part provided only for i386 and x86_64 runtimes. Other runtimes should be updated to take full benefit of this patch. The patch is constructed the way to be backward compatible and int and float type runtime diagnostics should be unaffected for not yet updated runtimes. Co-authored-by: Aaron Ballman --- clang/lib/CodeGen/CGExpr.cpp | 59 +- clang/test/CodeGen/bit-int-ubsan.c| 96 ++ compiler-rt/lib/ubsan/ubsan_value.cpp | 17 +- compiler-rt/lib/ubsan/ubsan_value.h | 34 +++- .../ubsan/TestCases/Integer/bit-int-pass.c| 42 + .../test/ubsan/TestCases/Integer/bit-int.c| 170 ++ 6 files changed, 405 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGen/bit-int-ubsan.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int-pass.c create mode 100644 compiler-rt/test/ubsan/TestCases/Integer/bit-int.c diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 534f46da74862..cebfe98eda97f 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -41,6 +41,7 @@ #include "llvm/IR/MatrixBuilder.h" #include "llvm/Passes/OptimizationLevel.h" #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/SaveAndRestore.h" @@ -64,6 +65,22 @@ static llvm::cl::opt ClSanitizeGuardChecks( "ubsan-guard-checks", llvm::cl::Optional, llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`.")); +//======// +//Defines for metadata +//======// + +// Those values are crucial to be the SAME as in ubsan runtime library. +enum VariableTypeDescriptorKind : uint16_t { + /// An integer type. + TK_Integer = 0x, + /// A floating-point type. + TK_Float = 0x0001, + /// An _BitInt(N) type. + TK_BitInt = 0x0002, + /// Any other type. The value representation is unspecified. + TK_Unknown = 0x +}; + //======// //Miscellaneous Helper Methods //======// @@ -3298,22 +3315,40 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { /// { i16 TypeKind, i16 TypeInfo } /// \endcode /// -/// followed by an array of i8 containing the type name. TypeKind is 0 for an -/// integer, 1 for a floating point value, and -1 for anything else. +/// followed by an array of i8 containing the type name with extra information +/// for BitInt. TypeKind is TK_Integer(0) for an integer, TK_Float(1) for a +/// floating point value, TK_BitInt(2) for BitInt and TK_Unknown(0x) for +/// anything else. llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { // Only emit each type's descriptor once. if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T)) return C; - uint16_t TypeKind = -1; + uint16_t TypeKind = TK_Unknown; uint16_t TypeInfo = 0; + bool IsBitInt = false; if (T->isIntegerType()) { -TypeKind = 0; +TypeKind = TK_Integer; TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) | (T->isSignedIntegerType() ? 1 : 0); +// Follow suggestion from https://github.com/llvm/llvm-project/issues/64100 +// So we can write the exact amount of bits in TypeName after '\0' +// making it .'\0'.<32-bit width>. +if (T->isSignedIntegerType() && T->getAs()) { + // Do a sanity checks as we are using 32-bit type to store bit length. + assert((getContext().getTypeSize(T) > 0) && + " non positive amount of bits in __BitInt type"); + assert((getContext().getTypeSize(T) <= 0x) && + " too many bits in __BitInt type"); + + // Redefine TypeKind with the actual __BitInt type if we have signed + // BitInt. + TypeKind = TK_BitInt; + IsBitInt = true; +} } else if (T->isFloatingType()) { -TypeKind = 1; +TypeKind = TK_Float; TypeInfo = getContext().getTypeSize(T); } @@ -3324,6 +3359,20 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) { DiagnosticsEngine::ak_qualtype, (intptr_t)T.getAsOpaquePtr(), StringRef(