Rustup
This commit is contained in:
parent
d289c0f464
commit
753da676ba
9 changed files with 113 additions and 128 deletions
|
|
@ -5,6 +5,7 @@ extern crate miri;
|
|||
extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate env_logger;
|
||||
extern crate log_settings;
|
||||
extern crate syntax;
|
||||
|
|
@ -17,7 +18,8 @@ use rustc_driver::driver::{CompileState, CompileController};
|
|||
use rustc::session::config::{self, Input, ErrorOutputType};
|
||||
use rustc::hir::{self, itemlikevisit};
|
||||
use rustc::ty::TyCtxt;
|
||||
use syntax::ast::{self, MetaItemKind, NestedMetaItemKind};
|
||||
use rustc_trans_utils::trans_crate::TransCrate;
|
||||
use syntax::ast;
|
||||
use std::path::PathBuf;
|
||||
|
||||
struct MiriCompilerCalls {
|
||||
|
|
@ -61,6 +63,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
|
|||
}
|
||||
fn late_callback(
|
||||
&mut self,
|
||||
trans: &TransCrate,
|
||||
matches: &getopts::Matches,
|
||||
sess: &Session,
|
||||
cstore: &CrateStore,
|
||||
|
|
@ -68,7 +71,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
|
|||
odir: &Option<PathBuf>,
|
||||
ofile: &Option<PathBuf>,
|
||||
) -> Compilation {
|
||||
self.default.late_callback(matches, sess, cstore, input, odir, ofile)
|
||||
self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile)
|
||||
}
|
||||
fn build_controller(
|
||||
&mut self,
|
||||
|
|
@ -98,11 +101,9 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
state.session.abort_if_errors();
|
||||
|
||||
let tcx = state.tcx.unwrap();
|
||||
let limits = resource_limits_from_attributes(state);
|
||||
|
||||
if std::env::args().any(|arg| arg == "--test") {
|
||||
struct Visitor<'a, 'tcx: 'a>(
|
||||
miri::ResourceLimits,
|
||||
TyCtxt<'a, 'tcx, 'tcx>,
|
||||
&'a CompileState<'a, 'tcx>
|
||||
);
|
||||
|
|
@ -113,13 +114,13 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
attr.name().map_or(false, |n| n == "test")
|
||||
})
|
||||
{
|
||||
let did = self.1.hir.body_owner_def_id(body_id);
|
||||
let did = self.0.hir.body_owner_def_id(body_id);
|
||||
println!(
|
||||
"running test: {}",
|
||||
self.1.def_path_debug_str(did),
|
||||
self.0.def_path_debug_str(did),
|
||||
);
|
||||
miri::eval_main(self.1, did, None, self.0);
|
||||
self.2.session.abort_if_errors();
|
||||
miri::eval_main(self.0, did, None);
|
||||
self.1.session.abort_if_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,7 +128,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
|
||||
}
|
||||
state.hir_crate.unwrap().visit_all_item_likes(
|
||||
&mut Visitor(limits, tcx, state),
|
||||
&mut Visitor(tcx, state),
|
||||
);
|
||||
} else if let Some((entry_node_id, _)) = *state.session.entry_fn.borrow() {
|
||||
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
|
||||
|
|
@ -138,7 +139,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
None
|
||||
}
|
||||
});
|
||||
miri::eval_main(tcx, entry_def_id, start_wrapper, limits);
|
||||
miri::eval_main(tcx, entry_def_id, start_wrapper);
|
||||
|
||||
state.session.abort_if_errors();
|
||||
} else {
|
||||
|
|
@ -146,50 +147,6 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn resource_limits_from_attributes(state: &CompileState) -> miri::ResourceLimits {
|
||||
let mut limits = miri::ResourceLimits::default();
|
||||
let krate = state.hir_crate.as_ref().unwrap();
|
||||
let err_msg = "miri attributes need to be in the form `miri(key = value)`";
|
||||
let extract_int = |lit: &syntax::ast::Lit| -> u128 {
|
||||
match lit.node {
|
||||
syntax::ast::LitKind::Int(i, _) => i,
|
||||
_ => {
|
||||
state.session.span_fatal(
|
||||
lit.span,
|
||||
"expected an integer literal",
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for attr in krate.attrs.iter().filter(|a| {
|
||||
a.name().map_or(false, |n| n == "miri")
|
||||
})
|
||||
{
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
for item in items {
|
||||
if let NestedMetaItemKind::MetaItem(ref inner) = item.node {
|
||||
if let MetaItemKind::NameValue(ref value) = inner.node {
|
||||
match &inner.name().as_str()[..] {
|
||||
"memory_size" => limits.memory_size = extract_int(value) as u64,
|
||||
"step_limit" => limits.step_limit = extract_int(value) as u64,
|
||||
"stack_limit" => limits.stack_limit = extract_int(value) as usize,
|
||||
_ => state.session.span_err(item.span, "unknown miri attribute"),
|
||||
}
|
||||
} else {
|
||||
state.session.span_err(inner.span, err_msg);
|
||||
}
|
||||
} else {
|
||||
state.session.span_err(item.span, err_msg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.session.span_err(attr.span, err_msg);
|
||||
}
|
||||
}
|
||||
limits
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
let format = |formatter: &mut env_logger::fmt::Formatter, record: &log::Record| {
|
||||
use std::io::Write;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ use syntax::codemap::Span;
|
|||
|
||||
use std::mem;
|
||||
|
||||
use rustc::traits;
|
||||
|
||||
use super::*;
|
||||
|
||||
use tls::MemoryExt;
|
||||
|
|
@ -49,7 +47,7 @@ pub trait EvalContextExt<'tcx> {
|
|||
fn write_null(&mut self, dest: Place, dest_ty: Ty<'tcx>) -> EvalResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
|
||||
fn eval_fn_call(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
|
|
@ -385,13 +383,17 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
promoted: None,
|
||||
};
|
||||
// compute global if not cached
|
||||
let val = match self.tcx.interpret_interner.borrow().get_cached(cid) {
|
||||
Some(ptr) => MemoryPointer::new(ptr, 0).into(),
|
||||
None => eval_body(self.tcx, instance, ty::ParamEnv::empty(traits::Reveal::All))?.0,
|
||||
let value: Value = match self.tcx.interpret_interner.get_cached(instance.def_id()) {
|
||||
Some(ptr) => {
|
||||
Value::ByRef(MemoryPointer::new(ptr, 0).into(), name_align)
|
||||
}
|
||||
None => {
|
||||
let res: Option<(Value, Pointer, Ty)> = eval_body(self.tcx.tcx, cid, ty::ParamEnv::reveal_all());
|
||||
res.ok_or_else(||EvalErrorKind::MachineError("<already reported>".to_string()))?.0
|
||||
},
|
||||
};
|
||||
let val = self.value_to_primval(ValTy { value: Value::ByRef(val, name_align),
|
||||
ty: args[0].ty })?.to_u64()?;
|
||||
if val == name {
|
||||
let value = self.value_to_primval(ValTy { value, ty: args[0].ty })?.to_u64()?;
|
||||
if value == name {
|
||||
result = Some(path_value);
|
||||
break;
|
||||
}
|
||||
|
|
@ -420,7 +422,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
};
|
||||
|
||||
// Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t.
|
||||
let key_type = args[0].ty.builtin_deref(true, ty::LvaluePreference::NoPreference)
|
||||
let key_type = args[0].ty.builtin_deref(true)
|
||||
.ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
|
||||
let key_size = self.layout_of(key_type)?.size;
|
||||
|
||||
|
|
@ -502,7 +504,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
for item in mem::replace(&mut items, Default::default()).iter() {
|
||||
if item.ident.name == *segment {
|
||||
if path_it.peek().is_none() {
|
||||
return Some(ty::Instance::mono(self.tcx, item.def.def_id()));
|
||||
return Some(ty::Instance::mono(self.tcx.tcx, item.def.def_id()));
|
||||
}
|
||||
|
||||
items = self.tcx.item_children(item.def.def_id());
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub trait EvalContextExt<'tcx> {
|
|||
) -> EvalResult<'tcx, Pointer>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
|
||||
fn wrapping_pointer_offset(
|
||||
&self,
|
||||
ptr: Pointer,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use rustc::mir;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::ty::layout::{TyLayout, LayoutOf};
|
||||
use rustc::ty;
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ pub trait EvalContextExt<'tcx> {
|
|||
) -> EvalResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
|
||||
fn call_intrinsic(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
|
|
@ -349,7 +348,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
match dest {
|
||||
Place::Local { frame, local } => self.modify_local(frame, local, init)?,
|
||||
Place::Ptr {
|
||||
ptr: ptr,
|
||||
ptr,
|
||||
align: _align,
|
||||
extra: PlaceExtra::None,
|
||||
} => self.memory.write_repeat(ptr, 0, size)?,
|
||||
|
|
@ -381,8 +380,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
|
||||
"needs_drop" => {
|
||||
let ty = substs.type_at(0);
|
||||
let env = ty::ParamEnv::empty(Reveal::All);
|
||||
let needs_drop = ty.needs_drop(self.tcx, env);
|
||||
let env = ty::ParamEnv::reveal_all();
|
||||
let needs_drop = ty.needs_drop(self.tcx.tcx, env);
|
||||
self.write_primval(
|
||||
dest,
|
||||
PrimVal::from_bool(needs_drop),
|
||||
|
|
@ -542,10 +541,10 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
|
||||
"transmute" => {
|
||||
let src_ty = substs.type_at(0);
|
||||
let src_align = self.layout_of(src_ty)?.align;
|
||||
let _src_align = self.layout_of(src_ty)?.align;
|
||||
let ptr = self.force_allocation(dest)?.to_ptr()?;
|
||||
let dest_align = self.layout_of(substs.type_at(1))?.align;
|
||||
self.write_value_to_ptr(args[0].value, ptr.into(), dest_align, src_ty);
|
||||
self.write_value_to_ptr(args[0].value, ptr.into(), dest_align, src_ty).unwrap();
|
||||
}
|
||||
|
||||
"unchecked_shl" => {
|
||||
|
|
@ -626,7 +625,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
match dest {
|
||||
Place::Local { frame, local } => self.modify_local(frame, local, uninit)?,
|
||||
Place::Ptr {
|
||||
ptr: ptr,
|
||||
ptr,
|
||||
align: _align,
|
||||
extra: PlaceExtra::None,
|
||||
} => self.memory.mark_definedness(ptr, size, false)?,
|
||||
|
|
|
|||
81
miri/lib.rs
81
miri/lib.rs
|
|
@ -22,7 +22,6 @@ use rustc::ty::{self, TyCtxt};
|
|||
use rustc::ty::layout::{TyLayout, LayoutOf};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir;
|
||||
use rustc::traits;
|
||||
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::codemap::Span;
|
||||
|
|
@ -56,14 +55,13 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
main_id: DefId,
|
||||
start_wrapper: Option<DefId>,
|
||||
limits: ResourceLimits,
|
||||
) {
|
||||
fn run_main<'a, 'tcx: 'a>(
|
||||
ecx: &mut rustc_mir::interpret::EvalContext<'a, 'tcx, Evaluator<'tcx>>,
|
||||
fn run_main<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||
ecx: &mut rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>,
|
||||
main_id: DefId,
|
||||
start_wrapper: Option<DefId>,
|
||||
) -> EvalResult<'tcx> {
|
||||
let main_instance = ty::Instance::mono(ecx.tcx, main_id);
|
||||
let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id);
|
||||
let main_mir = ecx.load_mir(main_instance.def)?;
|
||||
let mut cleanup_ptr = None; // Pointer to be deallocated when we are done
|
||||
|
||||
|
|
@ -78,8 +76,8 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
|||
let main_ret_ty = ecx.tcx.fn_sig(main_id).output();
|
||||
let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
|
||||
let start_instance = ty::Instance::resolve(
|
||||
ecx.tcx,
|
||||
ty::ParamEnv::empty(traits::Reveal::All),
|
||||
ecx.tcx.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
start_id,
|
||||
ecx.tcx.mk_substs(
|
||||
::std::iter::once(ty::subst::Kind::from(main_ret_ty)))).unwrap();
|
||||
|
|
@ -112,8 +110,8 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
|||
// First argument: pointer to main()
|
||||
let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance);
|
||||
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
|
||||
let main_ty = main_instance.ty(ecx.tcx);
|
||||
let main_ptr_ty = ecx.tcx.mk_fn_ptr(main_ty.fn_sig(ecx.tcx));
|
||||
let main_ty = main_instance.ty(ecx.tcx.tcx);
|
||||
let main_ptr_ty = ecx.tcx.mk_fn_ptr(main_ty.fn_sig(ecx.tcx.tcx));
|
||||
ecx.write_value(
|
||||
ValTy {
|
||||
value: Value::ByVal(PrimVal::Ptr(main_ptr)),
|
||||
|
|
@ -136,7 +134,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
|||
let ptr_align = ecx.tcx.data_layout.pointer_align;
|
||||
let foo_ptr = ecx.memory.allocate(ptr_size, ptr_align, None)?;
|
||||
ecx.memory.write_primval(foo_ptr, ptr_align, PrimVal::Ptr(foo.into()), ptr_size, false)?;
|
||||
ecx.memory.mark_static_initalized(foo_ptr.alloc_id, Mutability::Immutable)?;
|
||||
ecx.memory.mark_static_initialized(foo_ptr.alloc_id, Mutability::Immutable)?;
|
||||
ecx.write_ptr(dest, foo_ptr.into(), ty)?;
|
||||
|
||||
assert!(args.next().is_none(), "start lang item has more arguments than expected");
|
||||
|
|
@ -166,7 +164,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
let mut ecx = EvalContext::new(tcx, ty::ParamEnv::empty(traits::Reveal::All), limits, Default::default(), Default::default());
|
||||
let mut ecx = EvalContext::new(tcx.at(syntax::codemap::DUMMY_SP), ty::ParamEnv::reveal_all(), Default::default(), Default::default());
|
||||
match run_main(&mut ecx, main_id, start_wrapper) {
|
||||
Ok(()) => {
|
||||
let leaks = ecx.memory().leak_report();
|
||||
|
|
@ -175,7 +173,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
|||
}
|
||||
}
|
||||
Err(mut e) => {
|
||||
ecx.report(&mut e);
|
||||
ecx.report(&mut e, true, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -213,13 +211,13 @@ pub struct MemoryData<'tcx> {
|
|||
locks: HashMap<AllocId, RangeMap<LockInfo<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
||||
impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
||||
type MemoryData = MemoryData<'tcx>;
|
||||
type MemoryKinds = memory::MemoryKind;
|
||||
|
||||
/// Returns Ok() when the function was handled, fail otherwise
|
||||
fn eval_fn_call<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
destination: Option<(Place, mir::BasicBlock)>,
|
||||
args: &[ValTy<'tcx>],
|
||||
|
|
@ -230,7 +228,7 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
}
|
||||
|
||||
fn call_intrinsic<'a>(
|
||||
ecx: &mut rustc_mir::interpret::EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &mut rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[ValTy<'tcx>],
|
||||
dest: Place,
|
||||
|
|
@ -241,7 +239,7 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
}
|
||||
|
||||
fn try_ptr_op<'a>(
|
||||
ecx: &rustc_mir::interpret::EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
bin_op: mir::BinOp,
|
||||
left: PrimVal,
|
||||
left_ty: ty::Ty<'tcx>,
|
||||
|
|
@ -251,17 +249,35 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
ecx.ptr_op(bin_op, left, left_ty, right, right_ty)
|
||||
}
|
||||
|
||||
fn mark_static_initialized(m: memory::MemoryKind) -> EvalResult<'tcx> {
|
||||
use memory::MemoryKind::*;
|
||||
fn mark_static_initialized<'a>(
|
||||
_mem: &mut Memory<'a, 'mir, 'tcx, Self>,
|
||||
_id: AllocId,
|
||||
_mutability: Mutability,
|
||||
) -> EvalResult<'tcx, bool> {
|
||||
/*use memory::MemoryKind::*;
|
||||
match m {
|
||||
// FIXME: This could be allowed, but not for env vars set during miri execution
|
||||
Env => err!(Unimplemented("statics can't refer to env vars".to_owned())),
|
||||
_ => Ok(()),
|
||||
}
|
||||
_ => Ok(false), // TODO: What does the bool mean?
|
||||
}*/
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn init_static<'a>(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
cid: GlobalId<'tcx>,
|
||||
) -> EvalResult<'tcx, AllocId> {
|
||||
let def_id = cid.instance.def_id();
|
||||
let ty = ecx.tcx.type_of(def_id);
|
||||
let layout = ecx.tcx.layout_of(ty::ParamEnvAnd {
|
||||
param_env: ty::ParamEnv::reveal_all(),
|
||||
value: ty
|
||||
}).expect("Couldn't compute layout for the type of a static");
|
||||
ecx.memory.allocate(layout.size.bytes(), layout.align, None).map(|mptr|mptr.alloc_id)
|
||||
}
|
||||
|
||||
fn box_alloc<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
dest: Place,
|
||||
) -> EvalResult<'tcx> {
|
||||
|
|
@ -269,7 +285,7 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
|
||||
// Call the `exchange_malloc` lang item
|
||||
let malloc = ecx.tcx.lang_items().exchange_malloc_fn().unwrap();
|
||||
let malloc = ty::Instance::mono(ecx.tcx, malloc);
|
||||
let malloc = ty::Instance::mono(ecx.tcx.tcx, malloc);
|
||||
let malloc_mir = ecx.load_mir(malloc.def)?;
|
||||
ecx.push_stack_frame(
|
||||
malloc,
|
||||
|
|
@ -311,7 +327,7 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
}
|
||||
|
||||
fn global_item_with_linkage<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
mutability: Mutability,
|
||||
) -> EvalResult<'tcx> {
|
||||
|
|
@ -325,19 +341,16 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
None,
|
||||
)?;
|
||||
ecx.memory.write_ptr_sized_unsigned(ptr, ptr_align, PrimVal::Bytes(0))?;
|
||||
ecx.memory.mark_static_initalized(ptr.alloc_id, mutability)?;
|
||||
ecx.tcx.interpret_interner.borrow_mut().cache(
|
||||
GlobalId {
|
||||
instance,
|
||||
promoted: None,
|
||||
},
|
||||
ecx.memory.mark_static_initialized(ptr.alloc_id, mutability)?;
|
||||
ecx.tcx.interpret_interner.cache(
|
||||
instance.def_id(),
|
||||
ptr.alloc_id,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_locks<'a>(
|
||||
mem: &Memory<'a, 'tcx, Self>,
|
||||
mem: &Memory<'a, 'mir, 'tcx, Self>,
|
||||
ptr: MemoryPointer,
|
||||
size: u64,
|
||||
access: AccessKind,
|
||||
|
|
@ -346,14 +359,14 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
}
|
||||
|
||||
fn add_lock<'a>(
|
||||
mem: &mut Memory<'a, 'tcx, Self>,
|
||||
mem: &mut Memory<'a, 'mir, 'tcx, Self>,
|
||||
id: AllocId,
|
||||
) {
|
||||
mem.data.locks.insert(id, RangeMap::new());
|
||||
}
|
||||
|
||||
fn free_lock<'a>(
|
||||
mem: &mut Memory<'a, 'tcx, Self>,
|
||||
mem: &mut Memory<'a, 'mir, 'tcx, Self>,
|
||||
id: AllocId,
|
||||
len: u64,
|
||||
) -> EvalResult<'tcx> {
|
||||
|
|
@ -379,14 +392,14 @@ impl<'tcx> Machine<'tcx> for Evaluator<'tcx> {
|
|||
}
|
||||
|
||||
fn end_region<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
reg: Option<::rustc::middle::region::Scope>,
|
||||
) -> EvalResult<'tcx> {
|
||||
ecx.end_region(reg)
|
||||
}
|
||||
|
||||
fn validation_op<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
op: ::rustc::mir::ValidationOp,
|
||||
operand: &::rustc::mir::ValidationOperand<'tcx, ::rustc::mir::Place<'tcx>>,
|
||||
) -> EvalResult<'tcx> {
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ pub trait MemoryExt<'tcx> {
|
|||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evaluator<'tcx>> {
|
||||
fn check_locks(
|
||||
&self,
|
||||
ptr: MemoryPointer,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ pub trait EvalContextExt<'tcx> {
|
|||
) -> EvalResult<'tcx, (PrimVal, bool)>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
|
||||
fn ptr_op(
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
|
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
match bin_op {
|
||||
Offset if left_kind == Ptr && right_kind == usize => {
|
||||
let pointee_ty = left_ty
|
||||
.builtin_deref(true, ty::LvaluePreference::NoPreference)
|
||||
.builtin_deref(true)
|
||||
.expect("Offset called on non-ptr type")
|
||||
.ty;
|
||||
let ptr = self.pointer_offset(
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub trait EvalContextExt<'tcx> {
|
|||
fn run_tls_dtors(&mut self) -> EvalResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evaluator<'tcx>> {
|
||||
fn create_tls_key(&mut self, dtor: Option<ty::Instance<'tcx>>) -> TlsKey {
|
||||
let new_key = self.data.next_thread_local;
|
||||
self.data.next_thread_local += 1;
|
||||
|
|
@ -106,7 +106,7 @@ impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator<'tcx>> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx: 'a> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>> {
|
||||
fn run_tls_dtors(&mut self) -> EvalResult<'tcx> {
|
||||
let mut dtor = self.memory.fetch_tls_dtor(None)?;
|
||||
// FIXME: replace loop by some structure that works with stepping
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
use rustc::hir::{self, Mutability};
|
||||
use rustc::hir::Mutability::*;
|
||||
use rustc::mir::{self, ValidationOp, ValidationOperand};
|
||||
use rustc::ty::{self, Ty, TypeFoldable, TyCtxt};
|
||||
use rustc::mir::interpret::GlobalId;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, TyCtxt, Instance};
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc::ty::subst::{Substs, Subst};
|
||||
use rustc::traits;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::traits::Reveal;
|
||||
use rustc::middle::region;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_mir::interpret::HasMemory;
|
||||
use rustc_mir::interpret::{HasMemory, eval_body};
|
||||
|
||||
use super::{EvalContext, Place, PlaceExtra, ValTy};
|
||||
use rustc::mir::interpret::{DynamicLifetime, AccessKind, EvalErrorKind, Value, EvalError, EvalResult};
|
||||
|
|
@ -108,7 +109,7 @@ pub(crate) trait EvalContextExt<'tcx> {
|
|||
) -> EvalResult<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'tcx>> {
|
||||
impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
|
||||
fn abstract_place_projection(&self, proj: &mir::PlaceProjection<'tcx>) -> EvalResult<'tcx, AbsPlaceProjection<'tcx>> {
|
||||
use self::mir::ProjectionElem::*;
|
||||
|
||||
|
|
@ -117,7 +118,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
Field(f, _) => Field(f, ()),
|
||||
Index(v) => {
|
||||
let value = self.frame().get_local(v)?;
|
||||
let ty = self.tcx.types.usize;
|
||||
let ty = self.tcx.tcx.types.usize;
|
||||
let n = self.value_to_primval(ValTy { value, ty })?.to_u64()?;
|
||||
Index(n)
|
||||
},
|
||||
|
|
@ -152,7 +153,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
// because other crates may have been compiled with mir-emit-validate > 0. Ignore those
|
||||
// commands. This makes mir-emit-validate also a flag to control whether miri will do
|
||||
// validation or not.
|
||||
if self.tcx.sess.opts.debugging_opts.mir_emit_validate == 0 {
|
||||
if self.tcx.tcx.sess.opts.debugging_opts.mir_emit_validate == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
debug_assert!(self.memory.cur_frame == self.cur_frame());
|
||||
|
|
@ -187,7 +188,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
|
||||
// We need to monomorphize ty *without* erasing lifetimes
|
||||
trace!("validation_op1: {:?}", operand.ty.sty);
|
||||
let ty = operand.ty.subst(self.tcx, self.substs());
|
||||
let ty = operand.ty.subst(self.tcx.tcx, self.substs());
|
||||
trace!("validation_op2: {:?}", operand.ty.sty);
|
||||
let place = self.eval_place(&operand.place)?;
|
||||
let abs_place = self.abstract_place(&operand.place)?;
|
||||
|
|
@ -250,7 +251,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
}
|
||||
|
||||
fn normalize_type_unerased(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
return normalize_associated_type(self.tcx, &ty);
|
||||
return normalize_associated_type(self.tcx.tcx, &ty);
|
||||
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
|
||||
|
|
@ -356,7 +357,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
where
|
||||
T: MyTransNormalize<'tcx>,
|
||||
{
|
||||
let param_env = ty::ParamEnv::empty(Reveal::All);
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
|
||||
if !value.has_projections() {
|
||||
return value.clone();
|
||||
|
|
@ -383,7 +384,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
let tcx = self.tcx;
|
||||
let tcx = self.tcx.tcx;
|
||||
Ok(match layout.ty.sty {
|
||||
ty::TyBool |
|
||||
ty::TyChar |
|
||||
|
|
@ -393,6 +394,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
ty::TyFnPtr(_) |
|
||||
ty::TyNever |
|
||||
ty::TyFnDef(..) |
|
||||
ty::TyGeneratorWitness(..) |
|
||||
ty::TyDynamic(..) |
|
||||
ty::TyForeign(..) => {
|
||||
bug!("TyLayout::field_type({:?}): not applicable", layout)
|
||||
|
|
@ -437,7 +439,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
substs.field_tys(def_id, tcx).nth(i).unwrap()
|
||||
}
|
||||
|
||||
ty::TyTuple(tys, _) => tys[i],
|
||||
ty::TyTuple(tys) => tys[i],
|
||||
|
||||
// SIMD vector types.
|
||||
ty::TyAdt(def, ..) if def.repr.simd() => {
|
||||
|
|
@ -558,6 +560,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
TyAdt(adt, _) if adt.is_box() => true,
|
||||
TySlice(_) | TyAdt(_, _) | TyTuple(..) | TyClosure(..) | TyArray(..) |
|
||||
TyDynamic(..) | TyGenerator(..) | TyForeign(_) => false,
|
||||
TyGeneratorWitness(..) => bug!("I'm not sure what to return here"),
|
||||
TyParam(_) | TyInfer(_) | TyProjection(_) | TyAnon(..) | TyError => {
|
||||
bug!("I got an incomplete/unnormalized type for validation")
|
||||
}
|
||||
|
|
@ -725,7 +728,18 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
Ok(())
|
||||
}
|
||||
TyArray(elem_ty, len) => {
|
||||
let len = len.val.to_const_int().unwrap().to_u64().unwrap();
|
||||
let len_val = match len.val {
|
||||
ConstVal::Unevaluated(def_id, substs) => {
|
||||
eval_body(self.tcx.tcx, GlobalId {
|
||||
instance: Instance::new(def_id, substs),
|
||||
promoted: None,
|
||||
}, ty::ParamEnv::reveal_all())
|
||||
.ok_or_else(||EvalErrorKind::MachineError("<already reported>".to_string()))?
|
||||
.0
|
||||
}
|
||||
ConstVal::Value(val) => val,
|
||||
};
|
||||
let len = ConstVal::Value(len_val).unwrap_u64();
|
||||
for i in 0..len {
|
||||
let inner_place = self.place_index(query.place.1, query.ty, i as u64)?;
|
||||
self.validate(
|
||||
|
|
@ -759,7 +773,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
Ok(())
|
||||
}
|
||||
TyAdt(adt, _) => {
|
||||
if Some(adt.did) == self.tcx.lang_items().unsafe_cell_type() &&
|
||||
if Some(adt.did) == self.tcx.tcx.lang_items().unsafe_cell_type() &&
|
||||
query.mutbl == MutImmutable
|
||||
{
|
||||
// No locks for shared unsafe cells. Also no other validation, the only field is private anyway.
|
||||
|
|
@ -771,8 +785,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator<'
|
|||
let discr = self.read_discriminant_value(query.place.1, query.ty)?;
|
||||
|
||||
// Get variant index for discriminant
|
||||
let variant_idx = adt.discriminants(self.tcx).position(|variant_discr| {
|
||||
variant_discr.to_u128_unchecked() == discr
|
||||
let variant_idx = adt.discriminants(self.tcx.tcx).position(|variant_discr| {
|
||||
variant_discr.val == discr
|
||||
});
|
||||
let variant_idx = match variant_idx {
|
||||
Some(val) => val,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue