Allow writing mutable statics in miri by adding them to the Machine
This commit is contained in:
parent
d3e2f48c8c
commit
34772aad63
4 changed files with 47 additions and 42 deletions
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue