Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

comp: Fix bitfields to allow underaligned fields after them to take padding space. #1950

Merged
merged 1 commit into from Dec 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions bindgen-integration/src/lib.rs
Expand Up @@ -175,16 +175,19 @@ fn test_bitfields_seventh() {
fn test_bitfield_constructors() {
use std::mem;
let mut first = bindings::bitfields::First {
_bitfield_align_1: [],
_bitfield_1: bindings::bitfields::First::new_bitfield_1(1, 2, 3),
};
assert!(unsafe { first.assert(1, 2, 3) });

let mut second = bindings::bitfields::Second {
_bitfield_align_1: [],
_bitfield_1: bindings::bitfields::Second::new_bitfield_1(1337, true),
};
assert!(unsafe { second.assert(1337, true) });

let mut third = bindings::bitfields::Third {
_bitfield_align_1: [],
_bitfield_1: bindings::bitfields::Third::new_bitfield_1(
42,
false,
Expand Down
9 changes: 4 additions & 5 deletions src/codegen/bitfield_unit.rs
@@ -1,18 +1,17 @@
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align> {
pub struct __BindgenBitfieldUnit<Storage> {
storage: Storage,
align: [Align; 0],
}

impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
impl<Storage> __BindgenBitfieldUnit<Storage> {
#[inline]
pub const fn new(storage: Storage) -> Self {
Self { storage, align: [] }
Self { storage }
}
}

impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
impl<Storage> __BindgenBitfieldUnit<Storage>
where
Storage: AsRef<[u8]> + AsMut<[u8]>,
{
Expand Down
49 changes: 5 additions & 44 deletions src/codegen/bitfield_unit_tests.rs
Expand Up @@ -22,12 +22,10 @@
//! ```

use super::bitfield_unit::__BindgenBitfieldUnit;
use std::mem;

#[test]
fn bitfield_unit_get_bit() {
let unit =
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b10011101, 0b00011101]);
let unit = __BindgenBitfieldUnit::<[u8; 2]>::new([0b10011101, 0b00011101]);

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

for i in 0..16 {
if i % 3 == 0 {
Expand All @@ -63,7 +61,7 @@ fn bitfield_unit_set_bit() {
}

let mut unit =
__BindgenBitfieldUnit::<[u8; 2], u64>::new([0b11111111, 0b11111111]);
__BindgenBitfieldUnit::<[u8; 2]>::new([0b11111111, 0b11111111]);

for i in 0..16 {
if i % 3 == 0 {
Expand All @@ -76,43 +74,6 @@ fn bitfield_unit_set_bit() {
}
}

#[test]
fn bitfield_unit_align() {
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u8>>(),
mem::align_of::<u8>()
);
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u16>>(),
mem::align_of::<u16>()
);
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u32>>(),
mem::align_of::<u32>()
);
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 1], u64>>(),
mem::align_of::<u64>()
);

assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u8>>(),
mem::align_of::<u8>()
);
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u16>>(),
mem::align_of::<u16>()
);
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u32>>(),
mem::align_of::<u32>()
);
assert_eq!(
mem::align_of::<__BindgenBitfieldUnit<[u8; 8], u64>>(),
mem::align_of::<u64>()
);
}

macro_rules! bitfield_unit_get {
(
$(
Expand All @@ -123,7 +84,7 @@ macro_rules! bitfield_unit_get {
fn bitfield_unit_get() {
$({
let expected = $expected;
let unit = __BindgenBitfieldUnit::<_, u64>::new($storage);
let unit = __BindgenBitfieldUnit::<_>::new($storage);
let actual = unit.get($start, $len);

println!();
Expand Down Expand Up @@ -223,7 +184,7 @@ macro_rules! bitfield_unit_set {
#[test]
fn bitfield_unit_set() {
$(
let mut unit = __BindgenBitfieldUnit::<[u8; 4], u64>::new([0, 0, 0, 0]);
let mut unit = __BindgenBitfieldUnit::<[u8; 4]>::new([0, 0, 0, 0]);
unit.set($start, $len, $val);
let actual = unit.get(0, 32);

Expand Down
9 changes: 1 addition & 8 deletions src/codegen/helpers.rs
Expand Up @@ -120,16 +120,9 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> TokenStream {
tokens.append_all(quote! { root:: });
}

let align = match layout.align {
n if n >= 8 => quote! { u64 },
4 => quote! { u32 },
2 => quote! { u16 },
_ => quote! { u8 },
};

let size = layout.size;
tokens.append_all(quote! {
__BindgenBitfieldUnit<[u8; #size], #align>
__BindgenBitfieldUnit<[u8; #size]>
});

tokens
Expand Down
15 changes: 15 additions & 0 deletions src/codegen/mod.rs
Expand Up @@ -1437,6 +1437,21 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
}
};

{
let align_field_name = format!("_bitfield_align_{}", self.nth());
let align_field_ident = ctx.rust_ident(&align_field_name);
let align_ty = match self.layout().align {
n if n >= 8 => quote! { u64 },
4 => quote! { u32 },
2 => quote! { u16 },
_ => quote! { u8 },
};
let align_field = quote! {
pub #align_field_ident: [#align_ty; 0],
};
fields.extend(Some(align_field));
}

let unit_field_name = format!("_bitfield_{}", self.nth());
let unit_field_ident = ctx.rust_ident(&unit_field_name);

Expand Down
2 changes: 1 addition & 1 deletion src/ir/comp.rs
Expand Up @@ -575,7 +575,7 @@ where
} else {
bytes_from_bits_pow2(unit_align_in_bits)
};
let size = align_to(unit_size_in_bits, align * 8) / 8;
let size = align_to(unit_size_in_bits, 8) / 8;
let layout = Layout::new(size, align);
fields.extend(Some(Field::Bitfields(BitfieldUnit {
nth: *bitfield_unit_count,
Expand Down
20 changes: 9 additions & 11 deletions tests/expectations/tests/bitfield-32bit-overflow.rs
Expand Up @@ -7,17 +7,16 @@

#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align> {
pub struct __BindgenBitfieldUnit<Storage> {
storage: Storage,
align: [Align; 0],
}
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
impl<Storage> __BindgenBitfieldUnit<Storage> {
#[inline]
pub const fn new(storage: Storage) -> Self {
Self { storage, align: [] }
Self { storage }
}
}
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
impl<Storage> __BindgenBitfieldUnit<Storage>
where
Storage: AsRef<[u8]> + AsMut<[u8]>,
{
Expand Down Expand Up @@ -95,7 +94,8 @@ where
#[repr(C, packed)]
#[derive(Debug, Default, Copy, Clone)]
pub struct MuchBitfield {
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize], u8>,
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize]>,
}
#[test]
fn bindgen_test_layout_MuchBitfield() {
Expand Down Expand Up @@ -575,11 +575,9 @@ impl MuchBitfield {
m30: ::std::os::raw::c_char,
m31: ::std::os::raw::c_char,
m32: ::std::os::raw::c_char,
) -> __BindgenBitfieldUnit<[u8; 5usize], u8> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
[u8; 5usize],
u8,
> = Default::default();
) -> __BindgenBitfieldUnit<[u8; 5usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 5usize]> =
Default::default();
__bindgen_bitfield_unit.set(0usize, 1u8, {
let m0: u8 = unsafe { ::std::mem::transmute(m0) };
m0 as u64
Expand Down
33 changes: 14 additions & 19 deletions tests/expectations/tests/bitfield-large.rs
Expand Up @@ -7,17 +7,16 @@

#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align> {
pub struct __BindgenBitfieldUnit<Storage> {
storage: Storage,
align: [Align; 0],
}
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
impl<Storage> __BindgenBitfieldUnit<Storage> {
#[inline]
pub const fn new(storage: Storage) -> Self {
Self { storage, align: [] }
Self { storage }
}
}
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
impl<Storage> __BindgenBitfieldUnit<Storage>
where
Storage: AsRef<[u8]> + AsMut<[u8]>,
{
Expand Down Expand Up @@ -96,7 +95,8 @@ where
#[repr(align(16))]
#[derive(Debug, Default, Copy, Clone)]
pub struct HasBigBitfield {
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u64>,
pub _bitfield_align_1: [u64; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
#[test]
fn bindgen_test_layout_HasBigBitfield() {
Expand Down Expand Up @@ -126,13 +126,9 @@ impl HasBigBitfield {
}
}
#[inline]
pub fn new_bitfield_1(
x: i128,
) -> __BindgenBitfieldUnit<[u8; 16usize], u64> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
[u8; 16usize],
u64,
> = Default::default();
pub fn new_bitfield_1(x: i128) -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> =
Default::default();
__bindgen_bitfield_unit.set(0usize, 128u8, {
let x: u128 = unsafe { ::std::mem::transmute(x) };
x as u64
Expand All @@ -144,7 +140,8 @@ impl HasBigBitfield {
#[repr(align(16))]
#[derive(Debug, Default, Copy, Clone)]
pub struct HasTwoBigBitfields {
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u64>,
pub _bitfield_align_1: [u64; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>,
}
#[test]
fn bindgen_test_layout_HasTwoBigBitfields() {
Expand Down Expand Up @@ -190,11 +187,9 @@ impl HasTwoBigBitfields {
pub fn new_bitfield_1(
x: i128,
y: i128,
) -> __BindgenBitfieldUnit<[u8; 16usize], u64> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
[u8; 16usize],
u64,
> = Default::default();
) -> __BindgenBitfieldUnit<[u8; 16usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize]> =
Default::default();
__bindgen_bitfield_unit.set(0usize, 80u8, {
let x: u128 = unsafe { ::std::mem::transmute(x) };
x as u64
Expand Down
20 changes: 9 additions & 11 deletions tests/expectations/tests/bitfield-linux-32.rs
Expand Up @@ -7,17 +7,16 @@

#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage, Align> {
pub struct __BindgenBitfieldUnit<Storage> {
storage: Storage,
align: [Align; 0],
}
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> {
impl<Storage> __BindgenBitfieldUnit<Storage> {
#[inline]
pub const fn new(storage: Storage) -> Self {
Self { storage, align: [] }
Self { storage }
}
}
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
impl<Storage> __BindgenBitfieldUnit<Storage>
where
Storage: AsRef<[u8]> + AsMut<[u8]>,
{
Expand Down Expand Up @@ -96,7 +95,8 @@ where
#[derive(Debug, Default, Copy, Clone)]
pub struct Test {
pub foo: u64,
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u64>,
pub _bitfield_align_1: [u64; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
}
#[test]
fn bindgen_test_layout_Test() {
Expand Down Expand Up @@ -147,11 +147,9 @@ impl Test {
pub fn new_bitfield_1(
x: u64,
y: u64,
) -> __BindgenBitfieldUnit<[u8; 8usize], u64> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<
[u8; 8usize],
u64,
> = Default::default();
) -> __BindgenBitfieldUnit<[u8; 8usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> =
Default::default();
__bindgen_bitfield_unit.set(0usize, 56u8, {
let x: u64 = unsafe { ::std::mem::transmute(x) };
x as u64
Expand Down