From a7f44bd38ba38053657f898aaa0f7c551715e43e Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 19 May 2017 13:33:23 -0700 Subject: [PATCH 1/2] Add bitfield allocation unit constructors This commit gives bindgen the ability to generate constructors for bitfield allocation units. This enables more ergonomic use of struct literals for bindings structs that contain bitfields. Additionally, when we are generating unstable Rust, these constructors are marked as const functions. This enables the creation of const binding structs that contain bitfields. --- bindgen-integration/src/lib.rs | 34 +++ src/codegen/mod.rs | 121 +++++++++- src/ir/comp.rs | 6 + .../tests/bitfield-method-same-name.rs | 10 + tests/expectations/tests/bitfield_align.rs | 224 ++++++++++++++++++ .../tests/bitfield_method_mangling.rs | 16 ++ .../expectations/tests/jsval_layout_opaque.rs | 15 ++ tests/expectations/tests/layout_align.rs | 23 ++ tests/expectations/tests/layout_eth_conf.rs | 142 +++++++++++ tests/expectations/tests/layout_mbuf.rs | 112 +++++++++ tests/expectations/tests/only_bitfields.rs | 15 ++ .../tests/struct_with_bitfields.rs | 48 ++++ .../tests/union_with_anon_struct_bitfield.rs | 16 ++ tests/expectations/tests/weird_bitfields.rs | 65 +++++ 14 files changed, 846 insertions(+), 1 deletion(-) diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index be3c84518b..fe83246405 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -102,6 +102,40 @@ fn test_bitfields_third() { }); } +#[test] +fn test_bitfield_constructors() { + 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), + __bindgen_align: [], + }; + assert!(unsafe { + first.assert(1, 2, 3) + }); + + let mut second = bindings::bitfields::Second { + _bitfield_1: bindings::bitfields::Second::new_bitfield_1(1337, true), + __bindgen_align: [], + }; + assert!(unsafe { + second.assert(1337, true) + }); + + let mut third = bindings::bitfields::Third { + _bitfield_1: bindings::bitfields::Third::new_bitfield_1( + 42, + false, + bindings::bitfields::ItemKind::ITEM_KIND_TRES + ), + __bindgen_align: [], + }; + assert!(unsafe { + third.assert(42, + false, + bindings::bitfields::ItemKind::ITEM_KIND_TRES) + }); +} + impl Drop for bindings::AutoRestoreBool { fn drop(&mut self) { unsafe { bindings::AutoRestoreBool::destruct(self) } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index fdf61f407b..28cddb5d3c 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1020,6 +1020,108 @@ impl<'a> FieldCodegen<'a> for FieldData { } } +impl BitfieldUnit { + /// Get the constructor name for this bitfield unit. + fn ctor_name(&self, ctx: &BindgenContext) -> ast::Ident { + let ctor_name = format!("new_bitfield_{}", self.nth()); + ctx.ext_cx().ident_of(&ctor_name) + } + + /// Get the initial bitfield unit constructor that just returns 0. This will + /// then be extended by each bitfield in the unit. See `extend_ctor_impl` + /// below. + fn initial_ctor_impl(&self, + ctx: &BindgenContext, + unit_field_int_ty: &P) + -> P { + let ctor_name = self.ctor_name(ctx); + + // If we're generating unstable Rust, add the const. + let fn_prefix = if ctx.options().unstable_rust { + quote_tokens!(ctx.ext_cx(), pub const fn) + } else { + quote_tokens!(ctx.ext_cx(), pub fn) + }; + + quote_item!( + ctx.ext_cx(), + impl XxxUnused { + #[inline] + $fn_prefix $ctor_name() -> $unit_field_int_ty { + 0 + } + } + ).unwrap() + } +} + +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. Bitwise or'ing the parameter into the final value of the constructed + /// bitfield unit. + fn extend_ctor_impl(&self, + ctx: &BindgenContext, + parent: &CompInfo, + ctor_impl: P, + ctor_name: &ast::Ident, + unit_field_int_ty: &P) + -> P { + match ctor_impl.unwrap().node { + ast::ItemKind::Impl(_, _, _, _, _, ref items) => { + assert_eq!(items.len(), 1); + + match items.get(0).unwrap().node { + ast::ImplItemKind::Method(ref sig, ref body) => { + let params = sig.decl.clone().unwrap().inputs; + let param_name = bitfield_getter_name(ctx, parent, self.name()); + + let bitfield_ty_item = ctx.resolve_item(self.ty()); + let bitfield_ty = bitfield_ty_item.expect_type(); + let bitfield_ty_layout = bitfield_ty.layout(ctx) + .expect("Bitfield without layout? Gah!"); + let bitfield_int_ty = BlobTyBuilder::new(bitfield_ty_layout).build(); + let bitfield_ty = bitfield_ty + .to_rust_ty_or_opaque(ctx, bitfield_ty_item); + + let offset = self.offset_into_unit(); + let mask = self.mask(); + + // If we're generating unstable Rust, add the const. + let fn_prefix = if ctx.options().unstable_rust { + quote_tokens!(ctx.ext_cx(), pub const fn) + } else { + quote_tokens!(ctx.ext_cx(), pub fn) + }; + + quote_item!( + ctx.ext_cx(), + impl XxxUnused { + #[inline] + $fn_prefix $ctor_name($params $param_name : $bitfield_ty) + -> $unit_field_int_ty { + let bitfield_unit_val = $body; + let $param_name = $param_name + as $bitfield_int_ty + as $unit_field_int_ty; + let mask = $mask as $unit_field_int_ty; + let $param_name = ($param_name << $offset) & mask; + bitfield_unit_val | $param_name + } + } + ).unwrap() + } + _ => unreachable!(), + } + } + _ => unreachable!(), + } + } +} + impl<'a> FieldCodegen<'a> for BitfieldUnit { type Extra = (); @@ -1058,6 +1160,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { } }; + let ctor_name = self.ctor_name(ctx); + let mut ctor_impl = self.initial_ctor_impl(ctx, &unit_field_int_ty); + for bf in self.bitfields() { bf.codegen(ctx, fields_should_be_private, @@ -1069,8 +1174,22 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { fields, methods, (&unit_field_name, unit_field_int_ty.clone())); + + ctor_impl = bf.extend_ctor_impl(ctx, + parent, + ctor_impl, + &ctor_name, + &unit_field_int_ty); } + match ctor_impl.unwrap().node { + ast::ItemKind::Impl(_, _, _, _, _, items) => { + assert_eq!(items.len(), 1); + methods.extend(items.into_iter()); + }, + _ => unreachable!(), + }; + struct_layout.saw_bitfield_unit(self.layout()); } } @@ -1154,7 +1273,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { let bitfield_ty = bitfield_ty.to_rust_ty_or_opaque(ctx, bitfield_ty_item); let offset = self.offset_into_unit(); - let mask: usize = ((1usize << self.width()) - 1usize) << offset; + let mask: usize = self.mask(); let impl_item = quote_item!( ctx.ext_cx(), diff --git a/src/ir/comp.rs b/src/ir/comp.rs index e0ec683fc4..9c7577c91c 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -291,6 +291,12 @@ impl Bitfield { self.offset_into_unit } + /// Get the mask value that when &'ed with this bitfield's allocation unit + /// produces this bitfield's value. + pub fn mask(&self) -> usize { + ((1usize << self.width()) - 1usize) << self.offset_into_unit() + } + /// Get the bit width of this bitfield. pub fn width(&self) -> u32 { self.data.bitfield().unwrap() diff --git a/tests/expectations/tests/bitfield-method-same-name.rs b/tests/expectations/tests/bitfield-method-same-name.rs index 1cfcc189ab..f7d158bcdc 100644 --- a/tests/expectations/tests/bitfield-method-same-name.rs +++ b/tests/expectations/tests/bitfield-method-same-name.rs @@ -53,6 +53,16 @@ impl Foo { self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] + pub fn new_bitfield_1(type__bindgen_bitfield: ::std::os::raw::c_char) + -> u8 { + let bitfield_unit_val = { 0 }; + let type__bindgen_bitfield = type__bindgen_bitfield as u8 as u8; + let mask = 7usize as u8; + let type__bindgen_bitfield = + (type__bindgen_bitfield << 0usize) & mask; + bitfield_unit_val | type__bindgen_bitfield + } + #[inline] pub unsafe fn type_(&mut self) -> ::std::os::raw::c_char { Foo_type(self) } diff --git a/tests/expectations/tests/bitfield_align.rs b/tests/expectations/tests/bitfield_align.rs index a70343e21c..794b07174b 100644 --- a/tests/expectations/tests/bitfield_align.rs +++ b/tests/expectations/tests/bitfield_align.rs @@ -211,6 +211,134 @@ impl A { unit_field_val |= (val << 9usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(b1: ::std::os::raw::c_uint, + b2: ::std::os::raw::c_uint, + b3: ::std::os::raw::c_uint, + b4: ::std::os::raw::c_uint, + b5: ::std::os::raw::c_uint, + b6: ::std::os::raw::c_uint, + b7: ::std::os::raw::c_uint, + b8: ::std::os::raw::c_uint, + b9: ::std::os::raw::c_uint, + b10: ::std::os::raw::c_uint) -> u16 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + 0 + }; + let b1 = + b1 + as + u32 + as + u16; + let mask = + 1usize + as + u16; + let b1 = + (b1 + << + 0usize) + & + mask; + bitfield_unit_val + | + b1 + }; + let b2 = + b2 + as + u32 + as + u16; + let mask = + 2usize + as + u16; + let b2 = + (b2 + << + 1usize) + & + mask; + bitfield_unit_val + | + b2 + }; + let b3 = + b3 as u32 + as + u16; + let mask = + 4usize as + u16; + let b3 = + (b3 << + 2usize) + & + mask; + bitfield_unit_val + | b3 + }; + let b4 = + b4 as u32 as u16; + let mask = + 8usize as u16; + let b4 = + (b4 << 3usize) & + mask; + bitfield_unit_val | b4 + }; + let b5 = b5 as u32 as u16; + let mask = 16usize as u16; + let b5 = + (b5 << 4usize) & mask; + bitfield_unit_val | b5 + }; + let b6 = b6 as u32 as u16; + let mask = 32usize as u16; + let b6 = (b6 << 5usize) & mask; + bitfield_unit_val | b6 + }; + let b7 = b7 as u32 as u16; + let mask = 64usize as u16; + let b7 = (b7 << 6usize) & mask; + bitfield_unit_val | b7 + }; + let b8 = b8 as u32 as u16; + let mask = 128usize as u16; + let b8 = (b8 << 7usize) & mask; + bitfield_unit_val | b8 + }; + let b9 = b9 as u32 as u16; + let mask = 256usize as u16; + let b9 = (b9 << 8usize) & mask; + bitfield_unit_val | b9 + }; + let b10 = b10 as u32 as u16; + let mask = 512usize as u16; + let b10 = (b10 << 9usize) & mask; + bitfield_unit_val | b10 + } } #[repr(C)] #[derive(Debug, Default, Copy)] @@ -265,6 +393,22 @@ impl B { unit_field_val |= (val << 31usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(foo: ::std::os::raw::c_uint, + bar: ::std::os::raw::c_uchar) -> u32 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let foo = foo as u32 as u32; + let mask = 2147483647usize as u32; + let foo = (foo << 0usize) & mask; + bitfield_unit_val | foo + }; + let bar = bar as u8 as u32; + let mask = 2147483648usize as u32; + let bar = (bar << 31usize) & mask; + bitfield_unit_val | bar + } } #[repr(C)] #[derive(Debug, Default, Copy)] @@ -329,6 +473,22 @@ impl C { unit_field_val |= (val << 1usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(b1: ::std::os::raw::c_uint, + b2: ::std::os::raw::c_uint) -> u8 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let b1 = b1 as u32 as u8; + let mask = 1usize as u8; + let b1 = (b1 << 0usize) & mask; + bitfield_unit_val | b1 + }; + let b2 = b2 as u32 as u8; + let mask = 2usize as u8; + let b2 = (b2 << 1usize) & mask; + bitfield_unit_val | b2 + } } #[repr(C)] #[derive(Debug, Default, Copy)] @@ -404,6 +564,30 @@ impl Date1 { 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 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let nWeekDay = nWeekDay as u16 as u16; + let mask = 7usize as u16; + let nWeekDay = (nWeekDay << 0usize) & mask; + bitfield_unit_val | nWeekDay + }; + let nMonthDay = nMonthDay as u16 as u16; + let mask = 504usize as u16; + let nMonthDay = (nMonthDay << 3usize) & mask; + bitfield_unit_val | nMonthDay + }; + let nMonth = nMonth as u16 as u16; + let mask = 15872usize as u16; + let nMonth = (nMonth << 9usize) & mask; + bitfield_unit_val | nMonth + } + #[inline] pub fn nYear(&self) -> ::std::os::raw::c_ushort { let mask = 255usize as u8; let unit_field_val: u8 = @@ -421,6 +605,14 @@ impl Date1 { unit_field_val |= (val << 0usize) & mask; self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_2(nYear: ::std::os::raw::c_ushort) -> u8 { + let bitfield_unit_val = { 0 }; + let nYear = nYear as u16 as u8; + let mask = 255usize as u8; + let nYear = (nYear << 0usize) & mask; + bitfield_unit_val | nYear + } } #[repr(C)] #[derive(Debug, Default, Copy)] @@ -501,6 +693,30 @@ impl Date2 { 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 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let nWeekDay = nWeekDay as u16 as u16; + let mask = 7usize as u16; + let nWeekDay = (nWeekDay << 0usize) & mask; + bitfield_unit_val | nWeekDay + }; + let nMonthDay = nMonthDay as u16 as u16; + let mask = 504usize as u16; + let nMonthDay = (nMonthDay << 3usize) & mask; + bitfield_unit_val | nMonthDay + }; + let nMonth = nMonth as u16 as u16; + let mask = 15872usize as u16; + let nMonth = (nMonth << 9usize) & mask; + bitfield_unit_val | nMonth + } + #[inline] pub fn nYear(&self) -> ::std::os::raw::c_ushort { let mask = 255usize as u8; let unit_field_val: u8 = @@ -518,4 +734,12 @@ impl Date2 { unit_field_val |= (val << 0usize) & mask; self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_2(nYear: ::std::os::raw::c_ushort) -> u8 { + let bitfield_unit_val = { 0 }; + let nYear = nYear as u16 as u8; + let mask = 255usize as u8; + let nYear = (nYear << 0usize) & mask; + bitfield_unit_val | nYear + } } diff --git a/tests/expectations/tests/bitfield_method_mangling.rs b/tests/expectations/tests/bitfield_method_mangling.rs index 3ce2be9e27..fc5921f825 100644 --- a/tests/expectations/tests/bitfield_method_mangling.rs +++ b/tests/expectations/tests/bitfield_method_mangling.rs @@ -60,4 +60,20 @@ impl mach_msg_type_descriptor_t { unit_field_val |= (val << 24usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(pad3: ::std::os::raw::c_uint, + type_: ::std::os::raw::c_uint) -> u32 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let pad3 = pad3 as u32 as u32; + let mask = 16777215usize as u32; + let pad3 = (pad3 << 0usize) & mask; + bitfield_unit_val | pad3 + }; + let type_ = type_ as u32 as u32; + let mask = 4278190080usize as u32; + let type_ = (type_ << 24usize) & mask; + bitfield_unit_val | type_ + } } diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs index bc2135cb4c..56c6188a60 100644 --- a/tests/expectations/tests/jsval_layout_opaque.rs +++ b/tests/expectations/tests/jsval_layout_opaque.rs @@ -166,6 +166,21 @@ impl jsval_layout__bindgen_ty_1 { unit_field_val |= (val << 47usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(payload47: u64, tag: JSValueTag) -> u64 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let payload47 = payload47 as u64 as u64; + let mask = 140737488355327usize as u64; + let payload47 = (payload47 << 0usize) & mask; + bitfield_unit_val | payload47 + }; + let tag = tag as u32 as u64; + let mask = 18446603336221196288usize as u64; + let tag = (tag << 47usize) & mask; + bitfield_unit_val | tag + } } #[repr(C)] #[derive(Debug, Default, Copy)] diff --git a/tests/expectations/tests/layout_align.rs b/tests/expectations/tests/layout_align.rs index 54f0119573..24861441cb 100644 --- a/tests/expectations/tests/layout_align.rs +++ b/tests/expectations/tests/layout_align.rs @@ -144,4 +144,27 @@ impl rte_eth_link { unit_field_val |= (val << 2usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(link_duplex: u16, link_autoneg: u16, + link_status: u16) -> u8 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let link_duplex = link_duplex as u16 as u8; + let mask = 1usize as u8; + let link_duplex = (link_duplex << 0usize) & mask; + bitfield_unit_val | link_duplex + }; + let link_autoneg = link_autoneg as u16 as u8; + let mask = 2usize as u8; + let link_autoneg = (link_autoneg << 1usize) & mask; + bitfield_unit_val | link_autoneg + }; + let link_status = link_status as u16 as u8; + let mask = 4usize as u8; + let link_status = (link_status << 2usize) & mask; + bitfield_unit_val | link_status + } } diff --git a/tests/expectations/tests/layout_eth_conf.rs b/tests/expectations/tests/layout_eth_conf.rs index 8068c6a1dc..0fd1392ebb 100644 --- a/tests/expectations/tests/layout_eth_conf.rs +++ b/tests/expectations/tests/layout_eth_conf.rs @@ -281,6 +281,120 @@ impl rte_eth_rxmode { unit_field_val |= (val << 8usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(header_split: u16, hw_ip_checksum: u16, + hw_vlan_filter: u16, hw_vlan_strip: u16, + hw_vlan_extend: u16, jumbo_frame: u16, + hw_strip_crc: u16, enable_scatter: u16, + enable_lro: u16) -> u16 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + 0 + }; + let header_split = + header_split + as + u16 + as + u16; + let mask = + 1usize + as + u16; + let header_split = + (header_split + << + 0usize) + & + mask; + bitfield_unit_val + | + header_split + }; + let hw_ip_checksum = + hw_ip_checksum + as u16 + as + u16; + let mask = + 2usize as + u16; + let hw_ip_checksum = + (hw_ip_checksum + << + 1usize) + & + mask; + bitfield_unit_val + | + hw_ip_checksum + }; + let hw_vlan_filter = + hw_vlan_filter as + u16 as u16; + let mask = + 4usize as u16; + let hw_vlan_filter = + (hw_vlan_filter << + 2usize) & + mask; + bitfield_unit_val | + hw_vlan_filter + }; + let hw_vlan_strip = + hw_vlan_strip as u16 as + u16; + let mask = 8usize as u16; + let hw_vlan_strip = + (hw_vlan_strip << 3usize) + & mask; + bitfield_unit_val | + hw_vlan_strip + }; + let hw_vlan_extend = + hw_vlan_extend as u16 as u16; + let mask = 16usize as u16; + let hw_vlan_extend = + (hw_vlan_extend << 4usize) & mask; + bitfield_unit_val | hw_vlan_extend + }; + let jumbo_frame = jumbo_frame as u16 as u16; + let mask = 32usize as u16; + let jumbo_frame = + (jumbo_frame << 5usize) & mask; + bitfield_unit_val | jumbo_frame + }; + let hw_strip_crc = hw_strip_crc as u16 as u16; + let mask = 64usize as u16; + let hw_strip_crc = (hw_strip_crc << 6usize) & mask; + bitfield_unit_val | hw_strip_crc + }; + let enable_scatter = enable_scatter as u16 as u16; + let mask = 128usize as u16; + let enable_scatter = (enable_scatter << 7usize) & mask; + bitfield_unit_val | enable_scatter + }; + let enable_lro = enable_lro as u16 as u16; + let mask = 256usize as u16; + let enable_lro = (enable_lro << 8usize) & mask; + bitfield_unit_val | enable_lro + } } #[repr(u32)] /** @@ -384,6 +498,34 @@ impl rte_eth_txmode { unit_field_val |= (val << 2usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(hw_vlan_reject_tagged: u8, + hw_vlan_reject_untagged: u8, + hw_vlan_insert_pvid: u8) -> u8 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let hw_vlan_reject_tagged = + hw_vlan_reject_tagged as u8 as u8; + let mask = 1usize as u8; + let hw_vlan_reject_tagged = + (hw_vlan_reject_tagged << 0usize) & mask; + bitfield_unit_val | hw_vlan_reject_tagged + }; + let hw_vlan_reject_untagged = + hw_vlan_reject_untagged as u8 as u8; + let mask = 2usize as u8; + let hw_vlan_reject_untagged = + (hw_vlan_reject_untagged << 1usize) & mask; + bitfield_unit_val | hw_vlan_reject_untagged + }; + let hw_vlan_insert_pvid = hw_vlan_insert_pvid as u8 as u8; + let mask = 4usize as u8; + let hw_vlan_insert_pvid = (hw_vlan_insert_pvid << 2usize) & mask; + bitfield_unit_val | hw_vlan_insert_pvid + } } /** * A structure used to configure the Receive Side Scaling (RSS) feature diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs index e60ebb3022..d35464d611 100644 --- a/tests/expectations/tests/layout_mbuf.rs +++ b/tests/expectations/tests/layout_mbuf.rs @@ -302,6 +302,70 @@ impl rte_mbuf__bindgen_ty_2__bindgen_ty_1 { unit_field_val |= (val << 24usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(l2_type: u32, l3_type: u32, l4_type: u32, + tun_type: u32, inner_l2_type: u32, + inner_l3_type: u32, inner_l4_type: u32) -> u32 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { 0 }; + let l2_type = + l2_type as u32 as + u32; + let mask = + 15usize as u32; + let l2_type = + (l2_type << + 0usize) & + mask; + bitfield_unit_val | + l2_type + }; + let l3_type = + l3_type as u32 as u32; + let mask = 240usize as u32; + let l3_type = + (l3_type << 4usize) & + mask; + bitfield_unit_val | l3_type + }; + let l4_type = l4_type as u32 as u32; + let mask = 3840usize as u32; + let l4_type = + (l4_type << 8usize) & mask; + bitfield_unit_val | l4_type + }; + let tun_type = tun_type as u32 as u32; + let mask = 61440usize as u32; + let tun_type = (tun_type << 12usize) & mask; + bitfield_unit_val | tun_type + }; + let inner_l2_type = inner_l2_type as u32 as u32; + let mask = 983040usize as u32; + let inner_l2_type = (inner_l2_type << 16usize) & mask; + bitfield_unit_val | inner_l2_type + }; + let inner_l3_type = inner_l3_type as u32 as u32; + let mask = 15728640usize as u32; + let inner_l3_type = (inner_l3_type << 20usize) & mask; + bitfield_unit_val | inner_l3_type + }; + let inner_l4_type = inner_l4_type as u32 as u32; + let mask = 251658240usize as u32; + let inner_l4_type = (inner_l4_type << 24usize) & mask; + bitfield_unit_val | inner_l4_type + } } #[test] fn bindgen_test_layout_rte_mbuf__bindgen_ty_2() { @@ -662,6 +726,54 @@ impl rte_mbuf__bindgen_ty_5__bindgen_ty_1 { unit_field_val |= (val << 49usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(l2_len: u64, l3_len: u64, l4_len: u64, + tso_segsz: u64, outer_l3_len: u64, + outer_l2_len: u64) -> u64 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let l2_len = + l2_len as u64 as u64; + let mask = 127usize as u64; + let l2_len = + (l2_len << 0usize) & mask; + bitfield_unit_val | l2_len + }; + let l3_len = l3_len as u64 as u64; + let mask = 65408usize as u64; + let l3_len = + (l3_len << 7usize) & mask; + bitfield_unit_val | l3_len + }; + let l4_len = l4_len as u64 as u64; + let mask = 16711680usize as u64; + let l4_len = (l4_len << 16usize) & mask; + bitfield_unit_val | l4_len + }; + let tso_segsz = tso_segsz as u64 as u64; + let mask = 1099494850560usize as u64; + let tso_segsz = (tso_segsz << 24usize) & mask; + bitfield_unit_val | tso_segsz + }; + let outer_l3_len = outer_l3_len as u64 as u64; + let mask = 561850441793536usize as u64; + let outer_l3_len = (outer_l3_len << 40usize) & mask; + bitfield_unit_val | outer_l3_len + }; + let outer_l2_len = outer_l2_len as u64 as u64; + let mask = 71494644084506624usize as u64; + let outer_l2_len = (outer_l2_len << 49usize) & mask; + bitfield_unit_val | outer_l2_len + } } #[test] fn bindgen_test_layout_rte_mbuf__bindgen_ty_5() { diff --git a/tests/expectations/tests/only_bitfields.rs b/tests/expectations/tests/only_bitfields.rs index b32333f232..238c0eaf6b 100644 --- a/tests/expectations/tests/only_bitfields.rs +++ b/tests/expectations/tests/only_bitfields.rs @@ -57,4 +57,19 @@ impl C { unit_field_val |= (val << 1usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(a: bool, b: bool) -> u8 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let a = a as u8 as u8; + let mask = 1usize as u8; + let a = (a << 0usize) & mask; + bitfield_unit_val | a + }; + let b = b as u8 as u8; + let mask = 254usize as u8; + let b = (b << 1usize) & mask; + bitfield_unit_val | b + } } diff --git a/tests/expectations/tests/struct_with_bitfields.rs b/tests/expectations/tests/struct_with_bitfields.rs index d523479d72..24edb34bfb 100644 --- a/tests/expectations/tests/struct_with_bitfields.rs +++ b/tests/expectations/tests/struct_with_bitfields.rs @@ -101,6 +101,38 @@ impl bitfield { self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] + pub fn new_bitfield_1(a: ::std::os::raw::c_ushort, + b: ::std::os::raw::c_ushort, + c: ::std::os::raw::c_ushort, + d: ::std::os::raw::c_ushort) -> u8 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let a = a as u16 as u8; + let mask = 1usize as u8; + let a = (a << 0usize) & mask; + bitfield_unit_val | a + }; + let b = b as u16 as u8; + let mask = 2usize as u8; + let b = (b << 1usize) & mask; + bitfield_unit_val | b + }; + let c = c as u16 as u8; + let mask = 4usize as u8; + let c = (c << 2usize) & mask; + bitfield_unit_val | c + }; + let d = d as u16 as u8; + let mask = 192usize as u8; + let d = (d << 6usize) & mask; + bitfield_unit_val | d + } + #[inline] pub fn f(&self) -> ::std::os::raw::c_uint { let mask = 3usize as u8; let unit_field_val: u8 = @@ -119,6 +151,14 @@ impl bitfield { self._bitfield_2 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] + pub fn new_bitfield_2(f: ::std::os::raw::c_uint) -> u8 { + let bitfield_unit_val = { 0 }; + let f = f as u32 as u8; + let mask = 3usize as u8; + let f = (f << 0usize) & mask; + bitfield_unit_val | f + } + #[inline] pub fn g(&self) -> ::std::os::raw::c_uint { let mask = 4294967295usize as u32; let unit_field_val: u32 = @@ -136,4 +176,12 @@ impl bitfield { unit_field_val |= (val << 0usize) & mask; self._bitfield_3 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_3(g: ::std::os::raw::c_uint) -> u32 { + let bitfield_unit_val = { 0 }; + let g = g as u32 as u32; + let mask = 4294967295usize as u32; + let g = (g << 0usize) & mask; + bitfield_unit_val | g + } } diff --git a/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/tests/expectations/tests/union_with_anon_struct_bitfield.rs index 49c6d184db..b5abd47f12 100644 --- a/tests/expectations/tests/union_with_anon_struct_bitfield.rs +++ b/tests/expectations/tests/union_with_anon_struct_bitfield.rs @@ -88,6 +88,22 @@ impl foo__bindgen_ty_1 { unit_field_val |= (val << 7usize) & mask; self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } + #[inline] + pub fn new_bitfield_1(b: ::std::os::raw::c_int, c: ::std::os::raw::c_int) + -> u32 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let b = b as u32 as u32; + let mask = 127usize as u32; + let b = (b << 0usize) & mask; + bitfield_unit_val | b + }; + let c = c as u32 as u32; + let mask = 4294967168usize as u32; + let c = (c << 7usize) & mask; + bitfield_unit_val | c + } } #[test] fn bindgen_test_layout_foo() { diff --git a/tests/expectations/tests/weird_bitfields.rs b/tests/expectations/tests/weird_bitfields.rs index 89175acfa9..060d400bae 100644 --- a/tests/expectations/tests/weird_bitfields.rs +++ b/tests/expectations/tests/weird_bitfields.rs @@ -142,6 +142,22 @@ impl Weird { self._bitfield_1 = unsafe { ::std::mem::transmute(unit_field_val) }; } #[inline] + pub fn new_bitfield_1(bitTest: ::std::os::raw::c_uint, + bitTest2: ::std::os::raw::c_uint) -> u32 { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let bitTest = bitTest as u32 as u32; + let mask = 65535usize as u32; + let bitTest = (bitTest << 0usize) & mask; + bitfield_unit_val | bitTest + }; + let bitTest2 = bitTest2 as u32 as u32; + let mask = 2147418112usize as u32; + let bitTest2 = (bitTest2 << 16usize) & mask; + bitfield_unit_val | bitTest2 + } + #[inline] pub fn mFillOpacitySource(&self) -> nsStyleSVGOpacitySource { let mask = 7usize as u8; let unit_field_val: u8 = @@ -214,6 +230,46 @@ impl Weird { 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 { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = + { + let bitfield_unit_val = { 0 }; + let mFillOpacitySource = + mFillOpacitySource as u32 as u8; + let mask = 7usize as u8; + let mFillOpacitySource = + (mFillOpacitySource << 0usize) & mask; + bitfield_unit_val | mFillOpacitySource + }; + let mStrokeOpacitySource = + mStrokeOpacitySource as u32 as u8; + let mask = 56usize as u8; + let mStrokeOpacitySource = + (mStrokeOpacitySource << 3usize) & mask; + bitfield_unit_val | mStrokeOpacitySource + }; + let mStrokeDasharrayFromObject = + mStrokeDasharrayFromObject as u8 as u8; + let mask = 64usize as u8; + let mStrokeDasharrayFromObject = + (mStrokeDasharrayFromObject << 6usize) & mask; + bitfield_unit_val | mStrokeDasharrayFromObject + }; + let mStrokeDashoffsetFromObject = + mStrokeDashoffsetFromObject as u8 as u8; + let mask = 128usize as u8; + let mStrokeDashoffsetFromObject = + (mStrokeDashoffsetFromObject << 7usize) & mask; + bitfield_unit_val | mStrokeDashoffsetFromObject + } + #[inline] pub fn mStrokeWidthFromObject(&self) -> bool { let mask = 1usize as u8; let unit_field_val: u8 = @@ -231,4 +287,13 @@ impl Weird { 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 { + let bitfield_unit_val = { 0 }; + let mStrokeWidthFromObject = mStrokeWidthFromObject as u8 as u8; + let mask = 1usize as u8; + let mStrokeWidthFromObject = + (mStrokeWidthFromObject << 0usize) & mask; + bitfield_unit_val | mStrokeWidthFromObject + } } From 15b72b785af3094788b6c60841a39962db11ffa9 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 19 May 2017 14:36:59 -0700 Subject: [PATCH 2/2] Flatten nesting in Bitfield::extend_ctor_impl This commit flattens the nesting in `Bitfield::extend_ctor_impl`, as requested in review, because it was getting pretty deep. Should be easier to read now. --- src/codegen/mod.rs | 93 ++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 28cddb5d3c..06e3a4f6a8 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1070,55 +1070,58 @@ impl Bitfield { ctor_name: &ast::Ident, unit_field_int_ty: &P) -> P { - match ctor_impl.unwrap().node { - ast::ItemKind::Impl(_, _, _, _, _, ref items) => { - assert_eq!(items.len(), 1); + let items = match ctor_impl.unwrap().node { + ast::ItemKind::Impl(_, _, _, _, _, items) => { + items + } + _ => unreachable!(), + }; - match items.get(0).unwrap().node { - ast::ImplItemKind::Method(ref sig, ref body) => { - let params = sig.decl.clone().unwrap().inputs; - let param_name = bitfield_getter_name(ctx, parent, self.name()); - - let bitfield_ty_item = ctx.resolve_item(self.ty()); - let bitfield_ty = bitfield_ty_item.expect_type(); - let bitfield_ty_layout = bitfield_ty.layout(ctx) - .expect("Bitfield without layout? Gah!"); - let bitfield_int_ty = BlobTyBuilder::new(bitfield_ty_layout).build(); - let bitfield_ty = bitfield_ty - .to_rust_ty_or_opaque(ctx, bitfield_ty_item); - - let offset = self.offset_into_unit(); - let mask = self.mask(); - - // If we're generating unstable Rust, add the const. - let fn_prefix = if ctx.options().unstable_rust { - quote_tokens!(ctx.ext_cx(), pub const fn) - } else { - quote_tokens!(ctx.ext_cx(), pub fn) - }; + assert_eq!(items.len(), 1); + let (sig, body) = match items[0].node { + ast::ImplItemKind::Method(ref sig, ref body) => { + (sig, body) + } + _ => unreachable!(), + }; - quote_item!( - ctx.ext_cx(), - impl XxxUnused { - #[inline] - $fn_prefix $ctor_name($params $param_name : $bitfield_ty) - -> $unit_field_int_ty { - let bitfield_unit_val = $body; - let $param_name = $param_name - as $bitfield_int_ty - as $unit_field_int_ty; - let mask = $mask as $unit_field_int_ty; - let $param_name = ($param_name << $offset) & mask; - bitfield_unit_val | $param_name - } - } - ).unwrap() - } - _ => unreachable!(), + let params = sig.decl.clone().unwrap().inputs; + let param_name = bitfield_getter_name(ctx, parent, self.name()); + + let bitfield_ty_item = ctx.resolve_item(self.ty()); + let bitfield_ty = bitfield_ty_item.expect_type(); + let bitfield_ty_layout = bitfield_ty.layout(ctx) + .expect("Bitfield without layout? Gah!"); + let bitfield_int_ty = BlobTyBuilder::new(bitfield_ty_layout).build(); + let bitfield_ty = bitfield_ty + .to_rust_ty_or_opaque(ctx, bitfield_ty_item); + + let offset = self.offset_into_unit(); + let mask = self.mask(); + + // If we're generating unstable Rust, add the const. + let fn_prefix = if ctx.options().unstable_rust { + quote_tokens!(ctx.ext_cx(), pub const fn) + } else { + quote_tokens!(ctx.ext_cx(), pub fn) + }; + + quote_item!( + ctx.ext_cx(), + impl XxxUnused { + #[inline] + $fn_prefix $ctor_name($params $param_name : $bitfield_ty) + -> $unit_field_int_ty { + let bitfield_unit_val = $body; + let $param_name = $param_name + as $bitfield_int_ty + as $unit_field_int_ty; + let mask = $mask as $unit_field_int_ty; + let $param_name = ($param_name << $offset) & mask; + bitfield_unit_val | $param_name } } - _ => unreachable!(), - } + ).unwrap() } }