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

Reply via email to