https://github.com/adams381 updated https://github.com/llvm/llvm-project/pull/191499
>From 3f0d5ffbec5e0265829c58d9bb3760434861abd1 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Fri, 10 Apr 2026 12:23:34 -0700 Subject: [PATCH 1/2] [CIR] Raise IntType max bitwidth to match LLVM IR Increase IntType::maxBitwidth() from 128 to 1<<23 (8388608) so CIR can represent the full range of _BitInt widths that Clang and LLVM IR support. Remove the now-dead errorNYI guard for large _BitInt in CIRGenTypes. Follow-up to #188113 addressing feedback from @erichkeane. Made-with: Cursor --- clang/include/clang/CIR/Dialect/IR/CIRTypes.td | 5 +++-- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 11 +++-------- clang/test/CIR/CodeGen/bitint.c | 5 +++++ clang/test/CIR/IR/bitint.cir | 5 +++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index c8e63a08847fe..504ec850ddb5a 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -90,8 +90,9 @@ def CIR_IntType : CIR_Type<"Int", "int", [ /// Returns a minimum bitwidth of cir::IntType static unsigned minBitwidth() { return 1; } - /// Returns a maximum bitwidth of cir::IntType - static unsigned maxBitwidth() { return 128; } + /// Returns a maximum bitwidth of cir::IntType. + /// Matches llvm::IntegerType::MAX_INT_BITS (1 << 23). + static unsigned maxBitwidth() { return (1 << 23); } }]; let genVerifyDecl = 1; } diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 9b493263b76c2..3ee8f15c5467b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -563,14 +563,9 @@ mlir::Type CIRGenTypes::convertType(QualType type) { case Type::BitInt: { const auto *bitIntTy = cast<BitIntType>(type); - if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) { - cgm.errorNYI(SourceLocation(), "large _BitInt type", type); - resultType = cgm.sInt32Ty; - } else { - resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(), - bitIntTy->isSigned(), - /*isBitInt=*/true); - } + resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(), + bitIntTy->isSigned(), + /*isBitInt=*/true); break; } diff --git a/clang/test/CIR/CodeGen/bitint.c b/clang/test/CIR/CodeGen/bitint.c index 014b315c907ba..6d91986c165ba 100644 --- a/clang/test/CIR/CodeGen/bitint.c +++ b/clang/test/CIR/CodeGen/bitint.c @@ -13,19 +13,24 @@ // CIR-DAG: !s128i_bitint = !cir.int<s, 128, bitint> // CIR-DAG: !u64i_bitint = !cir.int<u, 64, bitint> // CIR-DAG: !s128i = !cir.int<s, 128> +// CIR-DAG: !s256i_bitint = !cir.int<s, 256, bitint> // _BitInt(128) has alignment 8 while __int128 has alignment 16. signed _BitInt(128) bitint128_var; __int128 int128_var; +signed _BitInt(256) bitint256_var; // CIR: cir.global external @bitint128_var = #cir.int<0> : !s128i_bitint {alignment = 8 : i64} // CIR: cir.global external @int128_var = #cir.int<0> : !s128i {alignment = 16 : i64} +// CIR: cir.global external @bitint256_var = #cir.int<0> : !s256i_bitint // LLVM: @bitint128_var = global i128 0, align 8 // LLVM: @int128_var = global i128 0, align 16 +// LLVM: @bitint256_var = global i256 0 // OGCG: @bitint128_var = global i128 0, align 8 // OGCG: @int128_var = global i128 0, align 16 +// OGCG: @bitint256_var = global i256 0 void take_bitint_32(_BitInt(32) x) {} // CIR: cir.func {{.*}} @take_bitint_32(%arg0: !s32i_bitint diff --git a/clang/test/CIR/IR/bitint.cir b/clang/test/CIR/IR/bitint.cir index 5dddddc833777..c61f1b581b62e 100644 --- a/clang/test/CIR/IR/bitint.cir +++ b/clang/test/CIR/IR/bitint.cir @@ -5,10 +5,11 @@ !s32i_bitint = !cir.int<s, 32, bitint> !u64i_bitint = !cir.int<u, 64, bitint> !s128i_bitint = !cir.int<s, 128, bitint> +!s1024i_bitint = !cir.int<s, 1024, bitint> module { - // CHECK: cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: !s128i_bitint) - cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: !s128i_bitint) { + // CHECK: cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: !s128i_bitint, %arg3: !s1024i_bitint) + cir.func @round_trip_bitint(%arg0: !s32i_bitint, %arg1: !u64i_bitint, %arg2: !s128i_bitint, %arg3: !s1024i_bitint) { cir.return } >From c1397198265c7c8e03c62a4b446f53a4dcddc18f Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Mon, 13 Apr 2026 13:34:22 -0700 Subject: [PATCH 2/2] [CIR] Add _BitInt boundary tests and maxBitwidth assert Add _BitInt(254) and _BitInt(257) test cases to exercise non-power-of-2 bitwidths near the 256 boundary. Add a defense-in-depth assert that the _BitInt width does not exceed CIR IntType::maxBitwidth(). Addresses review feedback from @erichkeane and @andykaylor. Made-with: Cursor --- clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 9 ++++++--- clang/test/CIR/CodeGen/bitint.c | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 3ee8f15c5467b..883b791d5909c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -563,9 +563,12 @@ mlir::Type CIRGenTypes::convertType(QualType type) { case Type::BitInt: { const auto *bitIntTy = cast<BitIntType>(type); - resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(), - bitIntTy->isSigned(), - /*isBitInt=*/true); + unsigned numBits = bitIntTy->getNumBits(); + assert(numBits <= cir::IntType::maxBitwidth() && + "_BitInt width exceeds CIR IntType maximum"); + resultType = + cir::IntType::get(&getMLIRContext(), numBits, bitIntTy->isSigned(), + /*isBitInt=*/true); break; } diff --git a/clang/test/CIR/CodeGen/bitint.c b/clang/test/CIR/CodeGen/bitint.c index 6d91986c165ba..e84b610c171b6 100644 --- a/clang/test/CIR/CodeGen/bitint.c +++ b/clang/test/CIR/CodeGen/bitint.c @@ -19,18 +19,26 @@ signed _BitInt(128) bitint128_var; __int128 int128_var; signed _BitInt(256) bitint256_var; +signed _BitInt(254) bitint254_var; +signed _BitInt(257) bitint257_var; // CIR: cir.global external @bitint128_var = #cir.int<0> : !s128i_bitint {alignment = 8 : i64} // CIR: cir.global external @int128_var = #cir.int<0> : !s128i {alignment = 16 : i64} // CIR: cir.global external @bitint256_var = #cir.int<0> : !s256i_bitint +// CIR: cir.global external @bitint254_var = #cir.int<0> : !cir.int<s, 254, bitint> +// CIR: cir.global external @bitint257_var = #cir.int<0> : !cir.int<s, 257, bitint> // LLVM: @bitint128_var = global i128 0, align 8 // LLVM: @int128_var = global i128 0, align 16 // LLVM: @bitint256_var = global i256 0 +// LLVM: @bitint254_var = global i254 0, align 8 +// LLVM: @bitint257_var = global i257 0, align 8 // OGCG: @bitint128_var = global i128 0, align 8 // OGCG: @int128_var = global i128 0, align 16 // OGCG: @bitint256_var = global i256 0 +// OGCG: @bitint254_var = global i256 0, align 8 +// OGCG: @bitint257_var = global [40 x i8] zeroinitializer, align 8 void take_bitint_32(_BitInt(32) x) {} // CIR: cir.func {{.*}} @take_bitint_32(%arg0: !s32i_bitint @@ -47,6 +55,16 @@ void take_unsigned_bitint(unsigned _BitInt(64) x) {} // LLVM: define {{.*}} void @take_unsigned_bitint(i64 {{.*}}) // OGCG: define {{.*}} void @take_unsigned_bitint(i64 {{.*}}) +void take_bitint_254(signed _BitInt(254) x) {} +// CIR: cir.func {{.*}} @take_bitint_254(%arg0: !cir.int<s, 254, bitint> +// LLVM: define {{.*}} void @take_bitint_254(i254 {{.*}}) +// OGCG: define {{.*}} void @take_bitint_254(ptr noundef byval(i256) align 8 {{.*}}) + +void take_bitint_257(signed _BitInt(257) x) {} +// CIR: cir.func {{.*}} @take_bitint_257(%arg0: !cir.int<s, 257, bitint> +// LLVM: define {{.*}} void @take_bitint_257(i257 {{.*}}) +// OGCG: define {{.*}} void @take_bitint_257(ptr noundef byval([40 x i8]) align 8 {{.*}}) + // Regular __int128 should NOT have the bitint flag. void take_int128(__int128 x) {} // CIR: cir.func {{.*}} @take_int128(%arg0: !s128i _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
