]> git.lizzy.rs Git - rust.git/blobdiff - src/machine.rs
Add communicate field to evaluator and fix formatting
[rust.git] / src / machine.rs
index 930eeee96b5939e73c72902da0c9d85debd284c8..ed9a8a1c46346f320149b1a9e473cbc56e3e124a 100644 (file)
@@ -1,3 +1,6 @@
+//! Global machine state as well as implementation of the interpreter engine
+//! `Machine` trait.
+
 use std::rc::Rc;
 use std::borrow::Cow;
 use std::collections::HashMap;
 use syntax::attr;
 use syntax::symbol::sym;
 use rustc::hir::def_id::DefId;
-use rustc::ty::{self, layout::{Size, LayoutOf}, query::TyCtxtAt};
+use rustc::ty::{self, layout::{Size, LayoutOf}, TyCtxt};
 use rustc::mir;
 
 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 = 16*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
+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
@@ -48,25 +52,24 @@ pub struct AllocExtra {
 }
 
 /// Extra global memory data
-#[derive(Default, Clone, Debug)]
+#[derive(Clone, Debug)]
 pub struct MemoryExtra {
     pub stacked_borrows: stacked_borrows::MemoryExtra,
     pub intptrcast: intptrcast::MemoryExtra,
 
-    /// The random number generator to use if Miri is running in non-deterministic mode and to
-    /// enable intptrcast
-    pub(crate) rng: Option<RefCell<StdRng>>,
+    /// The random number generator used for resolving non-determinism.
+    pub(crate) rng: RefCell<StdRng>,
 
     /// Whether to enforce the validity invariant.
     pub(crate) validate: bool,
 }
 
 impl MemoryExtra {
-    pub fn new(rng: Option<StdRng>, validate: bool) -> Self {
+    pub fn new(rng: StdRng, validate: bool) -> Self {
         MemoryExtra {
             stacked_borrows: Default::default(),
             intptrcast: Default::default(),
-            rng: rng.map(RefCell::new),
+            rng: RefCell::new(rng),
             validate,
         }
     }
@@ -90,10 +93,13 @@ pub struct Evaluator<'tcx> {
 
     /// TLS state.
     pub(crate) tls: TlsData<'tcx>,
+
+    /// If enabled, the `env_vars` field is populated with the host env vars during initialization.
+    pub(crate) communicate: bool,
 }
 
 impl<'tcx> Evaluator<'tcx> {
-    pub(crate) fn new() -> Self {
+    pub(crate) fn new(communicate: bool) -> Self {
         Evaluator {
             env_vars: HashMap::default(),
             argc: None,
@@ -101,6 +107,7 @@ pub(crate) fn new() -> Self {
             cmd_line: None,
             last_error: 0,
             tls: TlsData::default(),
+            communicate,
         }
     }
 }
@@ -132,17 +139,19 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
     type MemoryExtra = MemoryExtra;
     type AllocExtra = AllocExtra;
     type PointerTag = Tag;
+    type ExtraFnVal = Dlsym;
 
     type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
 
     const STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Static);
 
+    const CHECK_ALIGN: bool = true;
+
     #[inline(always)]
     fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
         ecx.memory().extra.validate
     }
 
-    /// Returns `Ok()` when the function was handled; fail otherwise.
     #[inline(always)]
     fn find_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -154,6 +163,17 @@ fn find_fn(
         ecx.find_fn(instance, args, dest, ret)
     }
 
+    #[inline(always)]
+    fn call_extra_fn(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        fn_val: Dlsym,
+        args: &[OpTy<'tcx, Tag>],
+        dest: Option<PlaceTy<'tcx, Tag>>,
+        ret: Option<mir::BasicBlock>,
+    ) -> InterpResult<'tcx> {
+        ecx.call_dlsym(fn_val, args, dest, ret)
+    }
+
     #[inline(always)]
     fn call_intrinsic(
         ecx: &mut rustc_mir::interpret::InterpCx<'mir, 'tcx, Self>,
@@ -165,13 +185,13 @@ fn call_intrinsic(
     }
 
     #[inline(always)]
-    fn ptr_op(
+    fn binary_ptr_op(
         ecx: &rustc_mir::interpret::InterpCx<'mir, 'tcx, Self>,
         bin_op: mir::BinOp,
         left: ImmTy<'tcx, Tag>,
         right: ImmTy<'tcx, Tag>,
     ) -> InterpResult<'tcx, (Scalar<Tag>, bool)> {
-        ecx.ptr_op(bin_op, left, right)
+        ecx.binary_ptr_op(bin_op, left, right)
     }
 
     fn box_alloc(
@@ -199,12 +219,12 @@ fn box_alloc(
 
         // First argument: `size`.
         // (`0` is allowed here -- this is expected to be handled by the lang item).
-        let arg = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
+        let arg = ecx.local_place(args.next().unwrap())?;
         let size = layout.size.bytes();
         ecx.write_scalar(Scalar::from_uint(size, arg.layout.size), arg)?;
 
         // Second argument: `align`.
-        let arg = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
+        let arg = ecx.local_place(args.next().unwrap())?;
         let align = layout.align.abi.bytes();
         ecx.write_scalar(Scalar::from_uint(align, arg.layout.size), arg)?;
 
@@ -217,8 +237,8 @@ fn box_alloc(
     }
 
     fn find_foreign_static(
+        tcx: TyCtxt<'tcx>,
         def_id: DefId,
-        tcx: TyCtxtAt<'tcx>,
     ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
         let attrs = tcx.get_attrs(def_id);
         let link_name = match attr::first_attr_value_str_by_name(&attrs, sym::link_name) {
@@ -233,9 +253,7 @@ fn find_foreign_static(
                 let data = vec![0; size.bytes() as usize];
                 Allocation::from_bytes(&data, tcx.data_layout.pointer_align.abi)
             }
-            _ => return err!(Unimplemented(
-                    format!("can't access foreign static: {}", link_name),
-                )),
+            _ => throw_unsup_format!("can't access foreign static: {}", link_name),
         };
         Ok(Cow::Owned(alloc))
     }
@@ -248,20 +266,20 @@ fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx
     }
 
     fn tag_allocation<'b>(
+        memory_extra: &MemoryExtra,
         id: AllocId,
         alloc: Cow<'b, Allocation>,
         kind: Option<MemoryKind<Self::MemoryKinds>>,
-        memory: &Memory<'mir, 'tcx, Self>,
     ) -> (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 {
+        let (stacks, base_tag) = if !memory_extra.validate {
             (None, Tag::Untagged)
         } else {
             let (stacks, base_tag) = Stacks::new_allocation(
                 id,
                 Size::from_bytes(alloc.bytes.len() as u64),
-                Rc::clone(&memory.extra.stacked_borrows),
+                Rc::clone(&memory_extra.stacked_borrows),
                 kind,
             );
             (Some(stacks), base_tag)
@@ -270,7 +288,7 @@ fn tag_allocation<'b>(
             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 memory_extra = memory.extra.stacked_borrows.borrow_mut();
+        let mut stacked_borrows = memory_extra.stacked_borrows.borrow_mut();
         let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
             bytes: alloc.bytes,
             relocations: Relocations::from_presorted(
@@ -278,10 +296,10 @@ fn tag_allocation<'b>(
                     // 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 {
+                        let tag = if !memory_extra.validate {
                             Tag::Untagged
                         } else {
-                            memory_extra.static_base_ptr(alloc)
+                            stacked_borrows.static_base_ptr(alloc)
                         };
                         (offset, (tag, alloc))
                     })
@@ -299,13 +317,13 @@ fn tag_allocation<'b>(
 
     #[inline(always)]
     fn tag_static_base_pointer(
+        memory_extra: &MemoryExtra,
         id: AllocId,
-        memory: &Memory<'mir, 'tcx, Self>,
     ) -> Self::PointerTag {
-        if !memory.extra.validate {
+        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)
         }
     }
 
@@ -338,28 +356,20 @@ fn stack_pop(
         Ok(ecx.memory().extra.stacked_borrows.borrow_mut().end_call(extra))
     }
 
+    #[inline(always)]
     fn int_to_ptr(
-        int: u64,
         memory: &Memory<'mir, 'tcx, Self>,
+        int: u64,
     ) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
-        if int == 0 {
-            err!(InvalidNullPointerUsage)
-        } else if memory.extra.rng.is_none() {
-            err!(ReadBytesAsPointer)
-        } else {
-           intptrcast::GlobalState::int_to_ptr(int, memory)
-        }
+        intptrcast::GlobalState::int_to_ptr(int, memory)
     }
 
+    #[inline(always)]
     fn ptr_to_int(
-        ptr: Pointer<Self::PointerTag>,
         memory: &Memory<'mir, 'tcx, Self>,
+        ptr: Pointer<Self::PointerTag>,
     ) -> InterpResult<'tcx, u64> {
-        if memory.extra.rng.is_none() {
-            err!(ReadPointerAsBytes)
-        } else {
-            intptrcast::GlobalState::ptr_to_int(ptr, memory)
-        }
+        intptrcast::GlobalState::ptr_to_int(ptr, memory)
     }
 }