diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 64f4926a8b..c5362bf450 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -178,19 +178,18 @@ 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: [], + _bindgen_align: [], _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: [], + _bindgen_align: [], _bitfield_1: bindings::bitfields::Third::new_bitfield_1( 42, false, diff --git a/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs b/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs index 81ce12a5c9..783f0ef7a9 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct MuchBitfield { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 5usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/bitfield-large.rs b/bindgen-tests/tests/expectations/tests/bitfield-large.rs index 8024d88c3b..5d614ab936 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield-large.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield-large.rs @@ -149,7 +149,6 @@ where #[repr(align(16))] #[derive(Debug, Default, Copy, Clone)] pub struct HasBigBitfield { - pub _bitfield_align_1: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -213,7 +212,6 @@ impl HasBigBitfield { #[repr(align(16))] #[derive(Debug, Default, Copy, Clone)] pub struct HasTwoBigBitfields { - pub _bitfield_align_1: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs b/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs index 8b0b37b481..3e676c53b5 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield-linux-32.rs @@ -145,19 +145,12 @@ where } } } -#[repr(C, packed(4))] +#[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Test { pub foo: u64, - pub _bitfield_align_1: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, } -#[allow(clippy::unnecessary_operation, clippy::identity_op)] -const _: () = { - ["Size of Test"][::std::mem::size_of::() - 16usize]; - ["Alignment of Test"][::std::mem::align_of::() - 4usize]; - ["Offset of field: Test::foo"][::std::mem::offset_of!(Test, foo) - 0usize]; -}; impl Test { #[inline] pub fn x(&self) -> u64 { diff --git a/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs b/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs index 84e152f3fd..09ca005589 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Foo { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/bitfield-template.rs b/bindgen-tests/tests/expectations/tests/bitfield-template.rs new file mode 100644 index 0000000000..eb454e0db4 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield-template.rs @@ -0,0 +1,214 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct foo { + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, + pub member: T, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, +} +impl Default for foo { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl foo { + #[inline] + pub fn b(&self) -> bool { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u8) } + } + #[inline] + pub fn set_b(&mut self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 8u8, val as u64) + } + } + #[inline] + pub unsafe fn b_raw(this: *const Self) -> bool { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 8u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_b_raw(this: *mut Self, val: bool) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 8u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1(b: bool) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 8u8, + { + let b: u8 = unsafe { ::std::mem::transmute(b) }; + b as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_align.rs b/bindgen-tests/tests/expectations/tests/bitfield_align.rs index 5f1321bbb1..0c70917fc5 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield_align.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield_align.rs @@ -146,11 +146,10 @@ where } } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct A { + pub _bindgen_align: [u32; 0], pub x: ::std::os::raw::c_uchar, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, pub y: ::std::os::raw::c_uchar, } @@ -632,7 +631,7 @@ impl A { #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct B { - pub _bitfield_align_1: [u32; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -744,7 +743,6 @@ impl B { #[derive(Debug, Default, Copy, Clone)] pub struct C { pub x: ::std::os::raw::c_uchar, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub baz: ::std::os::raw::c_uint, } @@ -856,10 +854,9 @@ impl C { } } #[repr(C)] -#[repr(align(2))] #[derive(Debug, Default, Copy, Clone)] pub struct Date1 { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, pub __bindgen_padding_0: u8, } @@ -1061,10 +1058,9 @@ impl Date1 { } } #[repr(C)] -#[repr(align(2))] #[derive(Debug, Default, Copy, Clone)] pub struct Date2 { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -1311,10 +1307,9 @@ impl Date2 { } } #[repr(C)] -#[repr(align(2))] #[derive(Debug, Default, Copy, Clone)] pub struct Date3 { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, pub byte: ::std::os::raw::c_uchar, } diff --git a/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs b/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs index 2a676d5636..b71bba18ad 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs @@ -157,7 +157,7 @@ pub enum MyEnum { #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct TaggedPtr { - pub _bitfield_align_1: [u64; 0], + pub _bindgen_align: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs b/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs index 51c777497b..ed7d1b3bb7 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield_large_overflow.rs @@ -1,8 +1,8 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] #[repr(C)] -#[repr(align(8))] #[derive(Debug, Default, Copy, Clone)] pub struct _bindgen_ty_1 { + pub _bindgen_align: [u64; 0], pub _bindgen_opaque_blob: [u64; 10usize], } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs b/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs index 1a08cd00f9..35117c74b6 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs @@ -148,7 +148,7 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct mach_msg_type_descriptor_t { - pub _bitfield_align_1: [u32; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/bitfield_pack_offset.rs b/bindgen-tests/tests/expectations/tests/bitfield_pack_offset.rs new file mode 100644 index 0000000000..d654e25b27 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/bitfield_pack_offset.rs @@ -0,0 +1,507 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct A { + pub name: [::std::os::raw::c_uchar; 7usize], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, + pub maxYield: ::std::os::raw::c_uchar, + pub _bitfield_2: __BindgenBitfieldUnit<[u8; 1usize]>, + pub description1: *const ::std::os::raw::c_uchar, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of A"][::std::mem::size_of::() - 24usize]; + ["Alignment of A"][::std::mem::align_of::() - 8usize]; + ["Offset of field: A::name"][::std::mem::offset_of!(A, name) - 0usize]; + ["Offset of field: A::maxYield"][::std::mem::offset_of!(A, maxYield) - 10usize]; + [ + "Offset of field: A::description1", + ][::std::mem::offset_of!(A, description1) - 16usize]; +}; +impl Default for A { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl A { + #[inline] + pub fn firmness(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) } + } + #[inline] + pub fn set_firmness(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn firmness_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_firmness_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn color(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) } + } + #[inline] + pub fn set_color(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_1.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn color_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 4usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_color_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn weedsBonus(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 3u8) as u16) } + } + #[inline] + pub fn set_weedsBonus(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(8usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn weedsBonus_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 8usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_weedsBonus_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 8usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn pestsBonus(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 3u8) as u16) } + } + #[inline] + pub fn set_pestsBonus(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(11usize, 3u8, val as u64) + } + } + #[inline] + pub unsafe fn pestsBonus_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 11usize, 3u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_pestsBonus_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 11usize, + 3u8, + val as u64, + ) + } + } + #[inline] + pub fn size(&self) -> ::std::os::raw::c_ushort { + unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 10u8) as u16) } + } + #[inline] + pub fn set_size(&mut self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + self._bitfield_1.set(14usize, 10u8, val as u64) + } + } + #[inline] + pub unsafe fn size_raw(this: *const Self) -> ::std::os::raw::c_ushort { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 14usize, 10u8) + as u16, + ) + } + } + #[inline] + pub unsafe fn set_size_raw(this: *mut Self, val: ::std::os::raw::c_ushort) { + unsafe { + let val: u16 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 3usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 14usize, + 10u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + firmness: ::std::os::raw::c_uchar, + color: ::std::os::raw::c_uchar, + weedsBonus: ::std::os::raw::c_ushort, + pestsBonus: ::std::os::raw::c_ushort, + size: ::std::os::raw::c_ushort, + ) -> __BindgenBitfieldUnit<[u8; 3usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let firmness: u8 = unsafe { ::std::mem::transmute(firmness) }; + firmness as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let color: u8 = unsafe { ::std::mem::transmute(color) }; + color as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 8usize, + 3u8, + { + let weedsBonus: u16 = unsafe { ::std::mem::transmute(weedsBonus) }; + weedsBonus as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 11usize, + 3u8, + { + let pestsBonus: u16 = unsafe { ::std::mem::transmute(pestsBonus) }; + pestsBonus as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 14usize, + 10u8, + { + let size: u16 = unsafe { ::std::mem::transmute(size) }; + size as u64 + }, + ); + __bindgen_bitfield_unit + } + #[inline] + pub fn minYield(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_2.get(0usize, 4u8) as u8) } + } + #[inline] + pub fn set_minYield(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(0usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn minYield_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 0usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_minYield_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 0usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn waterBonus(&self) -> ::std::os::raw::c_uchar { + unsafe { ::std::mem::transmute(self._bitfield_2.get(4usize, 4u8) as u8) } + } + #[inline] + pub fn set_waterBonus(&mut self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + self._bitfield_2.set(4usize, 4u8, val as u64) + } + } + #[inline] + pub unsafe fn waterBonus_raw(this: *const Self) -> ::std::os::raw::c_uchar { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_2), 4usize, 4u8) as u8, + ) + } + } + #[inline] + pub unsafe fn set_waterBonus_raw(this: *mut Self, val: ::std::os::raw::c_uchar) { + unsafe { + let val: u8 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 1usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_2), + 4usize, + 4u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_2( + minYield: ::std::os::raw::c_uchar, + waterBonus: ::std::os::raw::c_uchar, + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 4u8, + { + let minYield: u8 = unsafe { ::std::mem::transmute(minYield) }; + minYield as u64 + }, + ); + __bindgen_bitfield_unit + .set( + 4usize, + 4u8, + { + let waterBonus: u8 = unsafe { ::std::mem::transmute(waterBonus) }; + waterBonus as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs b/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs index 8869593ed5..6f9adcb5ab 100644 --- a/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs +++ b/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Struct { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -394,7 +393,7 @@ impl Struct { #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Inner { - pub _bitfield_align_1: [u16; 0], + pub _bindgen_align: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs b/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs index fc9f9a38c7..77c263e3cc 100644 --- a/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs +++ b/bindgen-tests/tests/expectations/tests/blocklist_bitfield_unit.rs @@ -6,7 +6,6 @@ use bitfields::*; #[derive(Debug, Default, Copy, Clone)] pub struct C { pub x: ::std::os::raw::c_uchar, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub baz: ::std::os::raw::c_uint, } diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs b/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs index aeb6a717f6..aeefb2e0f9 100644 --- a/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs +++ b/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs @@ -154,7 +154,6 @@ pub struct Point { #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Color { - pub(crate) _bitfield_align_1: [u8; 0], pub(crate) _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } impl Color { diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_private.rs b/bindgen-tests/tests/expectations/tests/default_visibility_private.rs index 4ee26721b0..dceed75e36 100644 --- a/bindgen-tests/tests/expectations/tests/default_visibility_private.rs +++ b/bindgen-tests/tests/expectations/tests/default_visibility_private.rs @@ -154,7 +154,6 @@ pub struct Point { #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Color { - _bitfield_align_1: [u8; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } impl Color { diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs b/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs index e676f6470d..f43be84bb0 100644 --- a/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs +++ b/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs @@ -154,7 +154,6 @@ pub struct Point { #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Color { - _bitfield_align_1: [u8; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } impl Color { diff --git a/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs b/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs index 05e66a72bc..c2a9d33ca6 100644 --- a/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs +++ b/bindgen-tests/tests/expectations/tests/derive-bitfield-method-same-name.rs @@ -94,7 +94,6 @@ where #[derive(Copy, Clone)] pub struct Foo { pub large: [::std::os::raw::c_int; 33usize], - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, pub __bindgen_padding_0: u16, } diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs index 351d3b31e5..c5eed87ae5 100644 --- a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs +++ b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-1-51.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct C { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub large_array: [::std::os::raw::c_int; 50usize], } diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs index edcb4e2a02..baeb87545d 100644 --- a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs +++ b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield-core.rs @@ -91,7 +91,6 @@ where #[repr(C)] #[derive(Copy, Clone)] pub struct C { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub large_array: [::std::os::raw::c_int; 50usize], } diff --git a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs index e266880509..e414b6fa32 100644 --- a/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs +++ b/bindgen-tests/tests/expectations/tests/derive-debug-bitfield.rs @@ -90,7 +90,6 @@ where #[repr(C)] #[derive(Copy, Clone)] pub struct C { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub large_array: [::std::os::raw::c_int; 50usize], } diff --git a/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs b/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs index eaf3f45e5f..7bcdce32a3 100644 --- a/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs +++ b/bindgen-tests/tests/expectations/tests/derive-partialeq-bitfield.rs @@ -90,7 +90,6 @@ where #[repr(C)] #[derive(Copy, Clone)] pub struct C { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub large_array: [::std::os::raw::c_int; 50usize], } diff --git a/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs b/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs index e01a9b3c72..37139d3136 100644 --- a/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs +++ b/bindgen-tests/tests/expectations/tests/divide-by-zero-in-struct-layout.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct WithBitfield { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub a: ::std::os::raw::c_uint, } @@ -162,7 +161,6 @@ impl WithBitfield { #[repr(C, packed)] #[derive(Debug, Default, Copy, Clone)] pub struct WithBitfieldAndAttrPacked { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub a: ::std::os::raw::c_uint, } @@ -176,7 +174,6 @@ impl WithBitfieldAndAttrPacked { #[repr(C, packed)] #[derive(Debug, Default, Copy, Clone)] pub struct WithBitfieldAndPacked { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub a: ::std::os::raw::c_uint, } diff --git a/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs b/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs index aebc04f03b..99ca3d4b9b 100644 --- a/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs +++ b/bindgen-tests/tests/expectations/tests/field-visibility-callback.rs @@ -150,7 +150,6 @@ where pub struct my_struct { pub a: ::std::os::raw::c_int, private_b: ::std::os::raw::c_int, - _bitfield_align_1: [u8; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, __bindgen_padding_0: [u8; 3usize], } diff --git a/bindgen-tests/tests/expectations/tests/field-visibility.rs b/bindgen-tests/tests/expectations/tests/field-visibility.rs index 3e43755a57..13a1d9a543 100644 --- a/bindgen-tests/tests/expectations/tests/field-visibility.rs +++ b/bindgen-tests/tests/expectations/tests/field-visibility.rs @@ -146,10 +146,9 @@ where } } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct my_struct1 { - _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, __bindgen_padding_0: [u8; 3usize], } @@ -211,10 +210,9 @@ impl my_struct1 { } } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct my_struct2 { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } diff --git a/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs b/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs index 6e9f6e7753..a90fe54bf3 100644 --- a/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs +++ b/bindgen-tests/tests/expectations/tests/incomplete-array-padding.rs @@ -178,7 +178,6 @@ impl ::std::fmt::Debug for __IncompleteArrayField { #[repr(C)] #[derive(Debug)] pub struct foo { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub b: __IncompleteArrayField<*mut ::std::os::raw::c_void>, } diff --git a/bindgen-tests/tests/expectations/tests/issue-1034.rs b/bindgen-tests/tests/expectations/tests/issue-1034.rs index 1034520c48..90cc768a94 100644 --- a/bindgen-tests/tests/expectations/tests/issue-1034.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1034.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct S2 { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs b/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs index 3d14c81a77..50e9283b5a 100644 --- a/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct S1 { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/issue-1947.rs b/bindgen-tests/tests/expectations/tests/issue-1947.rs index cceb42d8c5..795b033a12 100644 --- a/bindgen-tests/tests/expectations/tests/issue-1947.rs +++ b/bindgen-tests/tests/expectations/tests/issue-1947.rs @@ -150,11 +150,10 @@ pub type U16 = ::std::os::raw::c_ushort; #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct V56AMDY { - pub _bitfield_align_1: [u16; 0], + pub _bindgen_align: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, pub MADK: U8, pub MABR: U8, - pub _bitfield_align_2: [u16; 0], pub _bitfield_2: __BindgenBitfieldUnit<[u8; 3usize]>, pub _rB_: U8, } diff --git a/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs b/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs index 4e79cfdf71..bc1951e7d1 100644 --- a/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs +++ b/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs @@ -149,7 +149,7 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct Foo { - pub _bitfield_align_1: [u64; 0], + pub _bindgen_align: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 32usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/issue-743.rs b/bindgen-tests/tests/expectations/tests/issue-743.rs new file mode 100644 index 0000000000..af3eb5bf6e --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-743.rs @@ -0,0 +1,225 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub struct __BindgenBitfieldUnit { + storage: Storage, +} +impl __BindgenBitfieldUnit { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage } + } +} +impl __BindgenBitfieldUnit +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[inline] + fn extract_bit(byte: u8, index: usize) -> bool { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + byte & mask == mask + } + #[inline] + pub fn get_bit(&self, index: usize) -> bool { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = self.storage.as_ref()[byte_index]; + Self::extract_bit(byte, index) + } + #[inline] + pub unsafe fn raw_get_bit(this: *const Self, index: usize) -> bool { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + *(core::ptr::addr_of!((*this).storage) as *const u8) + .offset(byte_index as isize) + }; + Self::extract_bit(byte, index) + } + #[inline] + fn change_bit(byte: u8, index: usize, val: bool) -> u8 { + let bit_index = if cfg!(target_endian = "big") { + 7 - (index % 8) + } else { + index % 8 + }; + let mask = 1 << bit_index; + if val { byte | mask } else { byte & !mask } + } + #[inline] + pub fn set_bit(&mut self, index: usize, val: bool) { + debug_assert!(index / 8 < self.storage.as_ref().len()); + let byte_index = index / 8; + let byte = &mut self.storage.as_mut()[byte_index]; + *byte = Self::change_bit(*byte, index, val); + } + #[inline] + pub unsafe fn raw_set_bit(this: *mut Self, index: usize, val: bool) { + debug_assert!(index / 8 < core::mem::size_of::()); + let byte_index = index / 8; + let byte = unsafe { + (core::ptr::addr_of_mut!((*this).storage) as *mut u8) + .offset(byte_index as isize) + }; + unsafe { *byte = Self::change_bit(*byte, index, val) }; + } + #[inline] + pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if self.get_bit(i + bit_offset) { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub unsafe fn raw_get(this: *const Self, bit_offset: usize, bit_width: u8) -> u64 { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + let mut val = 0; + for i in 0..(bit_width as usize) { + if unsafe { Self::raw_get_bit(this, i + bit_offset) } { + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + val |= 1 << index; + } + } + val + } + #[inline] + pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + self.set_bit(index + bit_offset, val_bit_is_set); + } + } + #[inline] + pub unsafe fn raw_set(this: *mut Self, bit_offset: usize, bit_width: u8, val: u64) { + debug_assert!(bit_width <= 64); + debug_assert!(bit_offset / 8 < core::mem::size_of::()); + debug_assert!( + (bit_offset + (bit_width as usize)) / 8 <= core::mem::size_of::(), + ); + for i in 0..(bit_width as usize) { + let mask = 1 << i; + let val_bit_is_set = val & mask == mask; + let index = if cfg!(target_endian = "big") { + bit_width as usize - 1 - i + } else { + i + }; + unsafe { Self::raw_set_bit(this, index + bit_offset, val_bit_is_set) }; + } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct S { + pub p: *mut ::std::os::raw::c_void, + pub b: bool, + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, + pub __bindgen_padding_0: [u8; 5usize], +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of S"][::std::mem::size_of::() - 16usize]; + ["Alignment of S"][::std::mem::align_of::() - 8usize]; + ["Offset of field: S::p"][::std::mem::offset_of!(S, p) - 0usize]; + ["Offset of field: S::b"][::std::mem::offset_of!(S, b) - 8usize]; +}; +impl Default for S { + fn default() -> Self { + let mut s = ::std::mem::MaybeUninit::::uninit(); + unsafe { + ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1); + s.assume_init() + } + } +} +impl S { + #[inline] + pub fn u(&self) -> ::std::os::raw::c_uint { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) } + } + #[inline] + pub fn set_u(&mut self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 16u8, val as u64) + } + } + #[inline] + pub unsafe fn u_raw(this: *const Self) -> ::std::os::raw::c_uint { + unsafe { + ::std::mem::transmute( + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 16u8) + as u32, + ) + } + } + #[inline] + pub unsafe fn set_u_raw(this: *mut Self, val: ::std::os::raw::c_uint) { + unsafe { + let val: u32 = ::std::mem::transmute(val); + <__BindgenBitfieldUnit< + [u8; 2usize], + >>::raw_set( + ::std::ptr::addr_of_mut!((*this)._bitfield_1), + 0usize, + 16u8, + val as u64, + ) + } + } + #[inline] + pub fn new_bitfield_1( + u: ::std::os::raw::c_uint, + ) -> __BindgenBitfieldUnit<[u8; 2usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); + __bindgen_bitfield_unit + .set( + 0usize, + 16u8, + { + let u: u32 = unsafe { ::std::mem::transmute(u) }; + u as u64 + }, + ); + __bindgen_bitfield_unit + } +} diff --git a/bindgen-tests/tests/expectations/tests/issue-816.rs b/bindgen-tests/tests/expectations/tests/issue-816.rs index 56e719238b..b1494afede 100644 --- a/bindgen-tests/tests/expectations/tests/issue-816.rs +++ b/bindgen-tests/tests/expectations/tests/issue-816.rs @@ -146,10 +146,9 @@ where } } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct capabilities { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs index 7dd23241e9..dc0ef8ed7f 100644 --- a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs +++ b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs @@ -245,7 +245,7 @@ pub union jsval_layout { #[repr(C)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct jsval_layout__bindgen_ty_1 { - pub _bitfield_align_1: [u64; 0], + pub _bindgen_align: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/layout_align.rs b/bindgen-tests/tests/expectations/tests/layout_align.rs index 18662d4c83..a942adb8f2 100644 --- a/bindgen-tests/tests/expectations/tests/layout_align.rs +++ b/bindgen-tests/tests/expectations/tests/layout_align.rs @@ -219,12 +219,11 @@ impl Default for rte_kni_fifo { } } #[repr(C)] -#[repr(align(8))] #[derive(Debug, Default, Copy, Clone)] pub struct rte_eth_link { + pub _bindgen_align: [u64; 0], ///< ETH_SPEED_NUM_ pub link_speed: u32, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } diff --git a/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs b/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs index 4a62ddbea3..2686d8f5fa 100644 --- a/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs +++ b/bindgen-tests/tests/expectations/tests/layout_eth_conf.rs @@ -151,7 +151,6 @@ pub struct rte_eth_rxmode { pub max_rx_pkt_len: u32, ///< hdr buf size (header_split enabled). pub split_hdr_size: u16, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, } #[test] @@ -425,7 +424,6 @@ pub struct rte_eth_txmode { ///< TX multi-queues mode. pub mq_mode: rte_eth_tx_mq_mode, pub pvid: u16, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: u8, } diff --git a/bindgen-tests/tests/expectations/tests/layout_mbuf.rs b/bindgen-tests/tests/expectations/tests/layout_mbuf.rs index cb3698812b..ce6c58e39e 100644 --- a/bindgen-tests/tests/expectations/tests/layout_mbuf.rs +++ b/bindgen-tests/tests/expectations/tests/layout_mbuf.rs @@ -259,10 +259,9 @@ pub union rte_mbuf__bindgen_ty_2 { pub __bindgen_anon_1: rte_mbuf__bindgen_ty_2__bindgen_ty_1, } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct rte_mbuf__bindgen_ty_2__bindgen_ty_1 { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -820,11 +819,11 @@ pub union rte_mbuf__bindgen_ty_5 { pub __bindgen_anon_1: rte_mbuf__bindgen_ty_5__bindgen_ty_1, } #[repr(C)] -#[repr(align(8))] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct rte_mbuf__bindgen_ty_5__bindgen_ty_1 { - pub _bitfield_align_1: [u16; 0], + pub _bindgen_align: [u64; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 7usize]>, + pub __bindgen_padding_0: u8, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { diff --git a/bindgen-tests/tests/expectations/tests/only_bitfields.rs b/bindgen-tests/tests/expectations/tests/only_bitfields.rs index 3aedce1e3f..9a73fc2fee 100644 --- a/bindgen-tests/tests/expectations/tests/only_bitfields.rs +++ b/bindgen-tests/tests/expectations/tests/only_bitfields.rs @@ -148,7 +148,6 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone)] pub struct C { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/packed-bitfield.rs b/bindgen-tests/tests/expectations/tests/packed-bitfield.rs index 4e3918f558..b5a734454a 100644 --- a/bindgen-tests/tests/expectations/tests/packed-bitfield.rs +++ b/bindgen-tests/tests/expectations/tests/packed-bitfield.rs @@ -148,7 +148,6 @@ where #[repr(C, packed)] #[derive(Debug, Default, Copy, Clone)] pub struct Date { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 3usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/private_fields.rs b/bindgen-tests/tests/expectations/tests/private_fields.rs index a5d9e84499..abb2886d39 100644 --- a/bindgen-tests/tests/expectations/tests/private_fields.rs +++ b/bindgen-tests/tests/expectations/tests/private_fields.rs @@ -159,10 +159,9 @@ const _: () = { ["Offset of field: PubPriv::y"][::std::mem::offset_of!(PubPriv, y) - 4usize]; }; #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct PrivateBitFields { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } @@ -274,10 +273,9 @@ impl PrivateBitFields { } } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct PublicBitFields { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } @@ -387,10 +385,9 @@ impl PublicBitFields { } } #[repr(C)] -#[repr(align(4))] #[derive(Debug, Default, Copy, Clone)] pub struct MixedBitFields { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub __bindgen_padding_0: [u8; 3usize], } @@ -628,7 +625,6 @@ pub struct Override { ///
b: ::std::os::raw::c_uint, private_c: ::std::os::raw::c_uint, - pub _bitfield_align_1: [u8; 0], _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, pub __bindgen_padding_0: u16, } diff --git a/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs b/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs index c01762ca98..05401e52ca 100644 --- a/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs +++ b/bindgen-tests/tests/expectations/tests/redundant-packed-and-align.rs @@ -166,11 +166,10 @@ const _: () = { ][::std::mem::offset_of!(redundant_packed, b) - 4usize]; }; #[repr(C)] -#[repr(align(8))] #[derive(Debug, Default, Copy, Clone)] pub struct redundant_packed_bitfield { + pub _bindgen_align: [u64; 0], pub a: [u8; 3usize], - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub c: u32, } diff --git a/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs b/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs index 23588ee7da..a294c871d3 100644 --- a/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs +++ b/bindgen-tests/tests/expectations/tests/struct_with_bitfields.rs @@ -148,10 +148,8 @@ where #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct bitfield { - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, pub e: ::std::os::raw::c_int, - pub _bitfield_align_2: [u32; 0], pub _bitfield_2: __BindgenBitfieldUnit<[u8; 8usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/timex.rs b/bindgen-tests/tests/expectations/tests/timex.rs index 3d25971315..f73b608de2 100644 --- a/bindgen-tests/tests/expectations/tests/timex.rs +++ b/bindgen-tests/tests/expectations/tests/timex.rs @@ -149,7 +149,6 @@ where #[derive(Debug, Copy, Clone)] pub struct timex { pub tai: ::std::os::raw::c_int, - pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 44usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -171,7 +170,6 @@ impl Default for timex { #[derive(Debug, Copy, Clone)] pub struct timex_named { pub tai: ::std::os::raw::c_int, - pub _bitfield_align_1: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 44usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/union_bitfield.rs b/bindgen-tests/tests/expectations/tests/union_bitfield.rs index 70da5c3b02..8df0724738 100644 --- a/bindgen-tests/tests/expectations/tests/union_bitfield.rs +++ b/bindgen-tests/tests/expectations/tests/union_bitfield.rs @@ -146,10 +146,9 @@ where } } #[repr(C)] -#[repr(align(4))] #[derive(Copy, Clone)] pub union U4 { - pub _bitfield_align_1: [u8; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] @@ -223,8 +222,8 @@ impl U4 { #[repr(C)] #[derive(Copy, Clone)] pub union B { - pub _bitfield_align_1: [u32; 0], - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, + pub _bindgen_align: [u32; 0], + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] const _: () = { @@ -257,7 +256,7 @@ impl B { unsafe { ::std::mem::transmute( <__BindgenBitfieldUnit< - [u8; 4usize], + [u8; 1usize], >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 31u8) as u32, ) @@ -268,7 +267,7 @@ impl B { unsafe { let val: u32 = ::std::mem::transmute(val); <__BindgenBitfieldUnit< - [u8; 4usize], + [u8; 1usize], >>::raw_set( ::std::ptr::addr_of_mut!((*this)._bitfield_1), 0usize, @@ -279,13 +278,13 @@ impl B { } #[inline] pub fn bar(&self) -> ::std::os::raw::c_uchar { - unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u8) } + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) } } #[inline] pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { unsafe { let val: u8 = ::std::mem::transmute(val); - self._bitfield_1.set(31usize, 1u8, val as u64) + self._bitfield_1.set(0usize, 1u8, val as u64) } } #[inline] @@ -293,9 +292,8 @@ impl B { unsafe { ::std::mem::transmute( <__BindgenBitfieldUnit< - [u8; 4usize], - >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 31usize, 1u8) - as u8, + [u8; 1usize], + >>::raw_get(::std::ptr::addr_of!((*this)._bitfield_1), 0usize, 1u8) as u8, ) } } @@ -304,10 +302,10 @@ impl B { unsafe { let val: u8 = ::std::mem::transmute(val); <__BindgenBitfieldUnit< - [u8; 4usize], + [u8; 1usize], >>::raw_set( ::std::ptr::addr_of_mut!((*this)._bitfield_1), - 31usize, + 0usize, 1u8, val as u64, ) @@ -317,8 +315,8 @@ impl B { pub fn new_bitfield_1( foo: ::std::os::raw::c_uint, bar: ::std::os::raw::c_uchar, - ) -> __BindgenBitfieldUnit<[u8; 4usize]> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); + ) -> __BindgenBitfieldUnit<[u8; 1usize]> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); __bindgen_bitfield_unit .set( 0usize, @@ -330,7 +328,7 @@ impl B { ); __bindgen_bitfield_unit .set( - 31usize, + 0usize, 1u8, { let bar: u8 = unsafe { ::std::mem::transmute(bar) }; diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs index dd1a55e9b5..a1b61c035d 100644 --- a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs +++ b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs @@ -154,7 +154,7 @@ pub union foo { #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] pub struct foo__bindgen_ty_1 { - pub _bitfield_align_1: [u32; 0], + pub _bindgen_align: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/expectations/tests/weird_bitfields.rs b/bindgen-tests/tests/expectations/tests/weird_bitfields.rs index 17accb01d9..ca8d84520b 100644 --- a/bindgen-tests/tests/expectations/tests/weird_bitfields.rs +++ b/bindgen-tests/tests/expectations/tests/weird_bitfields.rs @@ -156,7 +156,6 @@ pub enum nsStyleSVGOpacitySource { #[derive(Debug, Copy, Clone)] pub struct Weird { pub mStrokeDasharrayLength: ::std::os::raw::c_uint, - pub _bitfield_align_1: [u16; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, pub mClipRule: ::std::os::raw::c_uchar, pub mColorInterpolation: ::std::os::raw::c_uchar, @@ -169,7 +168,6 @@ pub struct Weird { pub mStrokeLinejoin: ::std::os::raw::c_uchar, pub mTextAnchor: ::std::os::raw::c_uchar, pub mTextRendering: ::std::os::raw::c_uchar, - pub _bitfield_align_2: [u8; 0], pub _bitfield_2: __BindgenBitfieldUnit<[u8; 2usize]>, pub __bindgen_padding_0: [u8; 3usize], } diff --git a/bindgen-tests/tests/headers/bitfield-linux-32.hpp b/bindgen-tests/tests/headers/bitfield-linux-32.hpp index b9a480df15..71ee6a7e1d 100644 --- a/bindgen-tests/tests/headers/bitfield-linux-32.hpp +++ b/bindgen-tests/tests/headers/bitfield-linux-32.hpp @@ -1,4 +1,4 @@ -// bindgen-flags: -- --target=i586-unknown-linux +// bindgen-flags: --no-layout-tests -- --target=i586-unknown-linux typedef unsigned long long uint64_t; diff --git a/bindgen-tests/tests/headers/bitfield-template.hpp b/bindgen-tests/tests/headers/bitfield-template.hpp new file mode 100644 index 0000000000..664199b9c0 --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield-template.hpp @@ -0,0 +1,4 @@ +template struct foo { + T member; + bool b : 8; +}; diff --git a/bindgen-tests/tests/headers/bitfield_pack_offset.h b/bindgen-tests/tests/headers/bitfield_pack_offset.h new file mode 100644 index 0000000000..5118a64642 --- /dev/null +++ b/bindgen-tests/tests/headers/bitfield_pack_offset.h @@ -0,0 +1,21 @@ +struct A { + const unsigned char name[7]; /* 0 7 */ + unsigned char firmness:4; /* 7: 0 1 */ + unsigned char color:4; /* 7: 4 1 */ + unsigned short weedsBonus:3; /* 8: 0 2 */ + unsigned short pestsBonus:3; /* 8: 3 2 */ + unsigned short size:10; /* 8: 6 2 */ + unsigned char maxYield; /* 10 1 */ + unsigned char minYield:4; /* 11: 0 1 */ + unsigned char waterBonus:4; /* 11: 4 1 */ + + /* XXX 4 bytes hole, try to pack */ + + const unsigned char * description1; /* 16 8 */ + + /* size: 24, cachelines: 1, members: 10 */ + /* sum members: 16, holes: 1, sum holes: 4 */ + /* sum bitfield members: 32 bits (4 bytes) */ + /* last cacheline: 24 bytes */ +}; + diff --git a/bindgen-tests/tests/headers/issue-743.h b/bindgen-tests/tests/headers/issue-743.h new file mode 100644 index 0000000000..1f8e0ccd78 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-743.h @@ -0,0 +1,6 @@ + +struct S { + void *p; + _Bool b; + unsigned u : 16; +}; \ No newline at end of file diff --git a/bindgen-tests/tests/headers/union_bitfield.h b/bindgen-tests/tests/headers/union_bitfield.h index 990729574a..4592a8973a 100644 --- a/bindgen-tests/tests/headers/union_bitfield.h +++ b/bindgen-tests/tests/headers/union_bitfield.h @@ -1,10 +1,10 @@ // bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq union U4 { - unsigned derp : 1; + unsigned int derp:1; /* 0: 0 4 */ }; union B { - unsigned foo : 31; - unsigned char bar : 1; + unsigned int foo:31; /* 0: 0 4 */ + unsigned char bar:1; /* 0: 0 1 */ }; diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index c0f461b326..5425962bac 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -1770,22 +1770,6 @@ impl FieldCodegen<'_> 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 access_spec = access_specifier(visibility_kind); - let align_field = quote! { - #access_spec #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); @@ -2428,10 +2412,24 @@ impl CodeGenerator for CompInfo { attributes.push(attributes::repr("C")); } - if true { - if let Some(explicit) = explicit_align { - // Ensure that the struct has the correct alignment even in - // presence of alignas. + // Ensure that the struct has the correct alignment even in presence of alignas and co. + if let Some(explicit) = explicit_align { + // If we need explicit alignment and can do it, we prefer to insert a dummy field at + // the beginning of the struct. This avoids hitting + // https://github.com/rust-lang/rust-bindgen/issues/2179 + // Do it for bitfields only for now for backwards compat. + if self.has_bitfields() && explicit <= 8 { + let align_ty = match explicit { + 8 => quote! { u64 }, + 4 => quote! { u32 }, + 2 => quote! { u16 }, + _ => quote! { u8 }, + }; + let align_field = quote! { + pub _bindgen_align: [#align_ty; 0], + }; + fields.insert(0, align_field); + } else { let explicit = helpers::ast_ty::int_expr(explicit as i64); attributes.push(quote! { #[repr(align(#explicit))] diff --git a/bindgen/codegen/struct_layout.rs b/bindgen/codegen/struct_layout.rs index 0d2e6a05c5..3dfd076c25 100644 --- a/bindgen/codegen/struct_layout.rs +++ b/bindgen/codegen/struct_layout.rs @@ -45,23 +45,6 @@ pub(crate) fn align_to(size: usize, align: usize) -> usize { size + align - rem } -/// Returns the lower power of two byte count that can hold at most n bits. -pub(crate) fn bytes_from_bits_pow2(mut n: usize) -> usize { - if n == 0 { - return 0; - } - - if n <= 8 { - return 1; - } - - if !n.is_power_of_two() { - n = n.next_power_of_two(); - } - - n / 8 -} - #[test] fn test_align_to() { assert_eq!(align_to(1, 1), 1); @@ -71,20 +54,6 @@ fn test_align_to() { assert_eq!(align_to(17, 4), 20); } -#[test] -fn test_bytes_from_bits_pow2() { - assert_eq!(bytes_from_bits_pow2(0), 0); - for i in 1..9 { - assert_eq!(bytes_from_bits_pow2(i), 1); - } - for i in 9..17 { - assert_eq!(bytes_from_bits_pow2(i), 2); - } - for i in 17..33 { - assert_eq!(bytes_from_bits_pow2(i), 4); - } -} - impl<'a> StructLayoutTracker<'a> { pub(crate) fn new( ctx: &'a BindgenContext, diff --git a/bindgen/ir/comp.rs b/bindgen/ir/comp.rs index 655e0f1fa5..c0860f9fe3 100644 --- a/bindgen/ir/comp.rs +++ b/bindgen/ir/comp.rs @@ -12,7 +12,7 @@ use super::template::TemplateParameters; use super::traversal::{EdgeKind, Trace, Tracer}; use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT; use crate::clang; -use crate::codegen::struct_layout::{align_to, bytes_from_bits_pow2}; +use crate::codegen::struct_layout::align_to; use crate::ir::derive::CanDeriveCopy; use crate::parse::ParseError; use crate::HashMap; @@ -560,18 +560,12 @@ where fields: &mut E, bitfield_unit_count: &mut usize, unit_size_in_bits: usize, - unit_align_in_bits: usize, bitfields: Vec, - packed: bool, ) where E: Extend, { *bitfield_unit_count += 1; - let align = if packed { - 1 - } else { - bytes_from_bits_pow2(unit_align_in_bits) - }; + let align = 1; let size = align_to(unit_size_in_bits, 8) / 8; let layout = Layout::new(size, align); fields.extend(Some(Field::Bitfields(BitfieldUnit { @@ -581,70 +575,45 @@ where }))); } + // The offset we're in inside the struct, if we know it (we might not know it in presence of + // templates). + let mut start_offset_in_struct = 0; let mut max_align = 0; - let mut unfilled_bits_in_unit = 0; let mut unit_size_in_bits = 0; - let mut unit_align = 0; let mut bitfields_in_unit = vec![]; - // TODO(emilio): Determine this from attributes or pragma ms_struct - // directives. Also, perhaps we should check if the target is MSVC? - const is_ms_struct: bool = false; - + // TODO(emilio): Deal with ms_struct bitfield layout for MSVC? for bitfield in raw_bitfields { let bitfield_width = bitfield.bitfield_width().unwrap() as usize; let bitfield_layout = ctx.resolve_type(bitfield.ty()).layout(ctx).ok_or(())?; - let bitfield_size = bitfield_layout.size; let bitfield_align = bitfield_layout.align; + let bitfield_size = bitfield_layout.size; - let mut offset = unit_size_in_bits; - if !packed { - if is_ms_struct { - if unit_size_in_bits != 0 && - (bitfield_width == 0 || - bitfield_width > unfilled_bits_in_unit) - { - // We've reached the end of this allocation unit, so flush it - // and its bitfields. - unit_size_in_bits = - align_to(unit_size_in_bits, unit_align * 8); - flush_allocation_unit( - fields, - bitfield_unit_count, - unit_size_in_bits, - unit_align, - mem::take(&mut bitfields_in_unit), - packed, - ); + if unit_size_in_bits == 0 { + start_offset_in_struct = bitfield.offset().unwrap_or(0); + } - // Now we're working on a fresh bitfield allocation unit, so reset - // the current unit size and alignment. - offset = 0; - unit_align = 0; - } - } else if offset != 0 && - (bitfield_width == 0 || - (offset & (bitfield_align * 8 - 1)) + bitfield_width > - bitfield_size * 8) - { - offset = align_to(offset, bitfield_align * 8); - } + let mut offset_in_struct = + bitfield.offset().unwrap_or(unit_size_in_bits); + + // A zero-width field serves as alignment / padding. + if !packed && + offset_in_struct != 0 && + (bitfield_width == 0 || + (offset_in_struct & (bitfield_align * 8 - 1)) + + bitfield_width > + bitfield_size * 8) + { + offset_in_struct = align_to(offset_in_struct, bitfield_align * 8); } - // 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. + // 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 @@ -652,15 +621,12 @@ where // bitfields over their types size cause weird allocation size behavior from clang. // Therefore, all bitfields needed to be kept around in order to check for this // and make the struct opaque in this case - bitfields_in_unit.push(Bitfield::new(offset, bitfield)); - - unit_size_in_bits = offset + bitfield_width; - - // Compute what the physical unit's final size would be given what we - // have seen so far, and use that to compute how many bits are still - // available in the unit. - let data_size = align_to(unit_size_in_bits, bitfield_align * 8); - unfilled_bits_in_unit = data_size - unit_size_in_bits; + bitfields_in_unit.push(Bitfield::new( + offset_in_struct - start_offset_in_struct, + bitfield, + )); + unit_size_in_bits = + offset_in_struct - start_offset_in_struct + bitfield_width; } if unit_size_in_bits != 0 { @@ -669,9 +635,7 @@ where fields, bitfield_unit_count, unit_size_in_bits, - unit_align, bitfields_in_unit, - packed, ); } @@ -1181,7 +1145,8 @@ impl CompInfo { } } - fn has_bitfields(&self) -> bool { + /// Returns whether we have any bitfield within the struct. + pub(crate) fn has_bitfields(&self) -> bool { match self.fields { CompFields::Error => false, CompFields::After {