From 753da676bacd058cd6ef58aa23f02b787381421e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 14 Jan 2018 18:59:13 +0100 Subject: [PATCH] Rustup --- miri/bin/miri.rs | 65 +++++++------------------------------ miri/fn_call.rs | 24 +++++++------- miri/helpers.rs | 2 +- miri/intrinsic.rs | 15 ++++----- miri/lib.rs | 81 +++++++++++++++++++++++++++------------------- miri/locks.rs | 2 +- miri/operator.rs | 4 +-- miri/tls.rs | 4 +-- miri/validation.rs | 44 ++++++++++++++++--------- 9 files changed, 113 insertions(+), 128 deletions(-) diff --git a/miri/bin/miri.rs b/miri/bin/miri.rs index c3d422a6ff5d..bbc8322194fa 100644 --- a/miri/bin/miri.rs +++ b/miri/bin/miri.rs @@ -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, ofile: &Option, ) -> 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; diff --git a/miri/fn_call.rs b/miri/fn_call.rs index b46f712818f2..d07929e0d560 100644 --- a/miri/fn_call.rs +++ b/miri/fn_call.rs @@ -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("".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()); diff --git a/miri/helpers.rs b/miri/helpers.rs index 0e541cf29208..3dd499f7a62e 100644 --- a/miri/helpers.rs +++ b/miri/helpers.rs @@ -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, diff --git a/miri/intrinsic.rs b/miri/intrinsic.rs index 3357f0bba392..5047ab5b6ac2 100644 --- a/miri/intrinsic.rs +++ b/miri/intrinsic.rs @@ -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)?, diff --git a/miri/lib.rs b/miri/lib.rs index 091a3b7e1dfb..99bc91a17177 100644 --- a/miri/lib.rs +++ b/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, - 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, ) -> 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>>, } -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> { diff --git a/miri/locks.rs b/miri/locks.rs index f0e8815c4fc5..677b0454a546 100644 --- a/miri/locks.rs +++ b/miri/locks.rs @@ -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, diff --git a/miri/operator.rs b/miri/operator.rs index 919997a5217c..220f8f9acd54 100644 --- a/miri/operator.rs +++ b/miri/operator.rs @@ -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( diff --git a/miri/tls.rs b/miri/tls.rs index 7f4f194c67f1..e55cbede2339 100644 --- a/miri/tls.rs +++ b/miri/tls.rs @@ -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>) -> 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 diff --git a/miri/validation.rs b/miri/validation.rs index 843dcd4041d7..801fd952f666 100644 --- a/miri/validation.rs +++ b/miri/validation.rs @@ -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("".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,