about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-12-16 23:34:43 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-12-17 16:34:54 +0200
commit08646c6c2c167d4c04897660dc524623d349bdb1 (patch)
tree4de5db7e0a7e7bf0f2c38e5e00d81c5d7bd84867
parentff080d389dac079b3c7c8a7ad88b99660b05afa0 (diff)
downloadrust-08646c6c2c167d4c04897660dc524623d349bdb1.tar.gz
rust-08646c6c2c167d4c04897660dc524623d349bdb1.zip
miri: use separate Pointer and Align instead of PtrAndAlign.
-rw-r--r--src/librustc/mir/interpret/mod.rs2
-rw-r--r--src/librustc/mir/interpret/value.rs20
-rw-r--r--src/librustc_mir/interpret/const_eval.rs98
-rw-r--r--src/librustc_mir/interpret/eval_context.rs58
-rw-r--r--src/librustc_mir/interpret/memory.rs14
-rw-r--r--src/librustc_mir/interpret/place.rs79
-rw-r--r--src/librustc_mir/interpret/terminator/drop.rs9
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs10
8 files changed, 113 insertions, 177 deletions
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index c5d2ec1668c..6785e06ae35 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -10,7 +10,7 @@ mod value;
 
 pub use self::error::{EvalError, EvalResult, EvalErrorKind};
 
-pub use self::value::{PrimVal, PrimValKind, Value, Pointer, PtrAndAlign, bytes_to_f32, bytes_to_f64};
+pub use self::value::{PrimVal, PrimValKind, Value, Pointer, bytes_to_f32, bytes_to_f64};
 
 use std::collections::BTreeMap;
 use ty::layout::HasDataLayout;
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 10da5e7843b..0bfff2a80e6 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -6,24 +6,6 @@ use super::{EvalResult, MemoryPointer, PointerArithmetic};
 use syntax::ast::FloatTy;
 use rustc_const_math::ConstFloat;
 
-#[derive(Copy, Clone, Debug)]
-pub struct PtrAndAlign {
-    pub ptr: Pointer,
-    pub align: Align,
-}
-
-impl PtrAndAlign {
-    pub fn to_ptr<'tcx>(self) -> EvalResult<'tcx, MemoryPointer> {
-        self.ptr.to_ptr()
-    }
-    pub fn offset<'tcx, C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
-        Ok(PtrAndAlign {
-            ptr: self.ptr.offset(i, cx)?,
-            align: self.align,
-        })
-    }
-}
-
 pub fn bytes_to_f32(bits: u128) -> ConstFloat {
     ConstFloat {
         bits,
@@ -49,7 +31,7 @@ pub fn bytes_to_f64(bits: u128) -> ConstFloat {
 /// operations and fat pointers. This idea was taken from rustc's trans.
 #[derive(Clone, Copy, Debug)]
 pub enum Value {
-    ByRef(PtrAndAlign),
+    ByRef(Pointer, Align),
     ByVal(PrimVal),
     ByValPair(PrimVal, PrimVal),
 }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 4d9f55543e7..15840bffbde 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -12,8 +12,8 @@ use rustc_data_structures::indexed_vec::Idx;
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
 
-use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal, PtrAndAlign};
-use super::{Place, PlaceExtra, EvalContext, StackPopCleanup, ValTy, HasMemory};
+use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal};
+use super::{Place, EvalContext, StackPopCleanup, ValTy};
 
 use rustc_const_math::ConstInt;
 
@@ -357,11 +357,9 @@ pub fn const_eval_provider<'a, 'tcx>(
             (_, Err(err)) => Err(err),
             (Ok((miri_val, miri_ty)), Ok(ctfe)) => {
                 let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
-                let miri_ptr = PtrAndAlign {
-                    ptr: miri_val,
-                    align: ecx.layout_of(miri_ty).unwrap().align
-                };
-                check_ctfe_against_miri(&mut ecx, miri_ptr, miri_ty, ctfe.val);
+                let layout = ecx.layout_of(miri_ty).unwrap();
+                let miri_place = Place::from_primval_ptr(miri_val, layout.align);
+                check_ctfe_against_miri(&mut ecx, miri_place, miri_ty, ctfe.val);
                 Ok(ctfe)
             }
         }
@@ -372,19 +370,20 @@ pub fn const_eval_provider<'a, 'tcx>(
 
 fn check_ctfe_against_miri<'a, 'tcx>(
     ecx: &mut EvalContext<'a, 'tcx, CompileTimeEvaluator>,
-    miri_val: PtrAndAlign,
+    miri_place: Place,
     miri_ty: Ty<'tcx>,
     ctfe: ConstVal<'tcx>,
 ) {
     use rustc::middle::const_val::ConstAggregate::*;
     use rustc_const_math::ConstFloat;
     use rustc::ty::TypeVariants::*;
+    let miri_val = ValTy {
+        value: ecx.read_place(miri_place).unwrap(),
+        ty: miri_ty
+    };
     match miri_ty.sty {
         TyInt(int_ty) => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
-            let prim = get_prim(ecx, value);
+            let prim = get_prim(ecx, miri_val);
             let c = ConstInt::new_signed_truncating(prim as i128,
                                                     int_ty,
                                                     ecx.tcx.sess.target.isize_ty);
@@ -392,10 +391,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             assert_eq!(c, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", c, ctfe);
         },
         TyUint(uint_ty) => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
-            let prim = get_prim(ecx, value);
+            let prim = get_prim(ecx, miri_val);
             let c = ConstInt::new_unsigned_truncating(prim,
                                                      uint_ty,
                                                      ecx.tcx.sess.target.usize_ty);
@@ -403,18 +399,12 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             assert_eq!(c, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", c, ctfe);
         },
         TyFloat(ty) => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
-            let prim = get_prim(ecx, value);
+            let prim = get_prim(ecx, miri_val);
             let f = ConstVal::Float(ConstFloat { bits: prim, ty });
             assert_eq!(f, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", f, ctfe);
         },
         TyBool => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
-            let bits = get_prim(ecx, value);
+            let bits = get_prim(ecx, miri_val);
             if bits > 1 {
                 bug!("miri evaluated to {}, but expected a bool {:?}", bits, ctfe);
             }
@@ -422,10 +412,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             assert_eq!(b, ctfe, "miri evaluated to {:?}, but ctfe yielded {:?}", b, ctfe);
         },
         TyChar => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
-            let bits = get_prim(ecx, value);
+            let bits = get_prim(ecx, miri_val);
             if let Some(cm) = ::std::char::from_u32(bits as u32) {
                 assert_eq!(
                     ConstVal::Char(cm), ctfe,
@@ -436,10 +423,8 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             }
         },
         TyStr => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
-            if let Ok(Some(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len)))) = value {
+            let value = ecx.follow_by_ref_value(miri_val.value, miri_val.ty);
+            if let Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::Bytes(len))) = value {
                 let bytes = ecx
                     .memory
                     .read_bytes(ptr.into(), len as u64)
@@ -463,7 +448,6 @@ fn check_ctfe_against_miri<'a, 'tcx>(
         },
         TyArray(elem_ty, n) => {
             let n = n.val.to_const_int().unwrap().to_u64().unwrap();
-            let size = ecx.layout_of(elem_ty).unwrap().size.bytes();
             let vec: Vec<(ConstVal, Ty<'tcx>)> = match ctfe {
                 ConstVal::ByteStr(arr) => arr.data.iter().map(|&b| {
                     (ConstVal::Integral(ConstInt::U8(b)), ecx.tcx.types.u8)
@@ -476,10 +460,12 @@ fn check_ctfe_against_miri<'a, 'tcx>(
                 },
                 _ => bug!("miri produced {:?}, but ctfe yielded {:?}", miri_ty, ctfe),
             };
+            let layout = ecx.layout_of(miri_ty).unwrap();
             for (i, elem) in vec.into_iter().enumerate() {
                 assert!((i as u64) < n);
-                let ptr = miri_val.offset(size * i as u64, &ecx).unwrap();
-                check_ctfe_against_miri(ecx, ptr, elem_ty, elem.0);
+                let (field_place, _) =
+                    ecx.place_field(miri_place, Field::new(i), layout).unwrap();
+                check_ctfe_against_miri(ecx, field_place, elem_ty, elem.0);
             }
         },
         TyTuple(..) => {
@@ -489,22 +475,22 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             };
             let layout = ecx.layout_of(miri_ty).unwrap();
             for (i, elem) in vec.into_iter().enumerate() {
-                let offset = layout.fields.offset(i);
-                let ptr = miri_val.offset(offset.bytes(), &ecx).unwrap();
-                check_ctfe_against_miri(ecx, ptr, elem.ty, elem.val);
+                let (field_place, _) =
+                    ecx.place_field(miri_place, Field::new(i), layout).unwrap();
+                check_ctfe_against_miri(ecx, field_place, elem.ty, elem.val);
             }
         },
         TyAdt(def, _) => {
-            let (struct_variant, extra) = if def.is_enum() {
-                let discr = ecx.read_discriminant_value(
-                    Place::Ptr { ptr: miri_val, extra: PlaceExtra::None },
-                    miri_ty).unwrap();
+            let mut miri_place = miri_place;
+            let struct_variant = if def.is_enum() {
+                let discr = ecx.read_discriminant_value(miri_place, miri_ty).unwrap();
                 let variant = def.discriminants(ecx.tcx).position(|variant_discr| {
                     variant_discr.to_u128_unchecked() == discr
                 }).expect("miri produced invalid enum discriminant");
-                (&def.variants[variant], PlaceExtra::DowncastVariant(variant))
+                miri_place = ecx.place_downcast(miri_place, variant).unwrap();
+                &def.variants[variant]
             } else {
-                (def.struct_variant(), PlaceExtra::None)
+                def.struct_variant()
             };
             let vec = match ctfe {
                 ConstVal::Aggregate(Struct(v)) => v,
@@ -518,12 +504,9 @@ fn check_ctfe_against_miri<'a, 'tcx>(
             let layout = ecx.layout_of(miri_ty).unwrap();
             for &(name, elem) in vec.into_iter() {
                 let field = struct_variant.fields.iter().position(|f| f.name == name).unwrap();
-                let (place, _) = ecx.place_field(
-                    Place::Ptr { ptr: miri_val, extra },
-                    Field::new(field),
-                    layout,
-                ).unwrap();
-                check_ctfe_against_miri(ecx, place.to_ptr_align(), elem.ty, elem.val);
+                let (field_place, _) =
+                    ecx.place_field(miri_place, Field::new(field), layout).unwrap();
+                check_ctfe_against_miri(ecx, field_place, elem.ty, elem.val);
             }
         },
         TySlice(_) => bug!("miri produced a slice?"),
@@ -543,11 +526,9 @@ fn check_ctfe_against_miri<'a, 'tcx>(
         // should be fine
         TyFnDef(..) => {}
         TyFnPtr(_) => {
-            let value = ecx.read_with_align(miri_val.align, |ectx| {
-                ectx.try_read_value(miri_val.ptr, miri_ty)
-            });
+            let value = ecx.value_to_primval(miri_val);
             let ptr = match value {
-                Ok(Some(Value::ByVal(PrimVal::Ptr(ptr)))) => ptr,
+                Ok(PrimVal::Ptr(ptr)) => ptr,
                 value => bug!("expected fn ptr, got {:?}", value),
             };
             let inst = ecx.memory.get_fn(ptr).unwrap();
@@ -569,13 +550,10 @@ fn check_ctfe_against_miri<'a, 'tcx>(
 
 fn get_prim<'a, 'tcx>(
     ecx: &mut EvalContext<'a, 'tcx, CompileTimeEvaluator>,
-    res: Result<Option<Value>, EvalError<'tcx>>,
+    val: ValTy<'tcx>,
 ) -> u128 {
-    match res {
-        Ok(Some(Value::ByVal(prim))) => unwrap_miri(ecx, prim.to_bytes()),
-        Err(err) => unwrap_miri(ecx, Err(err)),
-        val => bug!("got {:?}", val),
-    }
+    let res = ecx.value_to_primval(val).and_then(|prim| prim.to_bytes());
+    unwrap_miri(ecx, res)
 }
 
 fn unwrap_miri<'a, 'tcx, T>(
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b1febf5da5a..bc0d82399b5 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -13,7 +13,7 @@ use rustc_data_structures::indexed_vec::Idx;
 use syntax::codemap::{self, DUMMY_SP};
 use syntax::ast::Mutability;
 use rustc::mir::interpret::{
-    PtrAndAlign, GlobalId, Value, Pointer, PrimVal, PrimValKind,
+    GlobalId, Value, Pointer, PrimVal, PrimValKind,
     EvalError, EvalResult, EvalErrorKind, MemoryPointer,
 };
 
@@ -498,7 +498,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     }
 
     pub fn deallocate_local(&mut self, local: Option<Value>) -> EvalResult<'tcx> {
-        if let Some(Value::ByRef(ptr)) = local {
+        if let Some(Value::ByRef(ptr, _align)) = local {
             trace!("deallocating local");
             let ptr = ptr.to_ptr()?;
             self.memory.dump_alloc(ptr.alloc_id);
@@ -637,12 +637,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 let src = self.eval_place(place)?;
                 // We ignore the alignment of the place here -- special handling for packed structs ends
                 // at the `&` operator.
-                let (ptr, extra) = self.force_allocation(src)?.to_ptr_align_extra();
+                let (ptr, _align, extra) = self.force_allocation(src)?.to_ptr_align_extra();
 
                 let val = match extra {
-                    PlaceExtra::None => ptr.ptr.to_value(),
-                    PlaceExtra::Length(len) => ptr.ptr.to_value_with_len(len),
-                    PlaceExtra::Vtable(vtable) => ptr.ptr.to_value_with_vtable(vtable),
+                    PlaceExtra::None => ptr.to_value(),
+                    PlaceExtra::Length(len) => ptr.to_value_with_len(len),
+                    PlaceExtra::Vtable(vtable) => ptr.to_value_with_vtable(vtable),
                     PlaceExtra::DowncastVariant(..) => {
                         bug!("attempted to take a reference to an enum downcast place")
                     }
@@ -951,10 +951,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     }
 
     pub fn read_global_as_value(&self, gid: GlobalId, layout: TyLayout) -> Value {
-        Value::ByRef(PtrAndAlign {
-            ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
-            align: layout.align
-        })
+        Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
+                     layout.align)
     }
 
     fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx> {
@@ -972,9 +970,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 // -1 since we don't store the return value
                 match self.stack[frame].locals[local.index() - 1] {
                     None => return err!(DeadLocal),
-                    Some(Value::ByRef(ptr)) => {
+                    Some(Value::ByRef(ptr, align)) => {
                         Place::Ptr {
                             ptr,
+                            align,
                             extra: PlaceExtra::None,
                         }
                     }
@@ -984,10 +983,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                         let layout = self.layout_of(ty)?;
                         let ptr = self.alloc_ptr(ty)?;
                         self.stack[frame].locals[local.index() - 1] =
-                            Some(Value::ByRef(PtrAndAlign {
-                                ptr: ptr.into(),
-                                align: layout.align
-                            })); // it stays live
+                            Some(Value::ByRef(ptr.into(), layout.align)); // it stays live
                         self.write_value_to_ptr(val, ptr.into(), ty)?;
                         Place::from_ptr(ptr, layout.align)
                     }
@@ -1005,7 +1001,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         ty: Ty<'tcx>,
     ) -> EvalResult<'tcx, Value> {
         match value {
-            Value::ByRef(PtrAndAlign { ptr, align }) => {
+            Value::ByRef(ptr, align) => {
                 self.read_with_align(align, |ectx| ectx.read_value(ptr, ty))
             }
             other => Ok(other),
@@ -1061,10 +1057,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         // correct if we never look at this data with the wrong type.
 
         match dest {
-            Place::Ptr {
-                ptr: PtrAndAlign { ptr, align },
-                extra,
-            } => {
+            Place::Ptr { ptr, align, extra } => {
                 assert_eq!(extra, PlaceExtra::None);
                 self.write_with_align_mut(align,
                     |ectx| ectx.write_value_to_ptr(src_val, ptr, dest_ty))
@@ -1090,11 +1083,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         old_dest_val: Value,
         dest_ty: Ty<'tcx>,
     ) -> EvalResult<'tcx> {
-        if let Value::ByRef(PtrAndAlign {
-                                ptr: dest_ptr,
-                                align,
-                            }) = old_dest_val
-        {
+        if let Value::ByRef(dest_ptr, align) = old_dest_val {
             // If the value is already `ByRef` (that is, backed by an `Allocation`),
             // then we must write the new value into this allocation, because there may be
             // other pointers into the allocation. These other pointers are logically
@@ -1106,11 +1095,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 ectx.write_value_to_ptr(src_val, dest_ptr, dest_ty)
             })?;
 
-        } else if let Value::ByRef(PtrAndAlign {
-                                       ptr: src_ptr,
-                                       align,
-                                   }) = src_val
-        {
+        } else if let Value::ByRef(src_ptr, align) = src_val {
             // If the value is not `ByRef`, then we know there are no pointers to it
             // and we can simply overwrite the `Value` in the locals array directly.
             //
@@ -1129,10 +1114,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                     let dest_ptr = ectx.alloc_ptr(dest_ty)?.into();
                     ectx.copy(src_ptr, dest_ptr, dest_ty)?;
                     let layout = ectx.layout_of(dest_ty)?;
-                    write_dest(ectx, Value::ByRef(PtrAndAlign {
-                        ptr: dest_ptr,
-                        align: layout.align
-                    }))?;
+                    write_dest(ectx, Value::ByRef(dest_ptr, layout.align))?;
                 }
                 Ok(())
             })?;
@@ -1153,7 +1135,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     ) -> EvalResult<'tcx> {
         trace!("write_value_to_ptr: {:#?}", value);
         match value {
-            Value::ByRef(PtrAndAlign { ptr, align }) => {
+            Value::ByRef(ptr, align) => {
                 self.read_with_align_mut(align, |ectx| ectx.copy(ptr, dest, dest_ty))
             }
             Value::ByVal(primval) => {
@@ -1485,7 +1467,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                         continue;
                     }
                     let (src_f_value, src_field) = match src {
-                        Value::ByRef(PtrAndAlign { ptr, align }) => {
+                        Value::ByRef(ptr, align) => {
                             let src_place = Place::from_primval_ptr(ptr, align);
                             let (src_f_place, src_field) =
                                 self.place_field(src_place, mir::Field::new(i), src_layout)?;
@@ -1537,7 +1519,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                     Err(err) => {
                         panic!("Failed to access local: {:?}", err);
                     }
-                    Ok(Value::ByRef(PtrAndAlign { ptr, align })) => {
+                    Ok(Value::ByRef(ptr, align)) => {
                         match ptr.into_inner_primval() {
                             PrimVal::Ptr(ptr) => {
                                 write!(msg, " by align({}) ref:", align.abi()).unwrap();
@@ -1566,7 +1548,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 trace!("{}", msg);
                 self.memory.dump_allocs(allocs);
             }
-            Place::Ptr { ptr: PtrAndAlign { ptr, align }, .. } => {
+            Place::Ptr { ptr, align, .. } => {
                 match ptr.into_inner_primval() {
                     PrimVal::Ptr(ptr) => {
                         trace!("by align({}) ref:", align.abi());
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 579977ba4a4..807b75a9e59 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -7,7 +7,7 @@ use rustc::ty::{Instance, TyCtxt};
 use rustc::ty::layout::{self, Align, TargetDataLayout};
 use syntax::ast::Mutability;
 
-use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, PtrAndAlign, Value, Pointer,
+use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, Value, Pointer,
                             EvalResult, PrimVal, EvalErrorKind};
 
 use super::{EvalContext, Machine};
@@ -1046,7 +1046,7 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
         value: Value,
     ) -> EvalResult<'tcx, Pointer> {
         Ok(match value {
-            Value::ByRef(PtrAndAlign { ptr, align }) => {
+            Value::ByRef(ptr, align) => {
                 self.memory().read_with_align(align, |mem| mem.read_ptr_sized_unsigned(ptr.to_ptr()?))?
             }
             Value::ByVal(ptr) |
@@ -1059,10 +1059,7 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
         value: Value,
     ) -> EvalResult<'tcx, (Pointer, MemoryPointer)> {
         match value {
-            Value::ByRef(PtrAndAlign {
-                      ptr: ref_ptr,
-                      align,
-                  }) => {
+            Value::ByRef(ref_ptr, align) => {
                 self.memory().read_with_align(align, |mem| {
                     let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into();
                     let vtable = mem.read_ptr_sized_unsigned(
@@ -1084,10 +1081,7 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
         value: Value,
     ) -> EvalResult<'tcx, (Pointer, u64)> {
         match value {
-            Value::ByRef(PtrAndAlign {
-                      ptr: ref_ptr,
-                      align,
-                  }) => {
+            Value::ByRef(ref_ptr, align) => {
                 self.memory().read_with_align(align, |mem| {
                     let ptr = mem.read_ptr_sized_unsigned(ref_ptr.to_ptr()?)?.into();
                     let len = mem.read_ptr_sized_unsigned(
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index baccdd381d6..097f769adcf 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -2,9 +2,8 @@ use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::mir::interpret::{GlobalId, PtrAndAlign};
 
-use rustc::mir::interpret::{Value, PrimVal, EvalResult, Pointer, MemoryPointer};
+use rustc::mir::interpret::{GlobalId, Value, PrimVal, EvalResult, Pointer, MemoryPointer};
 use super::{EvalContext, Machine, ValTy};
 use interpret::memory::HasMemory;
 
@@ -15,7 +14,8 @@ pub enum Place {
         /// An place may have an invalid (integral or undef) pointer,
         /// since it might be turned back into a reference
         /// before ever being dereferenced.
-        ptr: PtrAndAlign,
+        ptr: Pointer,
+        align: Align,
         extra: PlaceExtra,
     },
 
@@ -40,7 +40,8 @@ impl<'tcx> Place {
 
     pub fn from_primval_ptr(ptr: Pointer, align: Align) -> Self {
         Place::Ptr {
-            ptr: PtrAndAlign { ptr, align },
+            ptr,
+            align,
             extra: PlaceExtra::None,
         }
     }
@@ -49,23 +50,23 @@ impl<'tcx> Place {
         Self::from_primval_ptr(ptr.into(), align)
     }
 
-    pub fn to_ptr_align_extra(self) -> (PtrAndAlign, PlaceExtra) {
+    pub fn to_ptr_align_extra(self) -> (Pointer, Align, PlaceExtra) {
         match self {
-            Place::Ptr { ptr, extra } => (ptr, extra),
+            Place::Ptr { ptr, align, extra } => (ptr, align, extra),
             _ => bug!("to_ptr_and_extra: expected Place::Ptr, got {:?}", self),
 
         }
     }
 
-    pub fn to_ptr_align(self) -> PtrAndAlign {
-        let (ptr, _extra) = self.to_ptr_align_extra();
-        ptr
+    pub fn to_ptr_align(self) -> (Pointer, Align) {
+        let (ptr, align, _extra) = self.to_ptr_align_extra();
+        (ptr, align)
     }
 
     pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
         // At this point, we forget about the alignment information -- the place has been turned into a reference,
         // and no matter where it came from, it now must be aligned.
-        self.to_ptr_align().to_ptr()
+        self.to_ptr_align().0.to_ptr()
     }
 
     pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
@@ -169,9 +170,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
 
     pub fn read_place(&self, place: Place) -> EvalResult<'tcx, Value> {
         match place {
-            Place::Ptr { ptr, extra } => {
+            Place::Ptr { ptr, align, extra } => {
                 assert_eq!(extra, PlaceExtra::None);
-                Ok(Value::ByRef(ptr))
+                Ok(Value::ByRef(ptr, align))
             }
             Place::Local { frame, local } => self.stack[frame].get_local(local),
         }
@@ -194,10 +195,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 };
                 let layout = self.layout_of(self.place_ty(mir_place))?;
                 Place::Ptr {
-                    ptr: PtrAndAlign {
-                        ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
-                        align: layout.align
-                    },
+                    ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
+                    align: layout.align,
                     extra: PlaceExtra::None,
                 }
             }
@@ -233,8 +232,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         let offset = base_layout.fields.offset(field_index);
 
         // Do not allocate in trivial cases
-        let (base_ptr, base_extra) = match base {
-            Place::Ptr { ptr, extra } => (ptr, extra),
+        let (base_ptr, base_align, base_extra) = match base {
+            Place::Ptr { ptr, align, extra } => (ptr, align, extra),
             Place::Local { frame, local } => {
                 match (&self.stack[frame].get_local(local)?, &base_layout.abi) {
                     // in case the field covers the entire type, just return the value
@@ -253,16 +252,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             PlaceExtra::Vtable(tab) => {
                 let (_, align) = self.size_and_align_of_dst(
                     base_layout.ty,
-                    base_ptr.ptr.to_value_with_vtable(tab),
+                    base_ptr.to_value_with_vtable(tab),
                 )?;
                 offset.abi_align(align).bytes()
             }
             _ => offset.bytes(),
         };
 
-        let mut ptr = base_ptr.offset(offset, &self)?;
-        ptr.align = ptr.align.min(base_layout.align).min(field.align);
-
+        let ptr = base_ptr.offset(offset, &self)?;
+        let align = base_align.min(base_layout.align).min(field.align);
         let extra = if !field.is_unsized() {
             PlaceExtra::None
         } else {
@@ -277,7 +275,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             base_extra
         };
 
-        Ok((Place::Ptr { ptr, extra }, field))
+        Ok((Place::Ptr { ptr, align, extra }, field))
     }
 
     pub fn val_to_place(&self, val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Place> {
@@ -286,14 +284,16 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             ty::TyDynamic(..) => {
                 let (ptr, vtable) = self.into_ptr_vtable_pair(val)?;
                 Place::Ptr {
-                    ptr: PtrAndAlign { ptr, align: layout.align },
+                    ptr,
+                    align: layout.align,
                     extra: PlaceExtra::Vtable(vtable),
                 }
             }
             ty::TyStr | ty::TySlice(_) => {
                 let (ptr, len) = self.into_slice(val)?;
                 Place::Ptr {
-                    ptr: PtrAndAlign { ptr, align: layout.align },
+                    ptr,
+                    align: layout.align,
                     extra: PlaceExtra::Length(len),
                 }
             }
@@ -309,7 +309,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     ) -> EvalResult<'tcx, Place> {
         // Taking the outer type here may seem odd; it's needed because for array types, the outer type gives away the length.
         let base = self.force_allocation(base)?;
-        let base_ptr = base.to_ptr_align();
+        let (base_ptr, align) = base.to_ptr_align();
 
         let (elem_ty, len) = base.elem_ty_and_len(outer_ty);
         let elem_size = self.layout_of(elem_ty)?.size.bytes();
@@ -322,6 +322,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         let ptr = base_ptr.offset(n * elem_size, &*self)?;
         Ok(Place::Ptr {
             ptr,
+            align,
             extra: PlaceExtra::None,
         })
     }
@@ -333,9 +334,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
     ) -> EvalResult<'tcx, Place> {
         // FIXME(solson)
         let base = self.force_allocation(base)?;
-        let ptr = base.to_ptr_align();
+        let (ptr, align) = base.to_ptr_align();
         let extra = PlaceExtra::DowncastVariant(variant);
-        Ok(Place::Ptr { ptr, extra })
+        Ok(Place::Ptr { ptr, align, extra })
     }
 
     pub fn eval_place_projection(
@@ -345,14 +346,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
     ) -> EvalResult<'tcx, Place> {
         use rustc::mir::ProjectionElem::*;
-        let (ptr, extra) = match *proj_elem {
+        match *proj_elem {
             Field(field, _) => {
                 let layout = self.layout_of(base_ty)?;
-                return Ok(self.place_field(base, field, layout)?.0);
+                Ok(self.place_field(base, field, layout)?.0)
             }
 
             Downcast(_, variant) => {
-                return self.place_downcast(base, variant);
+                self.place_downcast(base, variant)
             }
 
             Deref => {
@@ -367,14 +368,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
 
                 trace!("deref to {} on {:?}", pointee_type, val);
 
-                return self.val_to_place(val, pointee_type);
+                self.val_to_place(val, pointee_type)
             }
 
             Index(local) => {
                 let value = self.frame().get_local(local)?;
                 let ty = self.tcx.types.usize;
                 let n = self.value_to_primval(ValTy { value, ty })?.to_u64()?;
-                return self.place_index(base, base_ty, n);
+                self.place_index(base, base_ty, n)
             }
 
             ConstantIndex {
@@ -384,7 +385,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
             } => {
                 // FIXME(solson)
                 let base = self.force_allocation(base)?;
-                let base_ptr = base.to_ptr_align();
+                let (base_ptr, align) = base.to_ptr_align();
 
                 let (elem_ty, n) = base.elem_ty_and_len(base_ty);
                 let elem_size = self.layout_of(elem_ty)?.size.bytes();
@@ -397,13 +398,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 };
 
                 let ptr = base_ptr.offset(index * elem_size, &self)?;
-                (ptr, PlaceExtra::None)
+                Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None })
             }
 
             Subslice { from, to } => {
                 // FIXME(solson)
                 let base = self.force_allocation(base)?;
-                let base_ptr = base.to_ptr_align();
+                let (base_ptr, align) = base.to_ptr_align();
 
                 let (elem_ty, n) = base.elem_ty_and_len(base_ty);
                 let elem_size = self.layout_of(elem_ty)?.size.bytes();
@@ -415,11 +416,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                 } else {
                     PlaceExtra::Length(n - u64::from(to) - u64::from(from))
                 };
-                (ptr, extra)
+                Ok(Place::Ptr { ptr, align, extra })
             }
-        };
-
-        Ok(Place::Ptr { ptr, extra })
+        }
     }
 
     pub fn place_ty(&self, place: &mir::Place<'tcx>) -> Ty<'tcx> {
diff --git a/src/librustc_mir/interpret/terminator/drop.rs b/src/librustc_mir/interpret/terminator/drop.rs
index 5db46149834..c5942712b87 100644
--- a/src/librustc_mir/interpret/terminator/drop.rs
+++ b/src/librustc_mir/interpret/terminator/drop.rs
@@ -21,16 +21,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
         let val = match self.force_allocation(place)? {
             Place::Ptr {
                 ptr,
+                align: _,
                 extra: PlaceExtra::Vtable(vtable),
-            } => ptr.ptr.to_value_with_vtable(vtable),
+            } => ptr.to_value_with_vtable(vtable),
             Place::Ptr {
                 ptr,
+                align: _,
                 extra: PlaceExtra::Length(len),
-            } => ptr.ptr.to_value_with_len(len),
+            } => ptr.to_value_with_len(len),
             Place::Ptr {
                 ptr,
+                align: _,
                 extra: PlaceExtra::None,
-            } => ptr.ptr.to_value(),
+            } => ptr.to_value(),
             _ => bug!("force_allocation broken"),
         };
         self.drop(val, instance, ty, span, target)
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index 64216b715a5..0c43490e1fd 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -4,7 +4,7 @@ use rustc::ty::layout::LayoutOf;
 use syntax::codemap::Span;
 use syntax::abi::Abi;
 
-use rustc::mir::interpret::{PtrAndAlign, EvalResult, PrimVal, Value};
+use rustc::mir::interpret::{EvalResult, PrimVal, Value};
 use super::{EvalContext, eval_context,
             Place, Machine, ValTy};
 
@@ -327,14 +327,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
                         if let ty::TyTuple(..) = args[1].ty.sty {
                             if self.frame().mir.args_iter().count() == layout.fields.count() + 1 {
                                 match args[1].value {
-                                    Value::ByRef(PtrAndAlign { ptr, align }) => {
+                                    Value::ByRef(ptr, align) => {
                                         for (i, arg_local) in arg_locals.enumerate() {
                                             let field = layout.field(&self, i)?;
                                             let offset = layout.fields.offset(i).bytes();
-                                            let arg = Value::ByRef(PtrAndAlign {
-                                                ptr: ptr.offset(offset, &self)?,
-                                                align: align.min(field.align)
-                                            });
+                                            let arg = Value::ByRef(ptr.offset(offset, &self)?,
+                                                                   align.min(field.align));
                                             let dest =
                                                 self.eval_place(&mir::Place::Local(arg_local))?;
                                             trace!(