diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-06-04 01:22:07 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-06-05 20:05:01 +0200 |
commit | 10106aa8a40f36477fdc9cd034d9a2eec2698318 (patch) | |
tree | 043ca73acc6457521eca880e2379ed711c783f04 | |
parent | 1f87fc87bc0ffb90e1ff22e19e31b53bfdae64b9 (diff) |
ir: Fix a bunch of bitfield correctness issues.
In particular, the "flush the allocation unit" logic is only valid for
ms_structs (that is, MSVC).
It's slightly annoying to have this different behavior, but it'd work just fine
if we'd turn that on for MSVC.
This patch doesn't do that, yet at least, and adds tests for all the weird
bitfield alignments around.
Fixes #726 (and another set of hidden issues by the old code).
-rw-r--r-- | bindgen-integration/cpp/Test.cc | 20 | ||||
-rw-r--r-- | bindgen-integration/cpp/Test.h | 31 | ||||
-rwxr-xr-x | bindgen-integration/src/lib.rs | 39 | ||||
-rw-r--r-- | src/ir/comp.rs | 68 | ||||
-rw-r--r-- | tests/expectations/tests/bitfield_align.rs | 192 | ||||
-rw-r--r-- | tests/expectations/tests/bitfield_align_2.rs | 72 | ||||
-rw-r--r-- | tests/expectations/tests/struct_with_bitfields.rs | 44 | ||||
-rw-r--r-- | tests/expectations/tests/weird_bitfields.rs | 110 | ||||
-rw-r--r-- | tests/headers/bitfield_align.h | 12 | ||||
-rw-r--r-- | tests/headers/bitfield_align_2.h | 12 |
10 files changed, 405 insertions, 195 deletions
diff --git a/bindgen-integration/cpp/Test.cc b/bindgen-integration/cpp/Test.cc index 7b0ec4ad..9d91250c 100644 --- a/bindgen-integration/cpp/Test.cc +++ b/bindgen-integration/cpp/Test.cc @@ -56,4 +56,24 @@ Third::assert(int first, bool second, ItemKind third) kind == third; } +bool +Fourth::assert(MyEnum tag, unsigned long ptr) +{ + return this->tag == tag && this->ptr == ptr; +} + +bool +Date2::assert(unsigned short nWeekDay, + unsigned short nMonthDay, + unsigned short nMonth, + unsigned short nYear, + unsigned short byte) +{ + return this->nWeekDay == nWeekDay && + this->nMonthDay == nMonthDay && + this->nMonth == nMonth && + this->nYear == nYear && + this->byte == byte; +} + } // namespace bitfields diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h index 01c7aea1..4b8c1690 100644 --- a/bindgen-integration/cpp/Test.h +++ b/bindgen-integration/cpp/Test.h @@ -49,7 +49,7 @@ struct Second { }; enum ItemKind { - ITEM_KIND_UNO, + ITEM_KIND_UNO = 0, ITEM_KIND_DOS, ITEM_KIND_TRES, }; @@ -63,6 +63,35 @@ struct Third { bool assert(int first, bool second, ItemKind third); }; +enum MyEnum { + ONE = 0, + TWO, + THREE, + FOUR, +}; + +struct Fourth { + MyEnum tag: 2; + unsigned long ptr: 48; + + /// Returns true if the bitfields match the arguments, false otherwise. + bool assert(MyEnum tag, unsigned long ptr); +}; + +struct Date2 { + 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 : 8; + + bool assert(unsigned short nWeekDay, + unsigned short nMonthDay, + unsigned short nMonth, + unsigned short nYear, + unsigned short byte); +}; + } // namespace bitfields struct AutoRestoreBool { diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index fe832464..ea2b77b2 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -103,10 +103,45 @@ fn test_bitfields_third() { } #[test] +fn test_bitfields_fourth() { + let mut fourth: bindings::bitfields::Fourth = unsafe { + mem::zeroed() + }; + assert!(unsafe { + fourth.assert(bindings::bitfields::MyEnum::ONE, 0) + }); + + fourth.set_tag(bindings::bitfields::MyEnum::THREE); + fourth.set_ptr(0xdeadbeef); + assert!(unsafe { + fourth.assert(bindings::bitfields::MyEnum::THREE, 0xdeadbeef) + }); +} + +#[test] +fn test_bitfields_date2() { + let mut date: bindings::bitfields::Date2 = unsafe { + mem::zeroed() + }; + assert!(unsafe { + date.assert(0, 0, 0, 0, 0) + }); + + date.set_nWeekDay(6); // saturdays are the best + date.set_nMonthDay(20); + date.set_nMonth(11); + date.set_nYear(95); + date.set_byte(255); + assert!(unsafe { + date.assert(6, 20, 11, 95, 255) + }); +} + +#[test] fn test_bitfield_constructors() { + use std::mem; let mut first = bindings::bitfields::First { - _bitfield_1: bindings::bitfields::First::new_bitfield_1(1), - _bitfield_2: bindings::bitfields::First::new_bitfield_2(2, 3), + _bitfield_1: unsafe { mem::transmute(bindings::bitfields::First::new_bitfield_1(1, 2, 3)) }, __bindgen_align: [], }; assert!(unsafe { diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 9c7577c9..5be20416 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -490,30 +490,48 @@ fn bitfields_to_allocation_units<E, I>(ctx: &BindgenContext, 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; + for bitfield in raw_bitfields { let bitfield_width = bitfield.bitfield().unwrap() as usize; - let bitfield_align = ctx.resolve_type(bitfield.ty()) - .layout(ctx) - .expect("Bitfield without layout? Gah!") - .align; - - 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, - bitfield_align); - flush_allocation_unit(fields, - bitfield_unit_count, - unit_size_in_bits, - unit_align, - mem::replace(&mut bitfields_in_unit, vec![])); - - // Now we're working on a fresh bitfield allocation unit, so reset - // the current unit size and alignment. - unit_size_in_bits = 0; - unit_align = 0; + let bitfield_layout = + ctx.resolve_type(bitfield.ty()) + .layout(ctx) + .expect("Bitfield without layout? Gah!"); + let bitfield_size = bitfield_layout.size; + let bitfield_align = bitfield_layout.align; + + let mut offset = unit_size_in_bits; + 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::replace(&mut bitfields_in_unit, vec![])); + + // Now we're working on a fresh bitfield allocation unit, so reset + // the current unit size and alignment. + #[allow(unused_assignments)] + { + unit_size_in_bits = 0; + 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); + } } // Only keep named bitfields around. Unnamed bitfields (with > 0 @@ -521,11 +539,9 @@ fn bitfields_to_allocation_units<E, I>(ctx: &BindgenContext, // the bit-offset into its allocation unit where its bits begin, we // don't need any padding bits hereafter. if bitfield.name().is_some() { - bitfields_in_unit.push(Bitfield::new(unit_size_in_bits, bitfield)); + bitfields_in_unit.push(Bitfield::new(offset, bitfield)); } - unit_size_in_bits += bitfield_width; - max_align = cmp::max(max_align, bitfield_align); // NB: The `bitfield_width` here is completely, absolutely intentional. @@ -533,6 +549,8 @@ fn bitfields_to_allocation_units<E, I>(ctx: &BindgenContext, // width, not (directly) on the bitfields' types' alignment. unit_align = cmp::max(unit_align, bitfield_width); + 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. diff --git a/tests/expectations/tests/bitfield_align.rs b/tests/expectations/tests/bitfield_align.rs index 7ebf1bbe..9b1fc603 100644 --- a/tests/expectations/tests/bitfield_align.rs +++ b/tests/expectations/tests/bitfield_align.rs @@ -392,9 +392,7 @@ impl C { #[repr(C)] #[derive(Debug, Default, Copy)] pub struct Date1 { - pub _bitfield_1: [u8; 2usize], - pub _bitfield_2: u8, - pub __bindgen_padding_0: u8, + pub _bitfield_1: [u8; 4usize], pub __bindgen_align: [u16; 0usize], } #[test] @@ -410,17 +408,17 @@ impl Clone for Date1 { impl Date1 { #[inline] pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { - let mask = 7usize as u16; - let unit_field_val: u16 = + 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 u16; - let val = val as u16 as u16; - let mut unit_field_val: u16 = + 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; @@ -428,17 +426,17 @@ impl Date1 { } #[inline] pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { - let mask = 504usize as u16; - let unit_field_val: u16 = + 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 u16; - let val = val as u16 as u16; - let mut unit_field_val: u16 = + 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; @@ -446,62 +444,62 @@ impl Date1 { } #[inline] pub fn nMonth(&self) -> ::std::os::raw::c_ushort { - let mask = 15872usize as u16; - let unit_field_val: u16 = + 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 u16; - let val = val as u16 as u16; - let mut unit_field_val: u16 = + 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 new_bitfield_1(nWeekDay: ::std::os::raw::c_ushort, - nMonthDay: ::std::os::raw::c_ushort, - nMonth: ::std::os::raw::c_ushort) -> u16 { - ({ - ({ - ({ 0 } | - ((nWeekDay as u16 as u16) << 0usize) & (7usize as u16)) - } | ((nMonthDay as u16 as u16) << 3usize) & (504usize as u16)) - } | ((nMonth as u16 as u16) << 9usize) & (15872usize as u16)) - } - #[inline] pub fn nYear(&self) -> ::std::os::raw::c_ushort { - let mask = 255usize as u8; - let unit_field_val: u8 = - unsafe { ::std::mem::transmute(self._bitfield_2) }; - let val = (unit_field_val & mask) >> 0usize; + 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 = 255usize as u8; - let val = val as u16 as u8; - let mut unit_field_val: u8 = - unsafe { ::std::mem::transmute(self._bitfield_2) }; + 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 << 0usize) & mask; - self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; + unit_field_val |= (val << 16usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] - pub fn new_bitfield_2(nYear: ::std::os::raw::c_ushort) -> u8 { - ({ 0 } | ((nYear as u16 as u8) << 0usize) & (255usize as u8)) + 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)) } } #[repr(C)] #[derive(Debug, Default, Copy)] pub struct Date2 { - pub _bitfield_1: [u8; 2usize], - pub _bitfield_2: u8, - pub byte: ::std::os::raw::c_uchar, + pub _bitfield_1: [u8; 4usize], pub __bindgen_align: [u16; 0usize], } #[test] @@ -510,11 +508,6 @@ fn bindgen_test_layout_Date2() { "Size of: " , stringify ! ( Date2 ) )); assert_eq! (::std::mem::align_of::<Date2>() , 2usize , concat ! ( "Alignment of " , stringify ! ( Date2 ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const Date2 ) ) . byte as * const _ as usize } - , 3usize , concat ! ( - "Alignment of field: " , stringify ! ( Date2 ) , "::" , - stringify ! ( byte ) )); } impl Clone for Date2 { fn clone(&self) -> Self { *self } @@ -522,17 +515,17 @@ impl Clone for Date2 { impl Date2 { #[inline] pub fn nWeekDay(&self) -> ::std::os::raw::c_ushort { - let mask = 7usize as u16; - let unit_field_val: u16 = + 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 u16; - let val = val as u16 as u16; - let mut unit_field_val: u16 = + 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; @@ -540,17 +533,17 @@ impl Date2 { } #[inline] pub fn nMonthDay(&self) -> ::std::os::raw::c_ushort { - let mask = 504usize as u16; - let unit_field_val: u16 = + 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 u16; - let val = val as u16 as u16; - let mut unit_field_val: u16 = + 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; @@ -558,53 +551,78 @@ impl Date2 { } #[inline] pub fn nMonth(&self) -> ::std::os::raw::c_ushort { - let mask = 15872usize as u16; - let unit_field_val: u16 = + 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 u16; - let val = val as u16 as u16; - let mut unit_field_val: u16 = + 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 new_bitfield_1(nWeekDay: ::std::os::raw::c_ushort, - nMonthDay: ::std::os::raw::c_ushort, - nMonth: ::std::os::raw::c_ushort) -> u16 { - ({ - ({ - ({ 0 } | - ((nWeekDay as u16 as u16) << 0usize) & (7usize as u16)) - } | ((nMonthDay as u16 as u16) << 3usize) & (504usize as u16)) - } | ((nMonth as u16 as u16) << 9usize) & (15872usize as u16)) - } - #[inline] pub fn nYear(&self) -> ::std::os::raw::c_ushort { - let mask = 255usize as u8; - let unit_field_val: u8 = - unsafe { ::std::mem::transmute(self._bitfield_2) }; - let val = (unit_field_val & mask) >> 0usize; + 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 = 255usize as u8; - let val = val as u16 as u8; - let mut unit_field_val: u8 = - unsafe { ::std::mem::transmute(self._bitfield_2) }; + 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 << 0usize) & mask; - self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; + unit_field_val |= (val << 16usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] + pub fn byte(&self) -> ::std::os::raw::c_uchar { + let mask = 4278190080usize as u32; + let unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 24usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_byte(&mut self, val: ::std::os::raw::c_uchar) { + let mask = 4278190080usize as u32; + let val = val as u8 as u32; + let mut unit_field_val: u32 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + unit_field_val &= !mask; + unit_field_val |= (val << 24usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] - pub fn new_bitfield_2(nYear: ::std::os::raw::c_ushort) -> u8 { - ({ 0 } | ((nYear as u16 as u8) << 0usize) & (255usize as u8)) + 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, + byte: ::std::os::raw::c_uchar) -> 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)) + } | ((byte as u8 as u32) << 24usize) & (4278190080usize as u32)) } } diff --git a/tests/expectations/tests/bitfield_align_2.rs b/tests/expectations/tests/bitfield_align_2.rs new file mode 100644 index 00000000..f406948c --- /dev/null +++ b/tests/expectations/tests/bitfield_align_2.rs @@ -0,0 +1,72 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MyEnum { ONE = 0, TWO = 1, THREE = 2, FOUR = 3, } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct TaggedPtr { + pub _bitfield_1: u64, + pub __bindgen_align: [u64; 0usize], +} +#[test] +fn bindgen_test_layout_TaggedPtr() { + assert_eq!(::std::mem::size_of::<TaggedPtr>() , 8usize , concat ! ( + "Size of: " , stringify ! ( TaggedPtr ) )); + assert_eq! (::std::mem::align_of::<TaggedPtr>() , 8usize , concat ! ( + "Alignment of " , stringify ! ( TaggedPtr ) )); +} +impl Clone for TaggedPtr { + fn clone(&self) -> Self { *self } +} +impl Default for TaggedPtr { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +impl TaggedPtr { + #[inline] + pub fn tag(&self) -> MyEnum { + let mask = 3usize as u64; + let unit_field_val: u64 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u32) } + } + #[inline] + pub fn set_tag(&mut self, val: MyEnum) { + let mask = 3usize as u64; + let val = val as u32 as u64; + let mut unit_field_val: u64 = + 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 ptr(&self) -> ::std::os::raw::c_long { + let mask = 18446744073709551612usize as u64; + let unit_field_val: u64 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + let val = (unit_field_val & mask) >> 2usize; + unsafe { ::std::mem::transmute(val as u64) } + } + #[inline] + pub fn set_ptr(&mut self, val: ::std::os::raw::c_long) { + let mask = 18446744073709551612usize as u64; + let val = val as u64 as u64; + let mut unit_field_val: u64 = + unsafe { ::std::mem::transmute(self._bitfield_1) }; + unit_field_val &= !mask; + unit_field_val |= (val << 2usize) & mask; + self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] + pub fn new_bitfield_1(tag: MyEnum, ptr: ::std::os::raw::c_long) -> u64 { + ({ ({ 0 } | ((tag as u32 as u64) << 0usize) & (3usize as u64)) } | + ((ptr as u64 as u64) << 2usize) & + (18446744073709551612usize as u64)) + } +} diff --git a/tests/expectations/tests/struct_with_bitfields.rs b/tests/expectations/tests/struct_with_bitfields.rs index 135cf087..44681d2e 100644 --- a/tests/expectations/tests/struct_with_bitfields.rs +++ b/tests/expectations/tests/struct_with_bitfields.rs @@ -9,8 +9,7 @@ pub struct bitfield { pub _bitfield_1: u8, pub e: ::std::os::raw::c_int, - pub _bitfield_2: u8, - pub _bitfield_3: u32, + pub _bitfield_2: [u32; 2usize], } #[test] fn bindgen_test_layout_bitfield() { @@ -114,46 +113,45 @@ impl bitfield { } #[inline] pub fn f(&self) -> ::std::os::raw::c_uint { - let mask = 3usize as u8; - let unit_field_val: u8 = + let mask = 3usize as u64; + let unit_field_val: u64 = unsafe { ::std::mem::transmute(self._bitfield_2) }; let val = (unit_field_val & mask) >> 0usize; unsafe { ::std::mem::transmute(val as u32) } } #[inline] pub fn set_f(&mut self, val: ::std::os::raw::c_uint) { - let mask = 3usize as u8; - let val = val as u32 as u8; - let mut unit_field_val: u8 = + let mask = 3usize as u64; + let val = val as u32 as u64; + let mut unit_field_val: u64 = unsafe { ::std::mem::transmute(self._bitfield_2) }; unit_field_val &= !mask; unit_field_val |= (val << 0usize) & mask; self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] - pub fn new_bitfield_2(f: ::std::os::raw::c_uint) -> u8 { - ({ 0 } | ((f as u32 as u8) << 0usize) & (3usize as u8)) - } - #[inline] pub fn g(&self) -> ::std::os::raw::c_uint { - let mask = 4294967295usize as u32; - let unit_field_val: u32 = - unsafe { ::std::mem::transmute(self._bitfield_3) }; - let val = (unit_field_val & mask) >> 0usize; + let mask = 18446744069414584320usize as u64; + let unit_field_val: u64 = + unsafe { ::std::mem::transmute(self._bitfield_2) }; + let val = (unit_field_val & mask) >> 32usize; unsafe { ::std::mem::transmute(val as u32) } } #[inline] pub fn set_g(&mut self, val: ::std::os::raw::c_uint) { - let mask = 4294967295usize as u32; - let val = val as u32 as u32; - let mut unit_field_val: u32 = - unsafe { ::std::mem::transmute(self._bitfield_3) }; + let mask = 18446744069414584320usize as u64; + let val = val as u32 as u64; + let mut unit_field_val: u64 = + unsafe { ::std::mem::transmute(self._bitfield_2) }; unit_field_val &= !mask; - unit_field_val |= (val << 0usize) & mask; - self._bitfield_3 = unsafe { ::std::mem::transmute(unit_field_val) }; + unit_field_val |= (val << 32usize) & mask; + self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] - pub fn new_bitfield_3(g: ::std::os::raw::c_uint) -> u32 { - ({ 0 } | ((g as u32 as u32) << 0usize) & (4294967295usize as u32)) + pub fn new_bitfield_2(f: ::std::os::raw::c_uint, + g: ::std::os::raw::c_uint) -> u64 { + ({ ({ 0 } | ((f as u32 as u64) << 0usize) & (3usize as u64)) } | + ((g as u32 as u64) << 32usize) & + (18446744069414584320usize as u64)) } } diff --git a/tests/expectations/tests/weird_bitfields.rs b/tests/expectations/tests/weird_bitfields.rs index 413b7103..2fb9cbc5 100644 --- a/tests/expectations/tests/weird_bitfields.rs +++ b/tests/expectations/tests/weird_bitfields.rs @@ -27,8 +27,7 @@ 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_2: u8, - pub _bitfield_3: u8, + pub _bitfield_2: [u8; 2usize], pub __bindgen_padding_0: [u8; 3usize], } #[test] @@ -151,17 +150,17 @@ impl Weird { } #[inline] pub fn mFillOpacitySource(&self) -> nsStyleSVGOpacitySource { - let mask = 7usize as u8; - let unit_field_val: u8 = + let mask = 7usize as u16; + let unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; let val = (unit_field_val & mask) >> 0usize; unsafe { ::std::mem::transmute(val as u32) } } #[inline] pub fn set_mFillOpacitySource(&mut self, val: nsStyleSVGOpacitySource) { - let mask = 7usize as u8; - let val = val as u32 as u8; - let mut unit_field_val: u8 = + let mask = 7usize as u16; + let val = val as u32 as u16; + let mut unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; unit_field_val &= !mask; unit_field_val |= (val << 0usize) & mask; @@ -169,17 +168,17 @@ impl Weird { } #[inline] pub fn mStrokeOpacitySource(&self) -> nsStyleSVGOpacitySource { - let mask = 56usize as u8; - let unit_field_val: u8 = + let mask = 56usize as u16; + let unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; let val = (unit_field_val & mask) >> 3usize; unsafe { ::std::mem::transmute(val as u32) } } #[inline] pub fn set_mStrokeOpacitySource(&mut self, val: nsStyleSVGOpacitySource) { - let mask = 56usize as u8; - let val = val as u32 as u8; - let mut unit_field_val: u8 = + let mask = 56usize as u16; + let val = val as u32 as u16; + let mut unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; unit_field_val &= !mask; unit_field_val |= (val << 3usize) & mask; @@ -187,17 +186,17 @@ impl Weird { } #[inline] pub fn mStrokeDasharrayFromObject(&self) -> bool { - let mask = 64usize as u8; - let unit_field_val: u8 = + let mask = 64usize as u16; + let unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; let val = (unit_field_val & mask) >> 6usize; unsafe { ::std::mem::transmute(val as u8) } } #[inline] pub fn set_mStrokeDasharrayFromObject(&mut self, val: bool) { - let mask = 64usize as u8; - let val = val as u8 as u8; - let mut unit_field_val: u8 = + let mask = 64usize as u16; + let val = val as u8 as u16; + let mut unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; unit_field_val &= !mask; unit_field_val |= (val << 6usize) & mask; @@ -205,65 +204,64 @@ impl Weird { } #[inline] pub fn mStrokeDashoffsetFromObject(&self) -> bool { - let mask = 128usize as u8; - let unit_field_val: u8 = + let mask = 128usize as u16; + let unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; let val = (unit_field_val & mask) >> 7usize; unsafe { ::std::mem::transmute(val as u8) } } #[inline] pub fn set_mStrokeDashoffsetFromObject(&mut self, val: bool) { - let mask = 128usize as u8; - let val = val as u8 as u8; - let mut unit_field_val: u8 = + let mask = 128usize as u16; + let val = val as u8 as u16; + let mut unit_field_val: u16 = unsafe { ::std::mem::transmute(self._bitfield_2) }; unit_field_val &= !mask; unit_field_val |= (val << 7usize) & mask; self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] + pub fn mStrokeWidthFromObject(&self) -> bool { + let mask = 256usize as u16; + let unit_field_val: u16 = + unsafe { ::std::mem::transmute(self._bitfield_2) }; + let val = (unit_field_val & mask) >> 8usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_mStrokeWidthFromObject(&mut self, val: bool) { + let mask = 256usize as u16; + let val = val as u8 as u16; + let mut unit_field_val: u16 = + unsafe { ::std::mem::transmute(self._bitfield_2) }; + unit_field_val &= !mask; + unit_field_val |= (val << 8usize) & mask; + self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; + } + #[inline] pub fn new_bitfield_2(mFillOpacitySource: nsStyleSVGOpacitySource, mStrokeOpacitySource: nsStyleSVGOpacitySource, mStrokeDasharrayFromObject: bool, - mStrokeDashoffsetFromObject: bool) -> u8 { + mStrokeDashoffsetFromObject: bool, + mStrokeWidthFromObject: bool) -> u16 { ({ ({ ({ - ({ 0 } | - ((mFillOpacitySource as u32 as u8) << 0usize) & - (7usize as u8)) + ({ + ({ 0 } | + ((mFillOpacitySource as u32 as u16) << + 0usize) & (7usize as u16)) + } | + ((mStrokeOpacitySource as u32 as u16) << 3usize) & + (56usize as u16)) } | - ((mStrokeOpacitySource as u32 as u8) << 3usize) & - (56usize as u8)) + ((mStrokeDasharrayFromObject as u8 as u16) << 6usize) & + (64usize as u16)) } | - ((mStrokeDasharrayFromObject as u8 as u8) << 6usize) & - (64usize as u8)) + ((mStrokeDashoffsetFromObject as u8 as u16) << 7usize) & + (128usize as u16)) } | - ((mStrokeDashoffsetFromObject as u8 as u8) << 7usize) & - (128usize as u8)) - } - #[inline] - pub fn mStrokeWidthFromObject(&self) -> bool { - let mask = 1usize as u8; - let unit_field_val: u8 = - unsafe { ::std::mem::transmute(self._bitfield_3) }; - let val = (unit_field_val & mask) >> 0usize; - unsafe { ::std::mem::transmute(val as u8) } - } - #[inline] - pub fn set_mStrokeWidthFromObject(&mut self, val: bool) { - let mask = 1usize as u8; - let val = val as u8 as u8; - let mut unit_field_val: u8 = - unsafe { ::std::mem::transmute(self._bitfield_3) }; - unit_field_val &= !mask; - unit_field_val |= (val << 0usize) & mask; - self._bitfield_3 = unsafe { ::std::mem::transmute(unit_field_val) }; - } - #[inline] - pub fn new_bitfield_3(mStrokeWidthFromObject: bool) -> u8 { - ({ 0 } | - ((mStrokeWidthFromObject as u8 as u8) << 0usize) & - (1usize as u8)) + ((mStrokeWidthFromObject as u8 as u16) << 8usize) & + (256usize as u16)) } } diff --git a/tests/headers/bitfield_align.h b/tests/headers/bitfield_align.h index 82b53099..5316b697 100644 --- a/tests/headers/bitfield_align.h +++ b/tests/headers/bitfield_align.h @@ -37,5 +37,15 @@ struct Date2 { 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; + 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; +// }; diff --git a/tests/headers/bitfield_align_2.h b/tests/headers/bitfield_align_2.h new file mode 100644 index 00000000..c6e5e5e7 --- /dev/null +++ b/tests/headers/bitfield_align_2.h @@ -0,0 +1,12 @@ + +enum MyEnum { + ONE, + TWO, + THREE, + FOUR +}; + +struct TaggedPtr { + enum MyEnum tag : 2; + long ptr : 62; +}; |