about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-01-25 08:06:53 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:34:09 +0100
commit34772aad63f9463f76ed5b16a21ae1d5a9729c6d (patch)
treee607c5f99ba09fd300cad8f733def5cdb6931e1b
parentd3e2f48c8cb3ee32fecf5a7a525fa51d10ab4035 (diff)
downloadrust-34772aad63f9463f76ed5b16a21ae1d5a9729c6d.tar.gz
rust-34772aad63f9463f76ed5b16a21ae1d5a9729c6d.zip
Allow writing mutable statics in miri by adding them to the Machine
-rw-r--r--src/librustc_mir/interpret/const_eval.rs24
-rw-r--r--src/librustc_mir/interpret/eval_context.rs27
-rw-r--r--src/librustc_mir/interpret/machine.rs9
-rw-r--r--src/librustc_mir/interpret/place.rs29
4 files changed, 47 insertions, 42 deletions
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 596baabba18..2a9e1cb57e4 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -1,6 +1,7 @@
 use rustc::hir;
-use rustc::middle::const_val::{ConstEvalErr, ConstVal};
+use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
 use rustc::middle::const_val::ErrKind::{TypeckError, CheckMatchError};
+use rustc::traits;
 use rustc::mir;
 use rustc::ty::{self, TyCtxt, Ty, Instance};
 use rustc::ty::layout::{self, LayoutOf};
@@ -326,6 +327,27 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
         Ok(false)
     }
 
+    fn init_static<'a>(
+        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+        cid: GlobalId<'tcx>,
+    ) -> EvalResult<'tcx, AllocId> {
+        let param_env = ty::ParamEnv::empty(traits::Reveal::All);
+        // ensure the static is computed
+        if let Err(err) = ecx.tcx.const_eval(param_env.and(cid)) {
+            match err.kind {
+                ErrKind::Miri(miri) => return Err(miri),
+                ErrKind::TypeckError => return err!(TypeckError),
+                other => bug!("const eval returned {:?}", other),
+            }
+        };
+        Ok(ecx
+            .tcx
+            .interpret_interner
+            .borrow()
+            .get_cached(cid.instance.def_id())
+            .expect("uncached static"))
+    }
+
     fn box_alloc<'a>(
         _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
         _ty: Ty<'tcx>,
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index dc66365bccb..1c60cda095c 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -1264,14 +1264,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                     self.memory.read_ptr_sized_unsigned(extra, ptr_align)?.to_ptr()?,
                 )),
                 ty::TySlice(..) | ty::TyStr => {
-                    match p.primval {
-                        PrimVal::Bytes(b) => bug!("slice ptr: {:x}", b),
-                        PrimVal::Undef => bug!("undef slice ptr"),
-                        _ => {},
-                    }
-                    Ok(
-                        p.to_value_with_len(self.memory.read_ptr_sized_unsigned(extra, ptr_align)?.to_bytes()? as u64),
-                    )
+                    let len = self
+                        .memory
+                        .read_ptr_sized_unsigned(extra, ptr_align)?
+                        .to_bytes()?;
+                    Ok(p.to_value_with_len(len as u64))
                 },
                 _ => bug!("unsized primval ptr read from {:?}", pointee_ty),
             }
@@ -1621,16 +1618,16 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
                 block.terminator().source_info.span
             });
             trace!("reporting const eval failure at {:?}", span);
-            let node_id = self
-                .stack()
-                .iter()
-                .rev()
-                .filter_map(|frame| self.tcx.hir.as_local_node_id(frame.instance.def_id()))
-                .next()
-                .expect("some part of a failing const eval must be local");
             let mut err = if as_err {
                 ::rustc::middle::const_val::struct_error(self.tcx, span, "constant evaluation error")
             } else {
+                let node_id = self
+                    .stack()
+                    .iter()
+                    .rev()
+                    .filter_map(|frame| self.tcx.hir.as_local_node_id(frame.instance.def_id()))
+                    .next()
+                    .expect("some part of a failing const eval must be local");
                 self.tcx.struct_span_lint_node(
                     ::rustc::lint::builtin::CONST_ERR,
                     node_id,
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index d5e57d3317c..5af0a053e92 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -2,7 +2,7 @@
 //! This separation exists to ensure that no fancy miri features like
 //! interpreting common C functions leak into CTFE.
 
-use rustc::mir::interpret::{AllocId, EvalResult, PrimVal, MemoryPointer, AccessKind};
+use rustc::mir::interpret::{AllocId, EvalResult, PrimVal, MemoryPointer, AccessKind, GlobalId};
 use super::{EvalContext, Place, ValTy, Memory};
 
 use rustc::mir;
@@ -66,6 +66,13 @@ pub trait Machine<'mir, 'tcx>: Sized {
         _mutability: Mutability,
     ) -> EvalResult<'tcx, bool>;
 
+    /// Called when requiring a pointer to a static. Non const eval can
+    /// create a mutable memory location for `static mut`
+    fn init_static<'a>(
+        ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
+        cid: GlobalId<'tcx>,
+    ) -> EvalResult<'tcx, AllocId>;
+
     /// Heap allocations via the `box` keyword
     ///
     /// Returns a pointer to the allocated memory
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 349ac630559..12725fb6dff 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -1,13 +1,11 @@
 use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
-use rustc::traits;
 use rustc_data_structures::indexed_vec::Idx;
 
 use rustc::mir::interpret::{GlobalId, Value, PrimVal, EvalResult, Pointer, MemoryPointer};
 use super::{EvalContext, Machine, ValTy};
 use interpret::memory::HasMemory;
-use rustc::middle::const_val::ErrKind;
 
 #[derive(Copy, Clone, Debug)]
 pub enum Place {
@@ -105,14 +103,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
             Local(mir::RETURN_PLACE) => err!(ReadFromReturnPointer),
             // Directly reading a local will always succeed
             Local(local) => self.frame().get_local(local).map(Some),
-            // Directly reading a static will always succeed
-            Static(ref static_) => {
-                let instance = ty::Instance::mono(self.tcx, static_.def_id);
-                self.read_global_as_value(GlobalId {
-                    instance,
-                    promoted: None,
-                }, self.place_ty(place)).map(Some)
-            }
+            // No fast path for statics. Reading from statics is rare and would require another
+            // Machine function to handle differently in miri.
+            Static(_) => Ok(None),
             Projection(ref proj) => self.try_read_place_projection(proj),
         }
     }
@@ -219,21 +212,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                         instance,
                         promoted: None
                     };
-                    let param_env = ty::ParamEnv::empty(traits::Reveal::All);
-                    // ensure the static is computed
-                    if let Err(err) = self.tcx.const_eval(param_env.and(cid)) {
-                        match err.kind {
-                            ErrKind::Miri(miri) => return Err(miri),
-                            ErrKind::TypeckError => return err!(TypeckError),
-                            other => bug!("const eval returned {:?}", other),
-                        }
-                    };
-                    let alloc = self
-                        .tcx
-                        .interpret_interner
-                        .borrow()
-                        .get_cached(static_.def_id)
-                        .expect("uncached static");
+                    let alloc = Machine::init_static(self, cid)?;
                     Place::Ptr {
                         ptr: MemoryPointer::new(alloc, 0).into(),
                         align: layout.align,