[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-03 Thread Adam Smith via cfe-commits


@@ -79,6 +79,35 @@ struct CIRRecordLowering final {
 cir::ArrayType::get(cirGenTypes.convertTypeForMem(field->getType()), 
0),
 cir::RecordMemberKind::BitField);
   }
+
+  /// An access unit can be narrower than the types its bit-fields were
+  /// declared with.  In `struct { int a : 4; int b : 11; int c : 17; }` all
+  /// three share one 4-byte unit, but `c` is declared `int`, so the declared
+  /// data runs 15 bits past the unit:
+  ///
+  ///   |-a-|b-|---c|
+  ///   |- 4-byte unit -|--- extent ---|
+  ///  |-- c declared as int --|
+  ///   0   4  15   32 47  bits

adams381 wrote:

That example explains the concept but not the motivation.  Consider this example

```c
typedef struct { long long x : 32; }  Wide;
typedef struct { int x : 32; } __attribute__((aligned(8))) Narrow;
```

`Wide` needs: `i64`

`Narrow` needs: `i32`

Currently we generate

```mlir
!rec_Narrow = !cir.struct<"Narrow" {bitfield !u32i, pad !cir.array}>
!rec_Wide   = !cir.struct<"Wide"   {bitfield !u32i, bitfield 
!cir.array x 0>, pad !cir.array}>
```

Without the extent member, the two types are identical.

https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Andy Kaylor via cfe-commits

https://github.com/andykaylor edited 
https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Andy Kaylor via cfe-commits


@@ -79,6 +79,35 @@ struct CIRRecordLowering final {
 cir::ArrayType::get(cirGenTypes.convertTypeForMem(field->getType()), 
0),
 cir::RecordMemberKind::BitField);
   }
+
+  /// An access unit can be narrower than the types its bit-fields were
+  /// declared with.  In `struct { int a : 4; int b : 11; int c : 17; }` all
+  /// three share one 4-byte unit, but `c` is declared `int`, so the declared
+  /// data runs 15 bits past the unit:
+  ///
+  ///   |-a-|b-|---c|
+  ///   |- 4-byte unit -|--- extent ---|
+  ///  |-- c declared as int --|
+  ///   0   4  15   32 47  bits

andykaylor wrote:

I don't understand this example. Since a, b, and c, all fit within a single 
32-bit integer, there is no need for c to extend beyond the 32 bits. Why are we 
recording anything here?

https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Andy Kaylor via cfe-commits

https://github.com/andykaylor commented:

I really hate the fact that we're inserting something in the IR that survives 
lowering to LLVM IR just as a hint to the calling convention lowering pass.

I'm going to experiment with introducing a new type to describe a bitfield. So

`struct S { unsigned a : 2; unsigned b : 5; unsigned c : 1; };`

would be represented in CIR like:

`!rec_S { data !cir.bitfield, data !cir.bitfield, data 
!cir.bitfield };`

I think this would solve both the extent problem and the zero-length bitfield 
problem. It could also allow us to get rid of `#cir.bitfield_info`.

https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Erich Keane via cfe-commits


@@ -79,6 +79,25 @@ struct CIRRecordLowering final {
 cir::ArrayType::get(cirGenTypes.convertTypeForMem(field->getType()), 
0),
 cir::RecordMemberKind::BitField);
   }
+
+  /// An access unit can be narrower than the types its bit-fields were
+  /// declared with, so the unit's extent does not say how far the declared
+  /// data runs.  This member carries the difference: the declared extent ends
+  /// \p excessInBits past \p offset.  It holds no storage, taking the same
+  /// zero-length-array shape as a zero-width bit-field so the record layout
+  /// walks skip it.

erichkeane wrote:

Can we get a quick example here?  I'm still not getting th is.

https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Erich Keane via cfe-commits


@@ -572,21 +572,27 @@ void UnionType::complete(ArrayRef members, bool 
packed,
 
 mlir::Type
 UnionType::getUnionStorageType(const mlir::DataLayout &dataLayout) const {
-  return getUnionStorageType(dataLayout, getMembers());
+  return getUnionStorageType(dataLayout, getMembers(), getMemberKinds());
 }
 
-mlir::Type UnionType::getUnionStorageType(const mlir::DataLayout &dataLayout,
-  llvm::ArrayRef members) {
-  if (members.empty())
-return {};
-  return *std::max_element(
-  members.begin(), members.end(), [&](mlir::Type lhs, mlir::Type rhs) {
-return dataLayout.getTypeABIAlignment(lhs) <
-   dataLayout.getTypeABIAlignment(rhs) ||
-   (dataLayout.getTypeABIAlignment(lhs) ==
-dataLayout.getTypeABIAlignment(rhs) &&
-dataLayout.getTypeSize(lhs) < dataLayout.getTypeSize(rhs));
-  });
+mlir::Type
+UnionType::getUnionStorageType(const mlir::DataLayout &dataLayout,
+   llvm::ArrayRef members,
+   llvm::ArrayRef kinds) {
+  // A member occupying no storage cannot be the storage.
+  mlir::Type storage;
+  for (auto [memberTy, kind] : llvm::zip_equal(members, kinds)) {
+if (isZeroWidthBitField(memberTy, kind))

erichkeane wrote:

I'd suggest just doing this with a filter iterator.  This loop is actually 
quite touch to read in a way that max_element did well.  

So just extract the `isZeroWidthBitField` into a filter-range.

https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Adam Smith via cfe-commits

https://github.com/adams381 edited 
https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Record how far a bit-field's declared types extend on x86_64 (PR #220069)

2026-09-02 Thread Adam Smith via cfe-commits

https://github.com/adams381 edited 
https://github.com/llvm/llvm-project/pull/220069
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits