diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 8bcca6f5d1803..81f0ee173395e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -372,9 +372,10 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base, unsigned index) { mlir::Location loc = getLoc(field->getLocation()); cir::PointerType fieldPtr = cir::PointerType::get(fieldType); - cir::GetMemberOp sea = getBuilder().createGetMember( - loc, fieldPtr, base.getPointer(), field->getName(), index); auto rec = cast(base.getAddress().getElementType()); + cir::GetMemberOp sea = getBuilder().createGetMember( + 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 b5d14540f488f..14a2aaf68d318 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; + +void f() { + demo d; + d.x = 1; + d.y = 2; + d.z = 0; +} + +// CIR: #bfi_y = #cir.bitfield_info +// CIR: #bfi_z = #cir.bitfield_info + +// CIR: cir.func no_proto dso_local @f +// CIR: [[ALLOC:%.*]] = cir.alloca !rec_demo, !cir.ptr, ["d"] {alignment = 4 : i64} +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i +// CIR: [[X:%.*]] = cir.get_member [[ALLOC]][0] {name = "x"} : !cir.ptr -> !cir.ptr +// CIR: cir.store align(4) [[ONE]], [[X]] : !s32i, !cir.ptr +// CIR: [[TWO:%.*]] = cir.const #cir.int<2> : !s32i +// CIR: [[Y:%.*]] = cir.get_member [[ALLOC]][1] {name = "y"} : !cir.ptr -> !cir.ptr +// CIR: [[SET:%.*]] = cir.set_bitfield align(4) (#bfi_y, [[Y]] : !cir.ptr, [[TWO]] : !s32i) -> !s32i +// CIR: [[ZERO:%.*]] = cir.const #cir.int<0> : !s32i +// CIR: [[Z:%.*]] = cir.get_member [[ALLOC]][2] {name = "z"} : !cir.ptr -> !cir.ptr +// CIR: [[SET2:%.*]] = cir.set_bitfield align(4) (#bfi_z, [[Z]] : !cir.ptr, [[ZERO]] : !s32i) -> !s32i +// CIR: cir.return + +// LLVM: define dso_local void @f +// 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 void @f +// 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