https://github.com/Andres-Salamanca updated https://github.com/llvm/llvm-project/pull/154398
>From 9627944cba4f3a2b33c64bcfc9ea654d56d008a3 Mon Sep 17 00:00:00 2001 From: Andres Salamanca <andrealebarbari...@gmail.com> Date: Tue, 19 Aug 2025 12:49:41 -0500 Subject: [PATCH 1/2] [CIR] Fix access to bitfields inside a union --- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 4 ++- clang/test/CIR/CodeGen/bitfield-union.c | 41 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 8bcca6f5d18031..16cf71cf4d56e8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -372,9 +372,11 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base, unsigned index) { mlir::Location loc = getLoc(field->getLocation()); cir::PointerType fieldPtr = cir::PointerType::get(fieldType); + auto rec = cast<cir::RecordType>(base.getAddress().getElementType()); + if (index == 0 && rec.isUnion()) + return base.getAddress(); cir::GetMemberOp sea = getBuilder().createGetMember( loc, fieldPtr, base.getPointer(), field->getName(), index); - auto rec = cast<cir::RecordType>(base.getAddress().getElementType()); CharUnits offset = CharUnits::fromQuantity( rec.getElementOffset(cgm.getDataLayout().layout, index)); return Address(sea, base.getAlignment().alignmentAtOffset(offset)); diff --git a/clang/test/CIR/CodeGen/bitfield-union.c b/clang/test/CIR/CodeGen/bitfield-union.c index b5d14540f488f2..4928be410479ce 100644 --- a/clang/test/CIR/CodeGen/bitfield-union.c +++ b/clang/test/CIR/CodeGen/bitfield-union.c @@ -28,3 +28,44 @@ typedef union { demo d; zero_bit z; + +int main() { + demo d; + d.x = 1; + d.y = 2; + d.z = 0; +} + +// CIR: #bfi_y = #cir.bitfield_info<name = "y", storage_type = !u8i, size = 4, offset = 0, is_signed = true> +// CIR: #bfi_z = #cir.bitfield_info<name = "z", storage_type = !u8i, size = 8, offset = 0, is_signed = true> + +// CIR: cir.func no_proto dso_local @main +// CIR: [[ALLOC:%.*]] = cir.alloca !rec_demo, !cir.ptr<!rec_demo>, ["d"] {alignment = 4 : i64} +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i +// CIR: [[X:%.*]] = cir.get_member [[ALLOC]][0] {name = "x"} : !cir.ptr<!rec_demo> -> !cir.ptr<!s32i> +// CIR: cir.store align(4) [[ONE]], [[X]] : !s32i, !cir.ptr<!s32i> +// CIR: [[TWO:%.*]] = cir.const #cir.int<2> : !s32i +// CIR: [[BITCAST:%.*]] = cir.cast(bitcast, [[ALLOC]] : !cir.ptr<!rec_demo>), !cir.ptr<!u8i> +// CIR: [[SET:%.*]] = cir.set_bitfield align(4) (#bfi_y, [[BITCAST]] : !cir.ptr<!u8i>, [[TWO]] : !s32i) -> !s32i +// CIR: [[ZERO:%.*]] = cir.const #cir.int<0> : !s32i +// CIR: [[BITCAST2:%.*]] = cir.cast(bitcast, [[ALLOC]] : !cir.ptr<!rec_demo>), !cir.ptr<!u8i> +// CIR: [[SET2:%.*]] = cir.set_bitfield align(4) (#bfi_z, [[BITCAST2]] : !cir.ptr<!u8i>, [[ZERO]] : !s32i) -> !s32i +// CIR: cir.return + +// LLVM: define dso_local i32 @main +// LLVM: [[ALLOC:%.*]] = alloca %union.demo, i64 1, align 4 +// LLVM: store i32 1, ptr [[ALLOC]], align 4 +// LLVM: [[BFLOAD:%.*]] = load i8, ptr [[ALLOC]], align 4 +// LLVM: [[CLEAR:%.*]] = and i8 [[BFLOAD]], -16 +// LLVM: [[SET:%.*]] = or i8 [[CLEAR]], 2 +// LLVM: store i8 [[SET]], ptr [[ALLOC]], align 4 +// LLVM: store i8 0, ptr [[ALLOC]], align 4 + +// OGCG: define dso_local i32 @main +// OGCG: [[ALLOC:%.*]] = alloca %union.demo, align 4 +// OGCG: store i32 1, ptr [[ALLOC]], align 4 +// OGCG: [[BFLOAD:%.*]] = load i8, ptr [[ALLOC]], align 4 +// OGCG: [[CLEAR:%.*]] = and i8 [[BFLOAD]], -16 +// OGCG: [[SET:%.*]] = or i8 [[CLEAR]], 2 +// OGCG: store i8 [[SET]], ptr [[ALLOC]], align 4 +// OGCG: store i8 0, ptr [[ALLOC]], align 4 >From 4ce62aa9720e0cb6ce112117d25185e9e5f6568f Mon Sep 17 00:00:00 2001 From: Andres Salamanca <andrealebarbari...@gmail.com> Date: Tue, 19 Aug 2025 15:00:31 -0500 Subject: [PATCH 2/2] Change test return and update getMember to use field index --- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 5 ++--- clang/test/CIR/CodeGen/bitfield-union.c | 14 +++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 16cf71cf4d56e8..81f0ee173395e1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -373,10 +373,9 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base, mlir::Location loc = getLoc(field->getLocation()); cir::PointerType fieldPtr = cir::PointerType::get(fieldType); auto rec = cast<cir::RecordType>(base.getAddress().getElementType()); - if (index == 0 && rec.isUnion()) - return base.getAddress(); cir::GetMemberOp sea = getBuilder().createGetMember( - loc, fieldPtr, base.getPointer(), field->getName(), index); + loc, fieldPtr, base.getPointer(), field->getName(), + rec.isUnion() ? field->getFieldIndex() : index); CharUnits offset = CharUnits::fromQuantity( rec.getElementOffset(cgm.getDataLayout().layout, index)); return Address(sea, base.getAlignment().alignmentAtOffset(offset)); diff --git a/clang/test/CIR/CodeGen/bitfield-union.c b/clang/test/CIR/CodeGen/bitfield-union.c index 4928be410479ce..8ddf627586a7b6 100644 --- a/clang/test/CIR/CodeGen/bitfield-union.c +++ b/clang/test/CIR/CodeGen/bitfield-union.c @@ -29,7 +29,7 @@ typedef union { demo d; zero_bit z; -int main() { +void main() { demo d; d.x = 1; d.y = 2; @@ -45,14 +45,14 @@ int main() { // CIR: [[X:%.*]] = cir.get_member [[ALLOC]][0] {name = "x"} : !cir.ptr<!rec_demo> -> !cir.ptr<!s32i> // CIR: cir.store align(4) [[ONE]], [[X]] : !s32i, !cir.ptr<!s32i> // CIR: [[TWO:%.*]] = cir.const #cir.int<2> : !s32i -// CIR: [[BITCAST:%.*]] = cir.cast(bitcast, [[ALLOC]] : !cir.ptr<!rec_demo>), !cir.ptr<!u8i> -// CIR: [[SET:%.*]] = cir.set_bitfield align(4) (#bfi_y, [[BITCAST]] : !cir.ptr<!u8i>, [[TWO]] : !s32i) -> !s32i +// CIR: [[Y:%.*]] = cir.get_member [[ALLOC]][1] {name = "y"} : !cir.ptr<!rec_demo> -> !cir.ptr<!u8i> +// CIR: [[SET:%.*]] = cir.set_bitfield align(4) (#bfi_y, [[Y]] : !cir.ptr<!u8i>, [[TWO]] : !s32i) -> !s32i // CIR: [[ZERO:%.*]] = cir.const #cir.int<0> : !s32i -// CIR: [[BITCAST2:%.*]] = cir.cast(bitcast, [[ALLOC]] : !cir.ptr<!rec_demo>), !cir.ptr<!u8i> -// CIR: [[SET2:%.*]] = cir.set_bitfield align(4) (#bfi_z, [[BITCAST2]] : !cir.ptr<!u8i>, [[ZERO]] : !s32i) -> !s32i +// CIR: [[Z:%.*]] = cir.get_member [[ALLOC]][2] {name = "z"} : !cir.ptr<!rec_demo> -> !cir.ptr<!u8i> +// CIR: [[SET2:%.*]] = cir.set_bitfield align(4) (#bfi_z, [[Z]] : !cir.ptr<!u8i>, [[ZERO]] : !s32i) -> !s32i // CIR: cir.return -// LLVM: define dso_local i32 @main +// LLVM: define dso_local void @main // LLVM: [[ALLOC:%.*]] = alloca %union.demo, i64 1, align 4 // LLVM: store i32 1, ptr [[ALLOC]], align 4 // LLVM: [[BFLOAD:%.*]] = load i8, ptr [[ALLOC]], align 4 @@ -61,7 +61,7 @@ int main() { // LLVM: store i8 [[SET]], ptr [[ALLOC]], align 4 // LLVM: store i8 0, ptr [[ALLOC]], align 4 -// OGCG: define dso_local i32 @main +// OGCG: define dso_local void @main // OGCG: [[ALLOC:%.*]] = alloca %union.demo, align 4 // OGCG: store i32 1, ptr [[ALLOC]], align 4 // OGCG: [[BFLOAD:%.*]] = load i8, ptr [[ALLOC]], align 4 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits