]> git.lizzy.rs Git - rust.git/blobdiff - src/machine.rs
Fix merge conflicts
[rust.git] / src / machine.rs
index b4aac147f94fb184dde74ae8469955877f8e08e5..7904e1cc123b359fbc08603f7325c5abbad80b5d 100644 (file)
@@ -1,24 +1,28 @@
 //! Global machine state as well as implementation of the interpreter engine
 //! `Machine` trait.
 
-use std::rc::Rc;
 use std::borrow::Cow;
 use std::cell::RefCell;
+use std::rc::Rc;
 
 use rand::rngs::StdRng;
 
-use syntax::attr;
-use syntax::symbol::sym;
 use rustc::hir::def_id::DefId;
-use rustc::ty::{self, layout::{Size, LayoutOf}, TyCtxt};
 use rustc::mir;
+use rustc::ty::{
+    self,
+    layout::{LayoutOf, Size},
+    Ty, TyCtxt,
+};
+use syntax::attr;
+use syntax::symbol::sym;
 
 use crate::*;
 
 // Some global facts about the emulated machine.
-pub const PAGE_SIZE: u64 = 4*1024; // FIXME: adjust to target architecture
-pub const STACK_ADDR: u64 = 32*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
-pub const STACK_SIZE: u64 = 16*PAGE_SIZE; // whatever
+pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
+pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
+pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever
 pub const NUM_CPUS: u64 = 1;
 
 /// Extra memory kinds
@@ -87,14 +91,17 @@ pub struct Evaluator<'tcx> {
     pub(crate) argv: Option<Pointer<Tag>>,
     pub(crate) cmd_line: Option<Pointer<Tag>>,
 
-    /// Last OS error.
-    pub(crate) last_error: u32,
+    /// Last OS error location in memory. It is a 32-bit integer.
+    pub(crate) last_error: Option<MPlaceTy<'tcx, Tag>>,
 
     /// TLS state.
     pub(crate) tls: TlsData<'tcx>,
 
-    /// If enabled, the `env_vars` field is populated with the host env vars during initialization.
+    /// If enabled, the `env_vars` field is populated with the host env vars during initialization
+    /// and random number generation is delegated to the host.
     pub(crate) communicate: bool,
+
+    pub(crate) file_handler: FileHandler,
 }
 
 impl<'tcx> Evaluator<'tcx> {
@@ -106,9 +113,10 @@ pub(crate) fn new(communicate: bool) -> Self {
             argc: None,
             argv: None,
             cmd_line: None,
-            last_error: 0,
+            last_error: None,
             tls: TlsData::default(),
             communicate,
+            file_handler: Default::default(),
         }
     }
 }
@@ -142,7 +150,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
     type PointerTag = Tag;
     type ExtraFnVal = Dlsym;
 
-    type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
+    type MemoryMap = MonoHashMap<
+        AllocId,
+        (
+            MemoryKind<MiriMemoryKind>,
+            Allocation<Tag, Self::AllocExtra>,
+        ),
+    >;
 
     const STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Static);
 
@@ -150,7 +164,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
 
     #[inline(always)]
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
-        ecx.memory().extra.validate
+        ecx.memory.extra.validate
     }
 
     #[inline(always)]
@@ -191,7 +205,7 @@ fn binary_ptr_op(
         bin_op: mir::BinOp,
         left: ImmTy<'tcx, Tag>,
         right: ImmTy<'tcx, Tag>,
-    ) -> InterpResult<'tcx, (Scalar<Tag>, bool)> {
+    ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)> {
         ecx.binary_ptr_op(bin_op, left, right)
     }
 
@@ -203,7 +217,7 @@ fn box_alloc(
         // Call the `exchange_malloc` lang item.
         let malloc = ecx.tcx.lang_items().exchange_malloc_fn().unwrap();
         let malloc = ty::Instance::mono(ecx.tcx.tcx, malloc);
-        let malloc_mir = ecx.load_mir(malloc.def)?;
+        let malloc_mir = ecx.load_mir(malloc.def, None)?;
         ecx.push_stack_frame(
             malloc,
             malloc_mir.span,
@@ -230,10 +244,7 @@ fn box_alloc(
         ecx.write_scalar(Scalar::from_uint(align, arg.layout.size), arg)?;
 
         // No more arguments.
-        assert!(
-            args.next().is_none(),
-            "`exchange_malloc` lang item has more arguments than expected"
-        );
+        args.next().expect_none("`exchange_malloc` lang item has more arguments than expected");
         Ok(())
     }
 
@@ -247,7 +258,7 @@ fn find_foreign_static(
             None => tcx.item_name(def_id).as_str(),
         };
 
-        let alloc = match link_name.get() {
+        let alloc = match &*link_name {
             "__cxa_thread_atexit_impl" => {
                 // This should be all-zero, pointer-sized.
                 let size = tcx.data_layout.pointer_size;
@@ -260,8 +271,7 @@ fn find_foreign_static(
     }
 
     #[inline(always)]
-    fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
-    {
+    fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
         // We are not interested in detecting loops.
         Ok(())
     }
@@ -271,7 +281,10 @@ fn tag_allocation<'b>(
         id: AllocId,
         alloc: Cow<'b, Allocation>,
         kind: Option<MemoryKind<Self::MemoryKinds>>,
-    ) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
+    ) -> (
+        Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>,
+        Self::PointerTag,
+    ) {
         let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
         let alloc = alloc.into_owned();
         let (stacks, base_tag) = if !memory_extra.validate {
@@ -279,52 +292,39 @@ fn tag_allocation<'b>(
         } else {
             let (stacks, base_tag) = Stacks::new_allocation(
                 id,
-                Size::from_bytes(alloc.bytes.len() as u64),
+                alloc.size,
                 Rc::clone(&memory_extra.stacked_borrows),
                 kind,
             );
             (Some(stacks), base_tag)
         };
-        if kind != MiriMemoryKind::Static.into() {
-            assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
-            // Now we can rely on the inner pointers being static, too.
-        }
         let mut stacked_borrows = memory_extra.stacked_borrows.borrow_mut();
-        let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
-            bytes: alloc.bytes,
-            relocations: Relocations::from_presorted(
-                alloc.relocations.iter()
-                    // The allocations in the relocations (pointers stored *inside* this allocation)
-                    // all get the base pointer tag.
-                    .map(|&(offset, ((), alloc))| {
-                        let tag = if !memory_extra.validate {
-                            Tag::Untagged
-                        } else {
-                            stacked_borrows.static_base_ptr(alloc)
-                        };
-                        (offset, (tag, alloc))
-                    })
-                    .collect()
-            ),
-            undef_mask: alloc.undef_mask,
-            align: alloc.align,
-            mutability: alloc.mutability,
-            extra: AllocExtra {
+        let alloc: Allocation<Tag, Self::AllocExtra> = alloc.with_tags_and_extra(
+            |alloc| {
+                if !memory_extra.validate {
+                    Tag::Untagged
+                } else {
+                    // Only statics may already contain pointers at this point
+                    assert_eq!(kind, MiriMemoryKind::Static.into());
+                    stacked_borrows.static_base_ptr(alloc)
+                }
+            },
+            AllocExtra {
                 stacked_borrows: stacks,
             },
-        };
+        );
         (Cow::Owned(alloc), base_tag)
     }
 
     #[inline(always)]
-    fn tag_static_base_pointer(
-        memory_extra: &MemoryExtra,
-        id: AllocId,
-    ) -> Self::PointerTag {
+    fn tag_static_base_pointer(memory_extra: &MemoryExtra, id: AllocId) -> Self::PointerTag {
         if !memory_extra.validate {
             Tag::Untagged
         } else {
-            memory_extra.stacked_borrows.borrow_mut().static_base_ptr(id)
+            memory_extra
+                .stacked_borrows
+                .borrow_mut()
+                .static_base_ptr(id)
         }
     }
 
@@ -336,7 +336,7 @@ fn retag(
     ) -> InterpResult<'tcx> {
         if !Self::enforce_validity(ecx) {
             // No tracking.
-             Ok(())
+            Ok(())
         } else {
             ecx.retag(kind, place)
         }
@@ -346,7 +346,7 @@ fn retag(
     fn stack_push(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
     ) -> InterpResult<'tcx, stacked_borrows::CallId> {
-        Ok(ecx.memory().extra.stacked_borrows.borrow_mut().new_call())
+        Ok(ecx.memory.extra.stacked_borrows.borrow_mut().new_call())
     }
 
     #[inline(always)]
@@ -354,7 +354,12 @@ fn stack_pop(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         extra: stacked_borrows::CallId,
     ) -> InterpResult<'tcx> {
-        Ok(ecx.memory().extra.stacked_borrows.borrow_mut().end_call(extra))
+        Ok(ecx
+            .memory
+            .extra
+            .stacked_borrows
+            .borrow_mut()
+            .end_call(extra))
     }
 
     #[inline(always)]