]> git.lizzy.rs Git - rust.git/commitdiff
pass typecheck
authorDavid Renshaw <dwrenshaw@gmail.com>
Tue, 2 Jan 2018 22:43:03 +0000 (17:43 -0500)
committerDavid Renshaw <dwrenshaw@gmail.com>
Tue, 2 Jan 2018 22:43:03 +0000 (17:43 -0500)
miri/fn_call.rs
miri/intrinsic.rs
miri/lib.rs
miri/operator.rs
miri/validation.rs

index 3ca71e9b90c20824860d49ae27324ea4f4db98d7..df101739ed91926e2e373fbe2f3ec12fe4237bcb 100644 (file)
@@ -1,5 +1,5 @@
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::LayoutOf;
+use rustc::ty::layout::{Align, LayoutOf};
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc::mir;
 use syntax::attr;
@@ -111,7 +111,7 @@ fn call_c_abi(
                 if size == 0 {
                     self.write_null(dest, dest_ty)?;
                 } else {
-                    let align = self.memory.pointer_size();
+                    let align = self.tcx.data_layout.pointer_align;
                     let ptr = self.memory.allocate(size, align, Some(MemoryKind::C.into()))?;
                     self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
                 }
@@ -307,7 +307,7 @@ fn call_c_abi(
                     // +1 for the null terminator
                     let value_copy = self.memory.allocate(
                         (value.len() + 1) as u64,
-                        1,
+                        Align::from_bytes(1, 1).unwrap(),
                         Some(MemoryKind::Env.into()),
                     )?;
                     self.memory.write_bytes(value_copy.into(), &value)?;
@@ -369,6 +369,8 @@ fn call_c_abi(
 
             "sysconf" => {
                 let name = self.value_to_primval(args[0])?.to_u64()?;
+                let name_align = self.layout_of(args[0].ty)?.align;
+
                 trace!("sysconf() called with name {}", name);
                 // cache the sysconf integers via miri's global cache
                 let paths = &[
@@ -387,7 +389,8 @@ fn call_c_abi(
                             Some(ptr) => ptr,
                             None => eval_body(self.tcx, instance, ty::ParamEnv::empty(traits::Reveal::All))?.0,
                         };
-                        let val = self.value_to_primval(ValTy { value: Value::ByRef(val), ty: args[0].ty })?.to_u64()?;
+                        let val = self.value_to_primval(ValTy { value: Value::ByRef(val, name_align),
+                                                                ty: args[0].ty })?.to_u64()?;
                         if val == name {
                             result = Some(path_value);
                             break;
@@ -406,6 +409,7 @@ fn call_c_abi(
             // Hook pthread calls that go to the thread-local storage memory subsystem
             "pthread_key_create" => {
                 let key_ptr = self.into_ptr(args[0].value)?;
+                let key_align = self.layout_of(args[0].ty)?.align;
 
                 // Extract the function type out of the signature (that seems easier than constructing it ourselves...)
                 let dtor = match self.into_ptr(args[1].value)?.into_inner_primval() {
@@ -427,6 +431,7 @@ fn call_c_abi(
                 }
                 self.memory.write_primval(
                     key_ptr.to_ptr()?,
+                    key_align,
                     PrimVal::Bytes(key),
                     key_size.bytes(),
                     false,
@@ -559,7 +564,9 @@ fn call_missing_fn(
                 if !align.is_power_of_two() {
                     return err!(HeapAllocNonPowerOfTwoAlignment(align));
                 }
-                let ptr = self.memory.allocate(size, align, Some(MemoryKind::Rust.into()))?;
+                let ptr = self.memory.allocate(size,
+                                               Align::from_bytes(align, align).unwrap(),
+                                               Some(MemoryKind::Rust.into()))?;
                 self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
             }
             "alloc::heap::::__rust_alloc_zeroed" => {
@@ -571,7 +578,9 @@ fn call_missing_fn(
                 if !align.is_power_of_two() {
                     return err!(HeapAllocNonPowerOfTwoAlignment(align));
                 }
-                let ptr = self.memory.allocate(size, align, Some(MemoryKind::Rust.into()))?;
+                let ptr = self.memory.allocate(size,
+                                               Align::from_bytes(align, align).unwrap(),
+                                               Some(MemoryKind::Rust.into()))?;
                 self.memory.write_repeat(ptr.into(), 0, size)?;
                 self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
             }
@@ -587,7 +596,7 @@ fn call_missing_fn(
                 }
                 self.memory.deallocate(
                     ptr,
-                    Some((old_size, align)),
+                    Some((old_size, Align::from_bytes(align, align).unwrap())),
                     MemoryKind::Rust.into(),
                 )?;
             }
@@ -609,9 +618,9 @@ fn call_missing_fn(
                 let new_ptr = self.memory.reallocate(
                     ptr,
                     old_size,
-                    old_align,
+                    Align::from_bytes(old_align, old_align).unwrap(),
                     new_size,
-                    new_align,
+                    Align::from_bytes(new_align, new_align).unwrap(),
                     MemoryKind::Rust.into(),
                 )?;
                 self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
index 705c332523397a02192a5a7690ef01c1eb9f2f7d..3357f0bba392758aced11531f1422ab2f412e7ba 100644 (file)
@@ -3,7 +3,7 @@
 use rustc::ty::layout::{TyLayout, LayoutOf};
 use rustc::ty;
 
-use rustc::mir::interpret::{EvalResult, PrimVal, PrimValKind, Value, Pointer, AccessKind, PtrAndAlign};
+use rustc::mir::interpret::{EvalResult, PrimVal, PrimValKind, Value, Pointer};
 use rustc_mir::interpret::{Place, PlaceExtra, HasMemory, EvalContext, ValTy};
 
 use helpers::EvalContextExt as HelperEvalContextExt;
@@ -87,8 +87,10 @@ fn call_intrinsic(
             "atomic_load_acq" |
             "volatile_load" => {
                 let ptr = self.into_ptr(args[0].value)?;
+                let align = self.layout_of(args[0].ty)?.align;
+
                 let valty = ValTy {
-                    value: Value::by_ref(ptr),
+                    value: Value::ByRef(ptr, align),
                     ty: substs.type_at(0),
                 };
                 self.write_value(valty, dest)?;
@@ -99,8 +101,9 @@ fn call_intrinsic(
             "atomic_store_rel" |
             "volatile_store" => {
                 let ty = substs.type_at(0);
+                let align = self.layout_of(ty)?.align;
                 let dest = self.into_ptr(args[0].value)?;
-                self.write_value_to_ptr(args[1].value, dest, ty)?;
+                self.write_value_to_ptr(args[1].value, dest, align, ty)?;
             }
 
             "atomic_fence_acq" => {
@@ -109,9 +112,10 @@ fn call_intrinsic(
 
             _ if intrinsic_name.starts_with("atomic_xchg") => {
                 let ty = substs.type_at(0);
+                let align = self.layout_of(ty)?.align;
                 let ptr = self.into_ptr(args[0].value)?;
                 let change = self.value_to_primval(args[1])?;
-                let old = self.read_value(ptr, ty)?;
+                let old = self.read_value(ptr, align, ty)?;
                 let old = match old {
                     Value::ByVal(val) => val,
                     Value::ByRef { .. } => bug!("just read the value, can't be byref"),
@@ -119,7 +123,7 @@ fn call_intrinsic(
                 };
                 self.write_primval(dest, old, ty)?;
                 self.write_primval(
-                    Place::from_primval_ptr(ptr),
+                    Place::from_primval_ptr(ptr, align),
                     change,
                     ty,
                 )?;
@@ -127,10 +131,11 @@ fn call_intrinsic(
 
             _ if intrinsic_name.starts_with("atomic_cxchg") => {
                 let ty = substs.type_at(0);
+                let align = self.layout_of(ty)?.align;
                 let ptr = self.into_ptr(args[0].value)?;
                 let expect_old = self.value_to_primval(args[1])?;
                 let change = self.value_to_primval(args[2])?;
-                let old = self.read_value(ptr, ty)?;
+                let old = self.read_value(ptr, align, ty)?;
                 let old = match old {
                     Value::ByVal(val) => val,
                     Value::ByRef { .. } => bug!("just read the value, can't be byref"),
@@ -143,7 +148,7 @@ fn call_intrinsic(
                 };
                 self.write_value(valty, dest)?;
                 self.write_primval(
-                    Place::from_primval_ptr(ptr),
+                    Place::from_primval_ptr(ptr, dest_layout.align),
                     change,
                     ty,
                 )?;
@@ -175,9 +180,10 @@ fn call_intrinsic(
             "atomic_xsub_acqrel" |
             "atomic_xsub_relaxed" => {
                 let ty = substs.type_at(0);
+                let align = self.layout_of(ty)?.align;
                 let ptr = self.into_ptr(args[0].value)?;
                 let change = self.value_to_primval(args[1])?;
-                let old = self.read_value(ptr, ty)?;
+                let old = self.read_value(ptr, align, ty)?;
                 let old = match old {
                     Value::ByVal(val) => val,
                     Value::ByRef { .. } => bug!("just read the value, can't be byref"),
@@ -196,7 +202,7 @@ fn call_intrinsic(
                 };
                 // FIXME: what do atomics do on overflow?
                 let (val, _) = self.binary_op(op, old, ty, change, ty)?;
-                self.write_primval(Place::from_primval_ptr(ptr), val, ty)?;
+                self.write_primval(Place::from_primval_ptr(ptr, dest_layout.align), val, ty)?;
             }
 
             "breakpoint" => unimplemented!(), // halt miri
@@ -210,14 +216,16 @@ fn call_intrinsic(
                 if count * elem_size != 0 {
                     // TODO: We do not even validate alignment for the 0-bytes case.  libstd relies on this in vec::IntoIter::next.
                     // Also see the write_bytes intrinsic.
-                    let elem_align = elem_layout.align.abi();
+                    let elem_align = elem_layout.align;
                     let src = self.into_ptr(args[0].value)?;
+                    let src_align = self.layout_of(args[0].ty)?.align;
                     let dest = self.into_ptr(args[1].value)?;
                     self.memory.copy(
                         src,
+                        src_align,
                         dest,
-                        count * elem_size,
                         elem_align,
+                        count * elem_size,
                         intrinsic_name.ends_with("_nonoverlapping"),
                     )?;
                 }
@@ -241,7 +249,8 @@ fn call_intrinsic(
             "discriminant_value" => {
                 let ty = substs.type_at(0);
                 let adt_ptr = self.into_ptr(args[0].value)?;
-                let place = Place::from_primval_ptr(adt_ptr);
+                let adt_align = self.layout_of(args[0].ty)?.align;
+                let place = Place::from_primval_ptr(adt_ptr, adt_align);
                 let discr_val = self.read_discriminant_value(place, ty)?;
                 self.write_primval(dest, PrimVal::Bytes(discr_val), dest_layout.ty)?;
             }
@@ -312,7 +321,7 @@ fn call_intrinsic(
                 let size = dest_layout.size.bytes();
                 let init = |this: &mut Self, val: Value| {
                     let zero_val = match val {
-                        Value::ByRef(PtrAndAlign { ptr, .. }) => {
+                        Value::ByRef(ptr, _) => {
                             // These writes have no alignment restriction anyway.
                             this.memory.write_repeat(ptr, 0, size)?;
                             val
@@ -326,7 +335,7 @@ fn call_intrinsic(
                                     let ptr = this.alloc_ptr(dest_layout.ty)?;
                                     let ptr = Pointer::from(PrimVal::Ptr(ptr));
                                     this.memory.write_repeat(ptr, 0, size)?;
-                                    Value::by_ref(ptr)
+                                    Value::ByRef(ptr, dest_layout.align)
                                 }
                             }
                         }
@@ -340,12 +349,11 @@ fn call_intrinsic(
                 match dest {
                     Place::Local { frame, local } => self.modify_local(frame, local, init)?,
                     Place::Ptr {
-                        ptr: PtrAndAlign { ptr, aligned: true },
+                        ptr: ptr,
+                        align: _align,
                         extra: PlaceExtra::None,
                     } => self.memory.write_repeat(ptr, 0, size)?,
-                    Place::Ptr { .. } => {
-                        bug!("init intrinsic tried to write to fat or unaligned ptr target")
-                    }
+                    _ => bug!("TODO"),
                 }
             }
 
@@ -367,7 +375,8 @@ fn call_intrinsic(
             "move_val_init" => {
                 let ty = substs.type_at(0);
                 let ptr = self.into_ptr(args[0].value)?;
-                self.write_value_to_ptr(args[1].value, ptr, ty)?;
+                let align = self.layout_of(args[0].ty)?.align;
+                self.write_value_to_ptr(args[1].value, ptr, align, ty)?;
             }
 
             "needs_drop" => {
@@ -533,14 +542,10 @@ fn call_intrinsic(
 
             "transmute" => {
                 let src_ty = substs.type_at(0);
+                let src_align = self.layout_of(src_ty)?.align;
                 let ptr = self.force_allocation(dest)?.to_ptr()?;
-                self.write_maybe_aligned_mut(
-                    /*aligned*/
-                    false,
-                    |ectx| {
-                        ectx.write_value_to_ptr(args[0].value, ptr.into(), src_ty)
-                    },
-                )?;
+                let dest_align = self.layout_of(substs.type_at(1))?.align;
+                self.write_value_to_ptr(args[0].value, ptr.into(), dest_align, src_ty);
             }
 
             "unchecked_shl" => {
@@ -612,7 +617,7 @@ fn call_intrinsic(
             "uninit" => {
                 let size = dest_layout.size.bytes();
                 let uninit = |this: &mut Self, val: Value| match val {
-                    Value::ByRef(PtrAndAlign { ptr, .. }) => {
+                    Value::ByRef(ptr, _) => {
                         this.memory.mark_definedness(ptr, size, false)?;
                         Ok(val)
                     }
@@ -621,12 +626,11 @@ fn call_intrinsic(
                 match dest {
                     Place::Local { frame, local } => self.modify_local(frame, local, uninit)?,
                     Place::Ptr {
-                        ptr: PtrAndAlign { ptr, aligned: true },
+                        ptr: ptr,
+                        align: _align,
                         extra: PlaceExtra::None,
                     } => self.memory.mark_definedness(ptr, size, false)?,
-                    Place::Ptr { .. } => {
-                        bug!("uninit intrinsic tried to write to fat or unaligned ptr target")
-                    }
+                    _ => bug!("todo"),
                 }
             }
 
@@ -639,7 +643,7 @@ fn call_intrinsic(
                 if count > 0 {
                     // HashMap relies on write_bytes on a NULL ptr with count == 0 to work
                     // TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic)
-                    self.memory.check_align(ptr, ty_layout.align.abi(), Some(AccessKind::Write))?;
+                    self.memory.check_align(ptr, ty_layout.align)?;
                     self.memory.write_repeat(ptr, val_byte, ty_layout.size.bytes() * count)?;
                 }
             }
index d4c211e1fd959f46f26fee220c3d5f4483a2eae4..d458a3c47e8c363e1a70237430a6d8718bcff43a 100644 (file)
@@ -20,7 +20,6 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::layout::{TyLayout, LayoutOf};
 use rustc::hir::def_id::DefId;
-use rustc::ty::subst::Substs;
 use rustc::mir;
 use rustc::traits;
 
@@ -87,7 +86,7 @@ fn run_main<'a, 'tcx: 'a>(
 
             // Return value
             let size = ecx.tcx.data_layout.pointer_size.bytes();
-            let align = ecx.tcx.data_layout.pointer_align.abi();
+            let align = ecx.tcx.data_layout.pointer_align;
             let ret_ptr = ecx.memory_mut().allocate(size, align, Some(MemoryKind::Stack))?;
             cleanup_ptr = Some(ret_ptr);
 
@@ -96,7 +95,7 @@ fn run_main<'a, 'tcx: 'a>(
                 start_instance,
                 start_mir.span,
                 start_mir,
-                Place::from_ptr(ret_ptr),
+                Place::from_ptr(ret_ptr, align),
                 StackPopCleanup::None,
             )?;
 
@@ -126,8 +125,9 @@ fn run_main<'a, 'tcx: 'a>(
             let ty = ecx.tcx.mk_imm_ptr(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8));
             let foo = ecx.memory.allocate_cached(b"foo\0");
             let ptr_size = ecx.memory.pointer_size();
-            let foo_ptr = ecx.memory.allocate(ptr_size * 1, ptr_size, None)?;
-            ecx.memory.write_primval(foo_ptr.into(), PrimVal::Ptr(foo.into()), ptr_size, false)?;
+            let ptr_align = ecx.tcx.data_layout.pointer_align;
+            let foo_ptr = ecx.memory.allocate(ptr_size, ptr_align, None)?;
+            ecx.memory.write_primval(foo_ptr, ptr_align, PrimVal::Ptr(foo.into()), ptr_size, false)?;
             ecx.memory.mark_static_initalized(foo_ptr.alloc_id, Mutability::Immutable)?;
             ecx.write_ptr(dest, foo_ptr.into(), ty)?;
 
@@ -158,7 +158,7 @@ fn run_main<'a, 'tcx: 'a>(
         Ok(())
     }
 
-    let mut ecx = EvalContext::new(tcx, ty::ParamEnv::empty(traits::Reveal::All), limits, Default::default(), Default::default(), Substs::empty());
+    let mut ecx = EvalContext::new(tcx, ty::ParamEnv::empty(traits::Reveal::All), limits, Default::default(), Default::default());
     match run_main(&mut ecx, main_id, start_wrapper) {
         Ok(()) => {
             let leaks = ecx.memory().leak_report();
@@ -310,22 +310,20 @@ fn global_item_with_linkage<'a>(
         // FIXME: check that it's `#[linkage = "extern_weak"]`
         trace!("Initializing an extern global with NULL");
         let ptr_size = ecx.memory.pointer_size();
+        let ptr_align = ecx.tcx.data_layout.pointer_align;
         let ptr = ecx.memory.allocate(
             ptr_size,
-            ptr_size,
+            ptr_align,
             None,
         )?;
-        ecx.memory.write_ptr_sized_unsigned(ptr, PrimVal::Bytes(0))?;
+        ecx.memory.write_ptr_sized_unsigned(ptr, ptr_align, PrimVal::Bytes(0))?;
         ecx.memory.mark_static_initalized(ptr.alloc_id, mutability)?;
         ecx.tcx.interpret_interner.borrow_mut().cache(
             GlobalId {
                 instance,
                 promoted: None,
             },
-            PtrAndAlign {
-                ptr: ptr.into(),
-                aligned: true,
-            },
+            ptr.into(),
         );
         Ok(())
     }
index e70f1b12628ac9b33a6057e002b83ce725a19d48..919997a5217cba746edae2ad1104eae6b1387b02 100644 (file)
@@ -153,7 +153,7 @@ fn map_to_primval((res, over): (MemoryPointer, bool)) -> (PrimVal, bool) {
                 map_to_primval(left.overflowing_offset(right as u64, self)),
 
             BitAnd if !signed => {
-                let base_mask : u64 = !(self.memory.get(left.alloc_id)?.align - 1);
+                let base_mask : u64 = !(self.memory.get(left.alloc_id)?.align.abi() - 1);
                 let right = right as u64;
                 if right & base_mask == base_mask {
                     // Case 1: The base address bits are all preserved, i.e., right is all-1 there
index 52f0c24bd6d18fd66724a46732068129e1131dbb..843dcd4041d775f6f8f641faa5c3c2d01662e4e0 100644 (file)
@@ -509,7 +509,7 @@ fn validate_ptr(
         // Check alignment and non-NULLness
         let (_, align) = self.size_and_align_of_dst(pointee_ty, val)?;
         let ptr = self.into_ptr(val)?;
-        self.memory.check_align(ptr, align.abi(), None)?;
+        self.memory.check_align(ptr, align)?;
 
         // Recurse
         let pointee_place = self.val_to_place(val, pointee_ty)?;
@@ -567,7 +567,7 @@ fn validate(
             // Tracking the same state for locals not backed by memory would just duplicate too
             // much machinery.
             // FIXME: We ignore alignment.
-            let (ptr, extra) = self.force_allocation(query.place.1)?.to_ptr_extra_aligned();
+            let (ptr, _, extra) = self.force_allocation(query.place.1)?.to_ptr_align_extra();
             // Determine the size
             // FIXME: Can we reuse size_and_align_of_dst for Places?
             let layout = self.layout_of(query.ty)?;