Skip to content

Commit f1f1bca

Browse files
committed
comp: Fix bitfields to allow underaligned fields after them to take padding space.
Fixes #1947. There are two separate issues here: First, the change in comp.rs ensures that we don't round up the amount of storage to the alignment of the bitfield. That generates the "expected" output in #1947 (`__BindgenBitfieldUnit<[u8; 3], u16>`). But that's still not enough to fix that test-case because __BindgenBitfieldUnit would be aligned and have padding, and Rust won't put the extra field in the padding. In order to ensure the bitfield starts at the right alignment, but that Rust can put stuff in the extra field, we need to make a breaking change and split the generated fields in two: One preceding that guarantees alignment, and the actual storage, bit-aligned. This keeps the existing behavior while fixing that test-case.
1 parent 4ce4b93 commit f1f1bca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+770
-523
lines changed

bindgen-integration/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,19 @@ fn test_bitfields_seventh() {
175175
fn test_bitfield_constructors() {
176176
use std::mem;
177177
let mut first = bindings::bitfields::First {
178+
_bitfield_align_1: [],
178179
_bitfield_1: bindings::bitfields::First::new_bitfield_1(1, 2, 3),
179180
};
180181
assert!(unsafe { first.assert(1, 2, 3) });
181182

182183
let mut second = bindings::bitfields::Second {
184+
_bitfield_align_1: [],
183185
_bitfield_1: bindings::bitfields::Second::new_bitfield_1(1337, true),
184186
};
185187
assert!(unsafe { second.assert(1337, true) });
186188

187189
let mut third = bindings::bitfields::Third {
190+
_bitfield_align_1: [],
188191
_bitfield_1: bindings::bitfields::Third::new_bitfield_1(
189192
42,
190193
false,

src/codegen/bitfield_unit.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
#[repr(C)]
22
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
3-
pub struct __BindgenBitfieldUnit<Storage, Align> {
3+
pub struct __BindgenBitfieldUnit<Storage> {
44
storage: Storage,
5-
align: [Align; 0],
65
}
76

8-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
7+
impl<Storage> __BindgenBitfieldUnit<Storage> {
98
#[inline]
109
pub const fn new(storage: Storage) -> Self {
11-
Self { storage, align: [] }
10+
Self { storage }
1211
}
1312
}
1413

15-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
14+
impl<Storage> __BindgenBitfieldUnit<Storage>
1615
where
1716
Storage: AsRef<[u8]> + AsMut<[u8]>,
1817
{

src/codegen/bitfield_unit_tests.rs

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,11 @@
2222
//! ```
2323
2424
use super::bitfield_unit::__BindgenBitfieldUnit;
25-
use std::mem;
2625

2726
#[test]
2827
fn bitfield_unit_get_bit() {
2928
let unit =
30-
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b10011101, 0b00011101]);
29+
__BindgenBitfieldUnit::<[u8; 2]>::new([0b10011101, 0b00011101]);
3130

3231
let mut bits = vec![];
3332
for i in 0..16 {
@@ -50,7 +49,7 @@ fn bitfield_unit_get_bit() {
5049
#[test]
5150
fn bitfield_unit_set_bit() {
5251
let mut unit =
53-
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b00000000, 0b00000000]);
52+
__BindgenBitfieldUnit::<[u8; 2]>::new([0b00000000, 0b00000000]);
5453

5554
for i in 0..16 {
5655
if i % 3 == 0 {
@@ -63,7 +62,7 @@ fn bitfield_unit_set_bit() {
6362
}
6463

6564
let mut unit =
66-
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b11111111, 0b11111111]);
65+
__BindgenBitfieldUnit::<[u8; 2]>::new([0b11111111, 0b11111111]);
6766

6867
for i in 0..16 {
6968
if i % 3 == 0 {
@@ -76,43 +75,6 @@ fn bitfield_unit_set_bit() {
7675
}
7776
}
7877

79-
#[test]
80-
fn bitfield_unit_align() {
81-
assert_eq!(
82-
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u8>>(),
83-
mem::align_of::<u8>()
84-
);
85-
assert_eq!(
86-
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u16>>(),
87-
mem::align_of::<u16>()
88-
);
89-
assert_eq!(
90-
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u32>>(),
91-
mem::align_of::<u32>()
92-
);
93-
assert_eq!(
94-
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u64>>(),
95-
mem::align_of::<u64>()
96-
);
97-
98-
assert_eq!(
99-
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u8>>(),
100-
mem::align_of::<u8>()
101-
);
102-
assert_eq!(
103-
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u16>>(),
104-
mem::align_of::<u16>()
105-
);
106-
assert_eq!(
107-
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u32>>(),
108-
mem::align_of::<u32>()
109-
);
110-
assert_eq!(
111-
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u64>>(),
112-
mem::align_of::<u64>()
113-
);
114-
}
115-
11678
macro_rules! bitfield_unit_get {
11779
(
11880
$(
@@ -123,7 +85,7 @@ macro_rules! bitfield_unit_get {
12385
fn bitfield_unit_get() {
12486
$({
12587
let expected = $expected;
126-
let unit = __BindgenBitfieldUnit::<_, u64>::new($storage);
88+
let unit = __BindgenBitfieldUnit::<_>::new($storage);
12789
let actual = unit.get($start, $len);
12890

12991
println!();
@@ -223,7 +185,7 @@ macro_rules! bitfield_unit_set {
223185
#[test]
224186
fn bitfield_unit_set() {
225187
$(
226-
let mut unit = __BindgenBitfieldUnit::<[u8; 4], u64>::new([0, 0, 0, 0]);
188+
let mut unit = __BindgenBitfieldUnit::<[u8; 4]>::new([0, 0, 0, 0]);
227189
unit.set($start, $len, $val);
228190
let actual = unit.get(0, 32);
229191

src/codegen/helpers.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,9 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> TokenStream {
120120
tokens.append_all(quote! { root:: });
121121
}
122122

123-
let align = match layout.align {
124-
n if n >= 8 => quote! { u64 },
125-
4 => quote! { u32 },
126-
2 => quote! { u16 },
127-
_ => quote! { u8 },
128-
};
129-
130123
let size = layout.size;
131124
tokens.append_all(quote! {
132-
__BindgenBitfieldUnit<[u8; #size], #align>
125+
__BindgenBitfieldUnit<[u8; #size]>
133126
});
134127

135128
tokens

src/codegen/mod.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,21 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
14371437
}
14381438
};
14391439

1440+
{
1441+
let align_field_name = format!("_bitfield_align_{}", self.nth());
1442+
let align_field_ident = ctx.rust_ident(&align_field_name);
1443+
let align_ty = match self.layout().align {
1444+
n if n >= 8 => quote! { u64 },
1445+
4 => quote! { u32 },
1446+
2 => quote! { u16 },
1447+
_ => quote! { u8 },
1448+
};
1449+
let align_field = quote! {
1450+
pub #align_field_ident: [#align_ty; 0],
1451+
};
1452+
fields.extend(Some(align_field));
1453+
}
1454+
14401455
let unit_field_name = format!("_bitfield_{}", self.nth());
14411456
let unit_field_ident = ctx.rust_ident(&unit_field_name);
14421457

src/ir/comp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ where
575575
} else {
576576
bytes_from_bits_pow2(unit_align_in_bits)
577577
};
578-
let size = align_to(unit_size_in_bits, align * 8) / 8;
578+
let size = align_to(unit_size_in_bits, 8) / 8;
579579
let layout = Layout::new(size, align);
580580
fields.extend(Some(Field::Bitfields(BitfieldUnit {
581581
nth: *bitfield_unit_count,

tests/expectations/tests/bitfield-32bit-overflow.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77

88
#[repr(C)]
99
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
10-
pub struct __BindgenBitfieldUnit<Storage, Align> {
10+
pub struct __BindgenBitfieldUnit<Storage> {
1111
storage: Storage,
12-
align: [Align; 0],
1312
}
14-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
13+
impl<Storage> __BindgenBitfieldUnit<Storage> {
1514
#[inline]
1615
pub const fn new(storage: Storage) -> Self {
17-
Self { storage, align: [] }
16+
Self { storage }
1817
}
1918
}
20-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
19+
impl<Storage> __BindgenBitfieldUnit<Storage>
2120
where
2221
Storage: AsRef<[u8]> + AsMut<[u8]>,
2322
{
@@ -95,7 +94,8 @@ where
9594
#[repr(C, packed)]
9695
#[derive(Debug, Default, Copy, Clone)]
9796
pub struct MuchBitfield {
98-
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize], u8>,
97+
pub _bitfield_align_1: [u8; 0],
98+
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize]>,
9999
}
100100
#[test]
101101
fn bindgen_test_layout_MuchBitfield() {
@@ -575,11 +575,9 @@ impl MuchBitfield {
575575
m30: ::std::os::raw::c_char,
576576
m31: ::std::os::raw::c_char,
577577
m32: ::std::os::raw::c_char,
578-
) -> __BindgenBitfieldUnit<[u8; 5usize], u8> {
579-
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
580-
[u8; 5usize],
581-
u8,
582-
> = Default::default();
578+
) -> __BindgenBitfieldUnit<[u8; 5usize]> {
579+
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 5usize]> =
580+
Default::default();
583581
__bindgen_bitfield_unit.set(0usize, 1u8, {
584582
let m0: u8 = unsafe { ::std::mem::transmute(m0) };
585583
m0 as u64

tests/expectations/tests/bitfield-large.rs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77

88
#[repr(C)]
99
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
10-
pub struct __BindgenBitfieldUnit<Storage, Align> {
10+
pub struct __BindgenBitfieldUnit<Storage> {
1111
storage: Storage,
12-
align: [Align; 0],
1312
}
14-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
13+
impl<Storage> __BindgenBitfieldUnit<Storage> {
1514
#[inline]
1615
pub const fn new(storage: Storage) -> Self {
17-
Self { storage, align: [] }
16+
Self { storage }
1817
}
1918
}
20-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
19+
impl<Storage> __BindgenBitfieldUnit<Storage>
2120
where
2221
Storage: AsRef<[u8]> + AsMut<[u8]>,
2322
{
@@ -96,7 +95,8 @@ where
9695
#[repr(align(16))]
9796
#[derive(Debug, Default, Copy, Clone)]
9897
pub struct HasBigBitfield {
99-
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u64>,
98+
pub _bitfield_align_1: [u64; 0],
99+
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
100100
}
101101
#[test]
102102
fn bindgen_test_layout_HasBigBitfield() {
@@ -126,13 +126,9 @@ impl HasBigBitfield {
126126
}
127127
}
128128
#[inline]
129-
pub fn new_bitfield_1(
130-
x: i128,
131-
) -> __BindgenBitfieldUnit<[u8; 16usize], u64> {
132-
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
133-
[u8; 16usize],
134-
u64,
135-
> = Default::default();
129+
pub fn new_bitfield_1(x: i128) -> __BindgenBitfieldUnit<[u8; 16usize]> {
130+
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> =
131+
Default::default();
136132
__bindgen_bitfield_unit.set(0usize, 128u8, {
137133
let x: u128 = unsafe { ::std::mem::transmute(x) };
138134
x as u64
@@ -144,7 +140,8 @@ impl HasBigBitfield {
144140
#[repr(align(16))]
145141
#[derive(Debug, Default, Copy, Clone)]
146142
pub struct HasTwoBigBitfields {
147-
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u64>,
143+
pub _bitfield_align_1: [u64; 0],
144+
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
148145
}
149146
#[test]
150147
fn bindgen_test_layout_HasTwoBigBitfields() {
@@ -190,11 +187,9 @@ impl HasTwoBigBitfields {
190187
pub fn new_bitfield_1(
191188
x: i128,
192189
y: i128,
193-
) -> __BindgenBitfieldUnit<[u8; 16usize], u64> {
194-
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
195-
[u8; 16usize],
196-
u64,
197-
> = Default::default();
190+
) -> __BindgenBitfieldUnit<[u8; 16usize]> {
191+
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> =
192+
Default::default();
198193
__bindgen_bitfield_unit.set(0usize, 80u8, {
199194
let x: u128 = unsafe { ::std::mem::transmute(x) };
200195
x as u64

tests/expectations/tests/bitfield-linux-32.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77

88
#[repr(C)]
99
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
10-
pub struct __BindgenBitfieldUnit<Storage, Align> {
10+
pub struct __BindgenBitfieldUnit<Storage> {
1111
storage: Storage,
12-
align: [Align; 0],
1312
}
14-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
13+
impl<Storage> __BindgenBitfieldUnit<Storage> {
1514
#[inline]
1615
pub const fn new(storage: Storage) -> Self {
17-
Self { storage, align: [] }
16+
Self { storage }
1817
}
1918
}
20-
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
19+
impl<Storage> __BindgenBitfieldUnit<Storage>
2120
where
2221
Storage: AsRef<[u8]> + AsMut<[u8]>,
2322
{
@@ -96,7 +95,8 @@ where
9695
#[derive(Debug, Default, Copy, Clone)]
9796
pub struct Test {
9897
pub foo: u64,
99-
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u64>,
98+
pub _bitfield_align_1: [u64; 0],
99+
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
100100
}
101101
#[test]
102102
fn bindgen_test_layout_Test() {
@@ -147,11 +147,9 @@ impl Test {
147147
pub fn new_bitfield_1(
148148
x: u64,
149149
y: u64,
150-
) -> __BindgenBitfieldUnit<[u8; 8usize], u64> {
151-
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
152-
[u8; 8usize],
153-
u64,
154-
> = Default::default();
150+
) -> __BindgenBitfieldUnit<[u8; 8usize]> {
151+
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> =
152+
Default::default();
155153
__bindgen_bitfield_unit.set(0usize, 56u8, {
156154
let x: u64 = unsafe { ::std::mem::transmute(x) };
157155
x as u64

0 commit comments

Comments
 (0)