diff options
-rw-r--r-- | src/codegen/mod.rs | 10 | ||||
-rw-r--r-- | src/ir/comp.rs | 5 | ||||
-rw-r--r-- | tests/expectations/tests/bitfield_align.rs | 116 | ||||
-rw-r--r-- | tests/headers/bitfield_align.h | 16 |
4 files changed, 133 insertions, 14 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 4cc41214..856ceb18 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1147,12 +1147,18 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { .build_ty(field_ty.clone()); fields.extend(Some(field)); - let unit_field_int_ty = match self.layout().size { + let mut field_int_size = self.layout().size; + if !field_int_size.is_power_of_two() { + field_int_size = field_int_size.next_power_of_two(); + } + + let unit_field_int_ty = match field_int_size { 8 => quote_ty!(ctx.ext_cx(), u64), 4 => quote_ty!(ctx.ext_cx(), u32), 2 => quote_ty!(ctx.ext_cx(), u16), 1 => quote_ty!(ctx.ext_cx(), u8), - _ => { + size => { + debug_assert!(size > 8); // Can't generate bitfield accessors for unit sizes larget than // 64 bits at the moment. struct_layout.saw_bitfield_unit(self.layout()); diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 171f130c..9370e996 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -488,8 +488,9 @@ fn bitfields_to_allocation_units<E, I>(ctx: &BindgenContext, where E: Extend<Field> { *bitfield_unit_count += 1; - let layout = Layout::new(bytes_from_bits_pow2(unit_size_in_bits), - bytes_from_bits_pow2(unit_align_in_bits)); + let align = bytes_from_bits_pow2(unit_align_in_bits); + let size = align_to(unit_size_in_bits, align * 8) / 8; + let layout = Layout::new(size, align); fields.extend(Some(Field::Bitfields(BitfieldUnit { nth: *bitfield_unit_count, layout: layout, diff --git a/tests/expectations/tests/bitfield_align.rs b/tests/expectations/tests/bitfield_align.rs index 9b1fc603..50d453fa 100644 --- a/tests/expectations/tests/bitfield_align.rs +++ b/tests/expectations/tests/bitfield_align.rs @@ -392,7 +392,8 @@ impl C { #[repr(C)] #[derive(Debug, Default, Copy)] pub struct Date1 { - pub _bitfield_1: [u8; 4usize], + pub _bitfield_1: [u8; 3usize], + pub __bindgen_padding_0: u8, pub __bindgen_align: [u16; 0usize], } #[test] @@ -626,3 +627,116 @@ impl Date2 { } | ((byte as u8 as u32) << 24usize) & (4278190080usize as u32)) } } +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Date3 { + pub _bitfield_1: [u8; 3usize], + pub byte: ::std::os::raw::c_uchar, + pub __bindgen_align: [u16; 0usize], +} +#[test] +fn bindgen_test_layout_Date3() { + assert_eq!(::std::mem::size_of::<Date3>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Date3 ) )); + assert_eq! (::std::mem::align_of::<Date3>() , 2usize , concat ! ( + "Alignment of " , stringify ! ( Date3 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Date3 ) ) . byte as * const _ as usize } + , 3usize , concat ! ( + "Alignment of field: " , stringify ! ( Date3 ) , "::" , + stringify ! ( byte ) )); +} +impl Clone for Date3 { + fn clone(&self) -> Self { *self } +} +impl Date3 { + #[inline] + pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { + let mask = 7usize as u32; + let unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u16) } + } + #[inline] + pub fn set_nWeekDay(&mut self, val: ::std::os::raw::c_ushort) { + let mask = 7usize as u32; + let val = val as u16 as u32; + let mut unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + unit_field_val &= !mask; + unit_field_val |= (val << 0usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] + pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { + let mask = 504usize as u32; + let unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 3usize; + unsafe { ::std::mem::transmute(val as u16) } + } + #[inline] + pub fn set_nMonthDay(&mut self, val: ::std::os::raw::c_ushort) { + let mask = 504usize as u32; + let val = val as u16 as u32; + let mut unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + unit_field_val &= !mask; + unit_field_val |= (val << 3usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] + pub fn nMonth(&self) -> ::std::os::raw::c_ushort { + let mask = 15872usize as u32; + let unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 9usize; + unsafe { ::std::mem::transmute(val as u16) } + } + #[inline] + pub fn set_nMonth(&mut self, val: ::std::os::raw::c_ushort) { + let mask = 15872usize as u32; + let val = val as u16 as u32; + let mut unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + unit_field_val &= !mask; + unit_field_val |= (val << 9usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] + pub fn nYear(&self) -> ::std::os::raw::c_ushort { + let mask = 16711680usize as u32; + let unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 16usize; + unsafe { ::std::mem::transmute(val as u16) } + } + #[inline] + pub fn set_nYear(&mut self, val: ::std::os::raw::c_ushort) { + let mask = 16711680usize as u32; + let val = val as u16 as u32; + let mut unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + unit_field_val &= !mask; + unit_field_val |= (val << 16usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] + pub fn new_bitfield_1(nWeekDay: ::std::os::raw::c_ushort, + nMonthDay: ::std::os::raw::c_ushort, + nMonth: ::std::os::raw::c_ushort, + nYear: ::std::os::raw::c_ushort) -> u32 { + ({ + ({ + ({ + ({ 0 } | + ((nWeekDay as u16 as u32) << 0usize) & + (7usize as u32)) + } | + ((nMonthDay as u16 as u32) << 3usize) & + (504usize as u32)) + } | ((nMonth as u16 as u32) << 9usize) & (15872usize as u32)) + } | ((nYear as u16 as u32) << 16usize) & (16711680usize as u32)) + } +} diff --git a/tests/headers/bitfield_align.h b/tests/headers/bitfield_align.h index 5316b697..7b9527a2 100644 --- a/tests/headers/bitfield_align.h +++ b/tests/headers/bitfield_align.h @@ -40,12 +40,10 @@ struct Date2 { unsigned char byte : 8; }; -// FIXME(#734) -// -// struct Date3 { -// unsigned short nWeekDay : 3; // 0..7 (3 bits) -// unsigned short nMonthDay : 6; // 0..31 (6 bits) -// unsigned short nMonth : 5; // 0..12 (5 bits) -// unsigned short nYear : 8; // 0..100 (8 bits) -// unsigned char byte; -// }; +struct Date3 { + unsigned short nWeekDay : 3; // 0..7 (3 bits) + unsigned short nMonthDay : 6; // 0..31 (6 bits) + unsigned short nMonth : 5; // 0..12 (5 bits) + unsigned short nYear : 8; // 0..100 (8 bits) + unsigned char byte; +}; |