diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-10-31 15:34:56 -0700 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-10-31 15:34:56 -0700 |
commit | e17bd8df3fbd686fa0857b2e09d6e38c9fb6262c (patch) | |
tree | e5c385a8060cddda62009b9d4f979757c93bf1fb | |
parent | 7bc4f34ab6a1361ac7232a99da794873a3feaffc (diff) |
Unnamed bit-fields should not affect alignment
According to the x86[-64] ABI spec: "Unnamed bit-fields’ types do not affect the
alignment of a structure or union". This makes sense: such bit-fields are only
used for padding, and we can't perform an un-aligned read of something we can't
read because we can't even name it.
Fixes #1076
-rw-r--r-- | src/ir/comp.rs | 22 | ||||
-rw-r--r-- | tests/expectations/tests/issue-1034.rs | 7 | ||||
-rw-r--r-- | tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs | 31 | ||||
-rw-r--r-- | tests/headers/issue-1076-unnamed-bitfield-alignment.h | 4 |
4 files changed, 54 insertions, 10 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index f3c986e7..7265660c 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -608,6 +608,21 @@ fn bitfields_to_allocation_units<E, I>( } } + // According to the x86[-64] ABI spec: "Unnamed bit-fields’ types do not + // affect the alignment of a structure or union". This makes sense: such + // bit-fields are only used for padding, and we can't perform an + // un-aligned read of something we can't read because we can't even name + // it. + if bitfield.name().is_some() { + max_align = cmp::max(max_align, bitfield_align); + + // NB: The `bitfield_width` here is completely, absolutely + // intentional. Alignment of the allocation unit is based on the + // maximum bitfield width, not (directly) on the bitfields' types' + // alignment. + unit_align = cmp::max(unit_align, bitfield_width); + } + // Always keep all bitfields around. While unnamed bitifields are used // for padding (and usually not needed hereafter), large unnamed // bitfields over their types size cause weird allocation size behavior from clang. @@ -615,13 +630,6 @@ fn bitfields_to_allocation_units<E, I>( // and make the struct opaque in this case bitfields_in_unit.push(Bitfield::new(offset, bitfield)); - max_align = cmp::max(max_align, bitfield_align); - - // NB: The `bitfield_width` here is completely, absolutely intentional. - // Alignment of the allocation unit is based on the maximum bitfield - // width, not (directly) on the bitfields' types' alignment. - unit_align = cmp::max(unit_align, bitfield_width); - unit_size_in_bits = offset + bitfield_width; // Compute what the physical unit's final size would be given what we diff --git a/tests/expectations/tests/issue-1034.rs b/tests/expectations/tests/issue-1034.rs index b0c4b529..b5c7d6bb 100644 --- a/tests/expectations/tests/issue-1034.rs +++ b/tests/expectations/tests/issue-1034.rs @@ -4,10 +4,11 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#[repr(C, packed)] +#[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct S2 { - pub _bitfield_1: u16, + pub _bitfield_1: u8, + pub __bindgen_padding_0: u8, } #[test] fn bindgen_test_layout_S2() { @@ -24,7 +25,7 @@ fn bindgen_test_layout_S2() { } impl S2 { #[inline] - pub fn new_bitfield_1() -> u16 { + pub fn new_bitfield_1() -> u8 { 0 } } diff --git a/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs b/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs new file mode 100644 index 00000000..00b3f11b --- /dev/null +++ b/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs @@ -0,0 +1,31 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct S1 { + pub _bitfield_1: [u8; 2usize], + pub __bindgen_padding_0: u8, +} +#[test] +fn bindgen_test_layout_S1() { + assert_eq!( + ::std::mem::size_of::<S1>(), + 3usize, + concat!("Size of: ", stringify!(S1)) + ); + assert_eq!( + ::std::mem::align_of::<S1>(), + 1usize, + concat!("Alignment of ", stringify!(S1)) + ); +} +impl S1 { + #[inline] + pub fn new_bitfield_1() -> u16 { + 0 + } +} diff --git a/tests/headers/issue-1076-unnamed-bitfield-alignment.h b/tests/headers/issue-1076-unnamed-bitfield-alignment.h new file mode 100644 index 00000000..876ec174 --- /dev/null +++ b/tests/headers/issue-1076-unnamed-bitfield-alignment.h @@ -0,0 +1,4 @@ +struct S1 { + signed : 15; + unsigned : 6 +}; |