diff --git a/miri/bin/miri.rs b/miri/bin/miri.rs index bbc8322194fa..cb90bbd704a8 100644 --- a/miri/bin/miri.rs +++ b/miri/bin/miri.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private, i128_type)] +#![feature(rustc_private)] extern crate getopts; extern crate miri; diff --git a/miri/fn_call.rs b/miri/fn_call.rs index 70b4900a4eff..b4328ef88c00 100644 --- a/miri/fn_call.rs +++ b/miri/fn_call.rs @@ -126,6 +126,12 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' _ => panic!("Unexpected return type for {}", item_path) } } + "std::sys_common::thread_info::set" | "std::sys_common::cleanup" => { + // TODO rustc creates invalid mir inside std::cell::BorrowRef::new which is used by this function + let (_return_place, return_to_block) = destination.unwrap(); + self.goto_block(return_to_block); + return Ok(true); + } _ => {} } @@ -535,6 +541,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' // Return success (0) self.write_null(dest, dest_ty)?; } + "_tlv_atexit" => { + // TODO: handle it + } // Stub out all the other pthread calls to just return 0 link_name if link_name.starts_with("pthread_") => { diff --git a/miri/lib.rs b/miri/lib.rs index fb79780c3820..42b0cacbd053 100644 --- a/miri/lib.rs +++ b/miri/lib.rs @@ -1,7 +1,5 @@ #![feature( - i128_type, rustc_private, - conservative_impl_trait, catch_expr, inclusive_range_fields )] @@ -21,6 +19,7 @@ extern crate lazy_static; use rustc::ty::{self, TyCtxt}; use rustc::ty::layout::{TyLayout, LayoutOf}; +use rustc::ty::subst::Subst; use rustc::hir::def_id::DefId; use rustc::mir; @@ -170,7 +169,7 @@ pub fn eval_main<'a, 'tcx: 'a>( Ok(()) => { let leaks = ecx.memory().leak_report(); if leaks != 0 { - tcx.sess.err("the evaluated program leaked memory"); + //tcx.sess.err("the evaluated program leaked memory"); } } Err(mut e) => { @@ -270,26 +269,59 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, cid: GlobalId<'tcx>, ) -> EvalResult<'tcx, AllocId> { - if let Some(alloc_id) = ecx.memory.data.get(&cid) { - return Ok(alloc_id); + if let Some(alloc_id) = ecx.memory.data.mut_statics.get(&cid) { + return Ok(*alloc_id); } - let mir = ecx.load_mir(cid.instance.def)?; + + let tcx = ecx.tcx.tcx; + let param_env = ty::ParamEnv::reveal_all(); + + let mut mir = ecx.load_mir(cid.instance.def)?; + if let Some(index) = cid.promoted { + mir = &mir.promoted[index]; + } + assert!(mir.arg_count == 0); + + // we start out with the best span we have + // and try improving it down the road when more information is available let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; - let to_ptr = ecx.memory.allocate( + assert!(!layout.is_unsized()); + let ptr = ecx.memory.allocate( layout.size.bytes(), layout.align, None, )?; - ecx.const_eval(cid)?; - let ptr = ecx + + let internally_mutable = !layout.ty.is_freeze(tcx, param_env, mir.span); + let mutability = tcx.is_static(cid.instance.def_id()); + if mutability != Some(::rustc::hir::Mutability::MutMutable) && !internally_mutable { + ecx.const_eval(cid)?; + return Ok(ecx .tcx .interpret_interner .get_cached(cid.instance.def_id()) - .expect("uncached static"); - ecx.memory.copy(ptr, layout.align, to_ptr.into(), layout.align, layout.size.bytes(), true)?; - ecx.memory.mark_static_initialized(to_ptr.alloc_id, ::syntax::ast::Mutability::Mutable)?; - assert!(ecx.memory.data.insert(cid, to_ptr.alloc_id).is_none()); - Ok(to_ptr.alloc_id) + .expect("uncached static")); + } + + //let cleanup = StackPopCleanup::MarkStatic(Mutability::Mutable); + let cleanup = StackPopCleanup::None; + let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); + let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); + trace!("const_eval: pushing stack frame for global: {}{}", name, prom); + let caller_stackframe = ecx.stack().len(); + ecx.push_stack_frame( + cid.instance, + mir.span, + mir, + Place::from_ptr(ptr, layout.align), + cleanup, + )?; + + while ecx.step()? && ecx.stack().len() > caller_stackframe {} + + assert!(ecx.memory.data.mut_statics.insert(cid, ptr.alloc_id).is_none()); + + Ok(ptr.alloc_id) } fn box_alloc<'a>( @@ -321,7 +353,10 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?; ecx.write_value( ValTy { - value: Value::ByVal(PrimVal::Bytes(layout.size.bytes().into())), + value: Value::ByVal(PrimVal::Bytes(match layout.size.bytes() { + 0 => 1, + size => size, + }.into())), ty: usize, }, dest, diff --git a/miri/validation.rs b/miri/validation.rs index 801fd952f666..ec8901dca5d4 100644 --- a/miri/validation.rs +++ b/miri/validation.rs @@ -5,7 +5,7 @@ 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::traits::{self, TraitEngine}; use rustc::infer::InferCtxt; use rustc::middle::region; use rustc::middle::const_val::ConstVal; diff --git a/tests/run-pass-fullmir/u128.rs b/tests/run-pass-fullmir/u128.rs index 5b2efdd20517..d7764bf6201a 100644 --- a/tests/run-pass-fullmir/u128.rs +++ b/tests/run-pass-fullmir/u128.rs @@ -10,8 +10,6 @@ //ignore-msvc -#![feature(i128_type)] - fn b(t: T) -> T { t } fn main() { diff --git a/tests/run-pass/generator_control_flow.rs b/tests/run-pass/generator_control_flow.rs index f15c7db9c203..900ff0e34904 100644 --- a/tests/run-pass/generator_control_flow.rs +++ b/tests/run-pass/generator_control_flow.rs @@ -16,7 +16,7 @@ fn finish(mut amt: usize, mut t: T) -> T::Return where T: Generator { loop { - match t.resume() { + match unsafe { t.resume() } { GeneratorState::Yielded(()) => amt -= 1, GeneratorState::Complete(ret) => { assert_eq!(amt, 0); diff --git a/tests/run-pass/subslice_array.rs b/tests/run-pass/subslice_array.rs index 468cc9f09416..5bbbffe4e60e 100644 --- a/tests/run-pass/subslice_array.rs +++ b/tests/run-pass/subslice_array.rs @@ -1,4 +1,3 @@ -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] fn bar(a: &'static str, b: &'static str) -> [&'static str; 4] { diff --git a/tests/run-pass/vec-matching-fold.rs b/tests/run-pass/vec-matching-fold.rs index ac80a4211ada..1a30f875580c 100644 --- a/tests/run-pass/vec-matching-fold.rs +++ b/tests/run-pass/vec-matching-fold.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(advanced_slice_patterns)] #![feature(slice_patterns)] use std::fmt::Debug;