[clang] [CIR] Record how far a bit-field's declared types reach on x86_64 (PR #220069)
Adam Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 2 05:49:42 PDT 2026
adams381 wrote:
I've been struggling with this representation. The field description is the right place to look, and `#cir.bitfield_info` is the natural home for all of it. However, that cannot be reached from here. It is an operand of `cir.get_bitfield` and `cir.set_bitfield`, so it exists only where a field is accessed. CallConvLowering classifies a signature and sees the record type alone, and the type carries no equivalent: a member is marked `bitfield` and has a storage type, but no name, width, offset or signedness. `bitfield_info` itself already carries `storage_type`, `size` and `offset`, so the declared type really is the only piece missing from it.
The equivalent that is reachable is to put it on the member description in the record type. `StructType` and `UnionType` already carry a `member_kinds` array parallel to the member types. We could add a third array that carries the extent per member, printed on the kind:
```mlir
!rec_S = !cir.struct<"S" {bitfield<11> !u64i, bitfield<4> !u16i, data !u32i}>
```
against today's
```mlir
!rec_S = !cir.struct<"S" {bitfield !u64i, bitfield !cir.array<!cir.array<!u8i x 3> x 0>, bitfield !u16i, bitfield !cir.array<!cir.array<!u8i x 2> x 0>, data !u32i}>
```
`bitfield<11> !u64i` reads as an 8-byte access unit whose bit-fields were declared with types extending to 11 bytes. Absent means nothing outruns the unit, so records without such a unit print exactly as they do now.
This fixes the problem that a zero-length member is still a member, so it reaches the LLVM struct type and shifts member indices:
```mlir
%struct.S = type { i64, [0 x i8], i16, [0 x i8], i32 } // -fclangir
%struct.S = type { i64, i16, i32 } // classic
```
That divergence is why this patch has to split CHECK prefixes in `bitfields.cpp` and move `cir.get_member` indices in `paren-list-agg-init.cpp`. An extent on the member description adds no member, so the lowered struct matches classic again and most of the test churn here disappears.
I can implement the extent parameter as a prereq for this PR and then rebase when that lands.
https://github.com/llvm/llvm-project/pull/220069
More information about the cfe-commits
mailing list