diff options
| author | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-01-25 08:06:53 +0100 |
|---|---|---|
| committer | Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de> | 2018-03-08 08:34:09 +0100 |
| commit | 34772aad63f9463f76ed5b16a21ae1d5a9729c6d (patch) | |
| tree | e607c5f99ba09fd300cad8f733def5cdb6931e1b | |
| parent | d3e2f48c8cb3ee32fecf5a7a525fa51d10ab4035 (diff) | |
| download | rust-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.rs | 24 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 27 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/machine.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/place.rs | 29 |
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, |
