diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 722167a4175a0f3c3912a6ef45ca013a04a675d4..b5d339dd9a7d58b5dfcb7406a52bb98d3edfffc2 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -387,7 +387,7 @@ fn intrinsic_with_overflow( }; let overflowed = self.intrinsic_overflowing(op, left, right, dest)?; - let offset = tup_layout.field_offset(1).bytes() as isize; + let offset = tup_layout.offsets[1].bytes() as isize; self.memory.write_bool(dest.offset(offset), overflowed) } @@ -460,8 +460,7 @@ fn eval_rvalue_into_lvalue( use rustc::ty::layout::Layout::*; match *dest_layout { Univariant { ref variant, .. } => { - let offsets = iter::once(0) - .chain(variant.offset_after_field.iter().map(|s| s.bytes())); + let offsets = variant.offsets.iter().map(|s| s.bytes()); self.assign_fields(dest, offsets, operands)?; } @@ -478,11 +477,14 @@ fn eval_rvalue_into_lvalue( if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { let discr_val = adt_def.variants[variant].disr_val.to_u64_unchecked(); let discr_size = discr.size().bytes() as usize; - self.memory.write_uint(dest, discr_val, discr_size)?; + let discr_offset = variants[variant].offsets[0].bytes() as isize; + let discr_dest = dest.offset(discr_offset); + self.memory.write_uint(discr_dest, discr_val, discr_size)?; - let offsets = variants[variant].offset_after_field.iter() + // Don't include the first offset; it's for the discriminant. + let field_offsets = variants[variant].offsets.iter().skip(1) .map(|s| s.bytes()); - self.assign_fields(dest, offsets, operands)?; + self.assign_fields(dest, field_offsets, operands)?; } else { bug!("tried to assign {:?} to Layout::General", kind); } @@ -508,8 +510,7 @@ fn eval_rvalue_into_lvalue( StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield } => { if let mir::AggregateKind::Adt(_, variant, _, _) = *kind { if nndiscr == variant as u64 { - let offsets = iter::once(0) - .chain(nonnull.offset_after_field.iter().map(|s| s.bytes())); + let offsets = nonnull.offsets.iter().map(|s| s.bytes()); try!(self.assign_fields(dest, offsets, operands)); } else { for operand in operands { @@ -715,7 +716,7 @@ fn get_field_offset(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<'tcx, use rustc::ty::layout::Layout::*; match *layout { Univariant { ref variant, .. } => { - Ok(variant.field_offset(field_index)) + Ok(variant.offsets[field_index]) } FatPointer { .. } => { let bytes = layout::FAT_PTR_ADDR * self.memory.pointer_size(); @@ -801,11 +802,11 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue use rustc::ty::layout::Layout::*; let field = field.index(); let offset = match *base_layout { - Univariant { ref variant, .. } => variant.field_offset(field), + Univariant { ref variant, .. } => variant.offsets[field], General { ref variants, .. } => { if let LvalueExtra::DowncastVariant(variant_idx) = base.extra { // +1 for the discriminant, which is field 0 - variants[variant_idx].field_offset(field + 1) + variants[variant_idx].offsets[field + 1] } else { bug!("field access on enum had no variant index"); } @@ -814,7 +815,9 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue assert_eq!(field.index(), 0); return Ok(base); } - StructWrappedNullablePointer { ref nonnull, .. } => nonnull.field_offset(field), + StructWrappedNullablePointer { ref nonnull, .. } => { + nonnull.offsets[field] + } _ => bug!("field access on non-product type: {:?}", base_layout), }; @@ -1289,17 +1292,3 @@ fn size(self) -> Size { } } } - -trait StructExt { - fn field_offset(&self, index: usize) -> Size; -} - -impl StructExt for layout::Struct { - fn field_offset(&self, index: usize) -> Size { - if index == 0 { - Size::from_bytes(0) - } else { - self.offset_after_field[index - 1] - } - } -} diff --git a/src/interpreter/terminator/intrinsics.rs b/src/interpreter/terminator/intrinsics.rs index 817ded7273d61bf935e30fe09126381fb120300c..31e337924adaa8748da34e8d836bb1f4a3e96c09 100644 --- a/src/interpreter/terminator/intrinsics.rs +++ b/src/interpreter/terminator/intrinsics.rs @@ -246,20 +246,12 @@ fn size_and_align_of_dst( let layout = self.type_layout(ty); debug!("DST {} layout: {:?}", ty, layout); - // Returns size in bytes of all fields except the last one - // (we will be recursing on the last one). - fn local_prefix_bytes(variant: &ty::layout::Struct) -> u64 { - let fields = variant.offset_after_field.len(); - if fields > 1 { - variant.offset_after_field[fields - 2].bytes() - } else { - 0 - } - } - let (sized_size, sized_align) = match *layout { ty::layout::Layout::Univariant { ref variant, .. } => { - (local_prefix_bytes(variant), variant.align.abi()) + // The offset of the start of the last field gives the size of the + // sized part of the type. + let size = variant.offsets.last().map_or(0, |f| f.bytes()); + (size, variant.align.abi()) } _ => { bug!("size_and_align_of_dst: expcted Univariant for `{}`, found {:#?}", diff --git a/src/interpreter/terminator/mod.rs b/src/interpreter/terminator/mod.rs index e0e6e3996c4006480209f6baac73ba9f67061a14..5c9123ba91e9c8a81aafb1bc33ac13b0841e6f11 100644 --- a/src/interpreter/terminator/mod.rs +++ b/src/interpreter/terminator/mod.rs @@ -5,7 +5,6 @@ use rustc::ty::layout::Layout; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, BareFnTy}; -use std::iter; use std::rc::Rc; use syntax::codemap::{DUMMY_SP, Span}; use syntax::{ast, attr}; @@ -343,9 +342,7 @@ fn unpack_fn_args(&self, args: &mut Vec<(Value, Ty<'tcx>)>) { match (&last_ty.sty, last_layout) { (&ty::TyTuple(fields), &Layout::Univariant { ref variant, .. }) => { - let offsets = iter::once(0) - .chain(variant.offset_after_field.iter() - .map(|s| s.bytes())); + let offsets = variant.offsets.iter().map(|s| s.bytes()); let last_ptr = match last { Value::ByRef(ptr) => ptr, _ => bug!("rust-call ABI tuple argument wasn't Value::ByRef"),