summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/mod.rs35
-rw-r--r--src/ir/comp.rs18
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,