Skip to content

Commit 88a7849

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 98841b3 commit 88a7849

Some content is hidden

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

43 files changed

+788
-546
lines changed

bindgen-integration/src/lib.rs

+3
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

+4-5
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

+5-44
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@
2222
//! ```
2323
2424
use super::bitfield_unit::__BindgenBitfieldUnit;
25-
use std::mem;
2625

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

3230
let mut bits = vec![];
3331
for i in 0..16 {
@@ -50,7 +48,7 @@ fn bitfield_unit_get_bit() {
5048
#[test]
5149
fn bitfield_unit_set_bit() {
5250
let mut unit =
53-
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b00000000, 0b00000000]);
51+
__BindgenBitfieldUnit::<[u8; 2]>::new([0b00000000, 0b00000000]);
5452

5553
for i in 0..16 {
5654
if i % 3 == 0 {
@@ -63,7 +61,7 @@ fn bitfield_unit_set_bit() {
6361
}
6462

6563
let mut unit =
66-
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b11111111, 0b11111111]);
64+
__BindgenBitfieldUnit::<[u8; 2]>::new([0b11111111, 0b11111111]);
6765

6866
for i in 0..16 {
6967
if i % 3 == 0 {
@@ -76,43 +74,6 @@ fn bitfield_unit_set_bit() {
7674
}
7775
}
7876

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-
11677
macro_rules! bitfield_unit_get {
11778
(
11879
$(
@@ -123,7 +84,7 @@ macro_rules! bitfield_unit_get {
12384
fn bitfield_unit_get() {
12485
$({
12586
let expected = $expected;
126-
let unit = __BindgenBitfieldUnit::<_, u64>::new($storage);
87+
let unit = __BindgenBitfieldUnit::<_>::new($storage);
12788
let actual = unit.get($start, $len);
12889

12990
println!();
@@ -223,7 +184,7 @@ macro_rules! bitfield_unit_set {
223184
#[test]
224185
fn bitfield_unit_set() {
225186
$(
226-
let mut unit = __BindgenBitfieldUnit::<[u8; 4], u64>::new([0, 0, 0, 0]);
187+
let mut unit = __BindgenBitfieldUnit::<[u8; 4]>::new([0, 0, 0, 0]);
227188
unit.set($start, $len, $val);
228189
let actual = unit.get(0, 32);
229190

src/codegen/helpers.rs

+1-8
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

+15
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

+1-1
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

+9-11
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

+14-19
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

+9-11
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)