https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/189954
>From 17f96eb874d732435a581d1098b9966646e8fa31 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <[email protected]> Date: Wed, 1 Apr 2026 05:53:46 -0700 Subject: [PATCH 1/2] [clang] Fix array filler lowering for _BitInt arrays Sometimes we use array of bytes to represent `_BitInt` types in memory. When this is the case the lowered array filler expression reaches `ConstantEmitter::emitForMemory` already with memory type which will be array of i8 instead of a single iN, so `cast<llvm::ConstantInt>` was failing. This patch fixes the assertion failure by not attempting any type changes if the type is right already. Fixes https://github.com/llvm/llvm-project/issues/189643 Assisted-by: claude in FileCkeck CHECK likes fixing --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/CodeGen/CGExprConstant.cpp | 40 ++++++++++++++++------------ clang/test/CodeGenCXX/ext-int.cpp | 30 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cd7f280fbb6db..e1d12bae134e5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -384,6 +384,7 @@ Bug Fixes in This Version - Correctly diagnosing and no longer crashing when ``export module foo`` (without a semicolon) are the final tokens in a module file. (#GH187771) - Fixed a crash in duplicate attribute checking caused by comparing constant arguments with different integer signedness. (#GH188259) +- Fixed a crash on _BitInt(N) arrays where 129 ≤ N ≤ 192 due to incorrect array filler lowering. (#GH189643) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index d69e825e0cbd7..8c6f40a170e6f 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -2032,24 +2032,30 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM, } if (destType->isBitIntType()) { - ConstantAggregateBuilder Builder(CGM); - llvm::Type *LoadStoreTy = CGM.getTypes().convertTypeForLoadStore(destType); - // ptrtoint/inttoptr should not involve _BitInt in constant expressions, so - // casting to ConstantInt is safe here. - auto *CI = cast<llvm::ConstantInt>(C); - llvm::Constant *Res = llvm::ConstantFoldCastOperand( - destType->isSignedIntegerOrEnumerationType() ? llvm::Instruction::SExt - : llvm::Instruction::ZExt, - CI, LoadStoreTy, CGM.getDataLayout()); - if (CGM.getTypes().typeRequiresSplitIntoByteArray(destType, C->getType())) { - // Long _BitInt has array of bytes as in-memory type. - // So, split constant into individual bytes. - llvm::Type *DesiredTy = CGM.getTypes().ConvertTypeForMem(destType); - llvm::APInt Value = cast<llvm::ConstantInt>(Res)->getValue(); - Builder.addBits(Value, /*OffsetInBits=*/0, /*AllowOverwrite=*/false); - return Builder.build(DesiredTy, /*AllowOversized*/ false); + llvm::Type *MemTy = CGM.getTypes().ConvertTypeForMem(destType); + if (C->getType() != MemTy) { + ConstantAggregateBuilder Builder(CGM); + llvm::Type *LoadStoreTy = + CGM.getTypes().convertTypeForLoadStore(destType); + // ptrtoint/inttoptr should not involve _BitInt in constant expressions, + // so casting to ConstantInt is safe here. + auto *CI = cast<llvm::ConstantInt>(C); + llvm::Constant *Res = llvm::ConstantFoldCastOperand( + destType->isSignedIntegerOrEnumerationType() + ? llvm::Instruction::SExt + : llvm::Instruction::ZExt, + CI, LoadStoreTy, CGM.getDataLayout()); + if (CGM.getTypes().typeRequiresSplitIntoByteArray(destType, + C->getType())) { + // Long _BitInt has array of bytes as in-memory type. + // So, split constant into individual bytes. + llvm::Type *DesiredTy = CGM.getTypes().ConvertTypeForMem(destType); + llvm::APInt Value = cast<llvm::ConstantInt>(Res)->getValue(); + Builder.addBits(Value, /*OffsetInBits=*/0, /*AllowOverwrite=*/false); + return Builder.build(DesiredTy, /*AllowOversized*/ false); + } + return Res; } - return Res; } return C; diff --git a/clang/test/CodeGenCXX/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp index a75b3701e36ef..a45720c53e877 100644 --- a/clang/test/CodeGenCXX/ext-int.cpp +++ b/clang/test/CodeGenCXX/ext-int.cpp @@ -67,6 +67,18 @@ struct HasBitIntMiddle { }; // CHECK: %struct.HasBitIntMiddle = type { i32, i64, i32 } +// Check array filler lowering. +namespace gh189643 { +_BitInt(129) arr[2] = {}; +// LIN64: {{.*}}arr{{.*}} = {{.*}}global [2 x [24 x i8]] zeroinitializer +// LIN32: {{.*}}arr{{.*}} = {{.*}}global [2 x [20 x i8]] zeroinitializer +// WIN: {{.*}}arr{{.*}} = {{.*}}global [2 x [24 x i8]] zeroinitializer +_BitInt(129) arr2[10] = {1}; +// LIN64: {{.*}}arr2{{.*}} = {{.*}}global <{ <{ i8, [23 x i8] }>, [9 x <{ i8, [23 x i8] }>] }> <{ <{ i8, [23 x i8] }> <{ i8 1, [23 x i8] zeroinitializer }>, [9 x <{ i8, [23 x i8] }>] zeroinitializer }> +// LIN32: {{.*}}arr2{{.*}} = {{.*}}global <{ <{ i8, [19 x i8] }>, [9 x <{ i8, [19 x i8] }>] }> <{ <{ i8, [19 x i8] }> <{ i8 1, [19 x i8] zeroinitializer }>, [9 x <{ i8, [19 x i8] }>] zeroinitializer }> +// WIN: {{.*}}arr2{{.*}} = {{.*}}global <{ <{ i8, [23 x i8] }>, [9 x <{ i8, [23 x i8] }>] }> <{ <{ i8, [23 x i8] }> <{ i8 1, [23 x i8] zeroinitializer }>, [9 x <{ i8, [23 x i8] }>] zeroinitializer }> +} + // Force emitting of the above structs. void StructEmit() { BitFieldsByte A; @@ -618,6 +630,24 @@ void TBAATest(_BitInt(sizeof(int) * 8) ExtInt, Other = 5; } +namespace gh189643 { +void test() { +// LIN: define{{.*}} void @_ZN8gh1896434testEv() +// WIN: define dso_local void @"?test@gh189643@@YAXXZ"() +_BitInt(140) arr3[2] = {}; +// LIN64: %[[ARR3:.+]] = alloca [2 x [24 x i8]], align 16 +// LIN32: %[[ARR3:.+]] = alloca [2 x [20 x i8]], align 4 +// WIN: %[[ARR3:.+]] = alloca [2 x [24 x i8]], +_BitInt(239) arr4[10] = {1}; +// CHECK: %[[ARR4:.+]] = alloca [10 x i256], +// LIN64: call void @llvm.memset{{.+}}(ptr align 16 %[[ARR3]], i8 0, i64 48, +// LIN32: call void @llvm.memset{{.+}}(ptr align 4 %[[ARR3]], i8 0, i32 40, +// WIN: call void @llvm.memset{{.+}}(ptr {{.*}} %[[ARR3]], i8 0, {{.*}} 48, +// CHECK: call void @llvm.memset{{.+}}(ptr {{.*}} %[[ARR4]], i8 0, {{.*}} 320, +// CHECK: store i256 1, ptr {{.*}} +} +} + // NoNewStructPathTBAA-DAG: ![[CHAR_TBAA_ROOT:.+]] = !{!"omnipotent char", ![[TBAA_ROOT:.+]], i64 0} // NoNewStructPathTBAA-DAG: ![[TBAA_ROOT]] = !{!"Simple C++ TBAA"} // NoNewStructPathTBAA-DAG: ![[EXTINT_TBAA]] = !{![[EXTINT_TBAA_ROOT:.+]], ![[EXTINT_TBAA_ROOT]], i64 0} >From 1b4e59876ce3945cc39a5c8731255ada96b23e7c Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <[email protected]> Date: Wed, 1 Apr 2026 06:24:51 -0700 Subject: [PATCH 2/2] Reuse new variable --- clang/lib/CodeGen/CGExprConstant.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 8c6f40a170e6f..24712d3325b2e 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -2049,10 +2049,9 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM, C->getType())) { // Long _BitInt has array of bytes as in-memory type. // So, split constant into individual bytes. - llvm::Type *DesiredTy = CGM.getTypes().ConvertTypeForMem(destType); llvm::APInt Value = cast<llvm::ConstantInt>(Res)->getValue(); Builder.addBits(Value, /*OffsetInBits=*/0, /*AllowOverwrite=*/false); - return Builder.build(DesiredTy, /*AllowOversized*/ false); + return Builder.build(MemTy, /*AllowOversized*/ false); } return Res; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
