summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs10
-rw-r--r--src/ir/comp.rs5
-rw-r--r--tests/expectations/tests/bitfield_align.rs116
-rw-r--r--tests/headers/bitfield_align.h16
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;
+};