diff options
-rw-r--r-- | src/codegen/mod.rs | 12 | ||||
-rw-r--r-- | tests/expectations/tests/bitfield-linux-32.rs | 147 | ||||
-rw-r--r-- | tests/headers/bitfield-linux-32.hpp | 8 |
3 files changed, 160 insertions, 7 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index bce52c53..32dc48a1 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1200,12 +1200,8 @@ impl BitfieldUnit { impl Bitfield { /// Extend an under construction bitfield unit constructor with this - /// bitfield. This involves two things: - /// - /// 1. Adding a parameter with this bitfield's name and its type. - /// - /// 2. Setting the relevant bits on the `__bindgen_bitfield_unit` variable - /// that's being constructed. + /// bitfield. This sets the relevant bits on the `__bindgen_bitfield_unit` + /// variable that's being constructed. fn extend_ctor_impl( &self, ctx: &BindgenContext, @@ -1216,7 +1212,9 @@ impl Bitfield { let bitfield_ty_layout = bitfield_ty .layout(ctx) .expect("Bitfield without layout? Gah!"); - let bitfield_int_ty = helpers::blob(ctx, bitfield_ty_layout); + let bitfield_int_ty = helpers::integer_type(ctx, bitfield_ty_layout) + .expect("Should already have verified that the bitfield is \ + representable as an int"); let offset = self.offset_into_unit(); let width = self.width() as u8; diff --git a/tests/expectations/tests/bitfield-linux-32.rs b/tests/expectations/tests/bitfield-linux-32.rs new file mode 100644 index 00000000..8b6d5306 --- /dev/null +++ b/tests/expectations/tests/bitfield-linux-32.rs @@ -0,0 +1,147 @@ +/* automatically generated by rust-bindgen */ + +#![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, Align> { + storage: Storage, + align: [Align; 0], +} +impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> { + #[inline] + pub const fn new(storage: Storage) -> Self { + Self { storage, align: [] } + } +} +impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align> +where + Storage: AsRef<[u8]> + AsMut<[u8]>, +{ + #[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]; + 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 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]; + 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 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 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); + } + } +} +#[repr(C, packed(4))] +#[repr(align(4))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Test { + pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize], u64>, +} +#[test] +fn bindgen_test_layout_Test() { + assert_eq!( + ::std::mem::size_of::<Test>(), + 8usize, + concat!("Size of: ", stringify!(Test)) + ); + assert_eq!( + ::std::mem::align_of::<Test>(), + 4usize, + concat!("Alignment of ", stringify!(Test)) + ); +} +impl Test { + #[inline] + pub fn x(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 56u8) as u64) } + } + #[inline] + pub fn set_x(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(0usize, 56u8, val as u64) + } + } + #[inline] + pub fn y(&self) -> u64 { + unsafe { ::std::mem::transmute(self._bitfield_1.get(56usize, 8u8) as u64) } + } + #[inline] + pub fn set_y(&mut self, val: u64) { + unsafe { + let val: u64 = ::std::mem::transmute(val); + self._bitfield_1.set(56usize, 8u8, val as u64) + } + } + #[inline] + pub fn new_bitfield_1(x: u64, y: u64) -> __BindgenBitfieldUnit<[u8; 8usize], u64> { + let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize], u64> = + Default::default(); + __bindgen_bitfield_unit.set(0usize, 56u8, { + let x: u64 = unsafe { ::std::mem::transmute(x) }; + x as u64 + }); + __bindgen_bitfield_unit.set(56usize, 8u8, { + let y: u64 = unsafe { ::std::mem::transmute(y) }; + y as u64 + }); + __bindgen_bitfield_unit + } +} diff --git a/tests/headers/bitfield-linux-32.hpp b/tests/headers/bitfield-linux-32.hpp new file mode 100644 index 00000000..b15aaded --- /dev/null +++ b/tests/headers/bitfield-linux-32.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: -- --target=i586-unknown-linux + +typedef unsigned long long uint64_t; + +struct Test { + uint64_t x : 56; + uint64_t y : 8; +}; |