diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-06-19 09:50:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-19 09:50:51 -0700 |
commit | 77d6962c1af3970cb6bdd4a07e4085f33152f787 (patch) | |
tree | a749a736926dc62da9ef5f913fa19894ae5588f6 /src | |
parent | b08b59a7d03a5b9b408f19c18efc38134d6ff119 (diff) | |
parent | 700a3ea249f1f82abe7ed4be98359aff615d13e1 (diff) |
Auto merge of #762 - emilio:much-brokenness, r=fitzgen
Moar bitfield fixes
Now with the right branch name. See individual commits for details.
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen/mod.rs | 35 | ||||
-rw-r--r-- | src/ir/comp.rs | 18 |
2 files changed, 32 insertions, 21 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 8d979dce..bd5b1f3b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1113,9 +1113,9 @@ impl Bitfield { #[inline] $fn_prefix $ctor_name($params $param_name : $bitfield_ty) -> $unit_field_int_ty { - ($body | - (($param_name as $bitfield_int_ty as $unit_field_int_ty) << $offset) & - ($mask as $unit_field_int_ty)) + ($body | + (($param_name as $bitfield_int_ty as $unit_field_int_ty) << $offset) & + ($mask as $unit_field_int_ty)) } } ).unwrap() @@ -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()); @@ -1273,7 +1279,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 = self.mask(); + let mask = self.mask(); let impl_item = quote_item!( ctx.ext_cx(), @@ -1282,7 +1288,9 @@ impl<'a> FieldCodegen<'a> for Bitfield { pub fn $getter_name(&self) -> $bitfield_ty { let mask = $mask as $unit_field_int_ty; let unit_field_val: $unit_field_int_ty = unsafe { - ::$prefix::mem::transmute(self.$unit_field_ident) + ::$prefix::ptr::read_unaligned( + &self.$unit_field_ident as *const _ as *const $unit_field_int_ty + ) }; let val = (unit_field_val & mask) >> $offset; unsafe { @@ -1296,14 +1304,19 @@ impl<'a> FieldCodegen<'a> for Bitfield { let val = val as $bitfield_int_ty as $unit_field_int_ty; let mut unit_field_val: $unit_field_int_ty = unsafe { - ::$prefix::mem::transmute(self.$unit_field_ident) + ::$prefix::ptr::read_unaligned( + &self.$unit_field_ident as *const _ as *const $unit_field_int_ty) }; + unit_field_val &= !mask; unit_field_val |= (val << $offset) & mask; - self.$unit_field_ident = unsafe { - ::$prefix::mem::transmute(unit_field_val) - }; + unsafe { + ::$prefix::ptr::write_unaligned( + &mut self.$unit_field_ident as *mut _ as *mut $unit_field_int_ty, + unit_field_val + ); + } } } ).unwrap(); diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 171f130c..315d342a 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -293,18 +293,15 @@ impl Bitfield { /// Get the mask value that when &'ed with this bitfield's allocation unit /// produces this bitfield's value. - /// - /// TODO(emilio): This should probably use the target's word size, and what - /// about bitfields that are bigger than that? - pub fn mask(&self) -> usize { + pub fn mask(&self) -> u64 { use std::mem; - use std::usize; + use std::u64; let unoffseted_mask = - if self.width() as usize == mem::size_of::<usize>() * 8 { - usize::MAX + if self.width() as u64 == mem::size_of::<u64>() as u64 * 8 { + u64::MAX } else { - ((1usize << self.width()) - 1usize) + ((1u64 << self.width()) - 1u64) }; unoffseted_mask << self.offset_into_unit() @@ -488,8 +485,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, |