Auto merge of #46743 - oli-obk:miri, r=eddyb

Some miri cleanups

r? @eddyb
This commit is contained in:
bors 2017-12-16 16:16:16 +00:00
commit 4f2ef415ba
2 changed files with 66 additions and 57 deletions

View File

@ -20,11 +20,32 @@ use rustc_const_math::ConstInt;
use std::fmt; use std::fmt;
use std::error::Error; use std::error::Error;
pub fn mk_eval_cx<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, EvalContext<'a, 'tcx, CompileTimeEvaluator>> {
debug!("mk_eval_cx: {:?}, {:?}", instance, param_env);
let limits = super::ResourceLimits::default();
let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
let mir = ecx.load_mir(instance.def)?;
// insert a stack frame so any queries have the correct substs
ecx.push_stack_frame(
instance,
mir.span,
mir,
Place::undef(),
StackPopCleanup::None,
)?;
Ok(ecx)
}
pub fn eval_body<'a, 'tcx>( pub fn eval_body<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>, instance: Instance<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> (EvalResult<'tcx, (PtrAndAlign, Ty<'tcx>)>, EvalContext<'a, 'tcx, CompileTimeEvaluator>) { ) -> EvalResult<'tcx, (PtrAndAlign, Ty<'tcx>)> {
debug!("eval_body: {:?}, {:?}", instance, param_env); debug!("eval_body: {:?}, {:?}", instance, param_env);
let limits = super::ResourceLimits::default(); let limits = super::ResourceLimits::default();
let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ()); let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
@ -33,55 +54,43 @@ pub fn eval_body<'a, 'tcx>(
promoted: None, promoted: None,
}; };
let try = (|| { if ecx.tcx.has_attr(instance.def_id(), "linkage") {
if ecx.tcx.has_attr(instance.def_id(), "linkage") { return Err(ConstEvalError::NotConst("extern global".to_string()).into());
return Err(ConstEvalError::NotConst("extern global".to_string()).into()); }
} // FIXME(eddyb) use `Instance::ty` when it becomes available.
// FIXME(eddyb) use `Instance::ty` when it becomes available. let instance_ty =
let instance_ty = ecx.monomorphize(instance.def.def_ty(tcx), instance.substs);
ecx.monomorphize(instance.def.def_ty(tcx), instance.substs); if tcx.interpret_interner.borrow().get_cached(cid).is_none() {
if tcx.interpret_interner.borrow().get_cached(cid).is_none() { let mir = ecx.load_mir(instance.def)?;
let mir = ecx.load_mir(instance.def)?; let layout = ecx.layout_of(instance_ty)?;
let layout = ecx.layout_of(instance_ty)?; assert!(!layout.is_unsized());
assert!(!layout.is_unsized()); let ptr = ecx.memory.allocate(
let ptr = ecx.memory.allocate( layout.size.bytes(),
layout.size.bytes(), layout.align.abi(),
layout.align.abi(), None,
None, )?;
)?; tcx.interpret_interner.borrow_mut().cache(
tcx.interpret_interner.borrow_mut().cache( cid,
cid, PtrAndAlign {
PtrAndAlign { ptr: ptr.into(),
ptr: ptr.into(), aligned: !layout.is_packed(),
aligned: !layout.is_packed(), },
}, );
); let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable); let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id())); trace!("const_eval: pushing stack frame for global: {}", name);
trace!("const_eval: pushing stack frame for global: {}", name); ecx.push_stack_frame(
ecx.push_stack_frame( instance,
instance, mir.span,
mir.span, mir,
mir, Place::from_ptr(ptr),
Place::from_ptr(ptr), cleanup.clone(),
cleanup.clone(), )?;
)?;
while ecx.step()? {} while ecx.step()? {}
}
// reinsert the stack frame so any future queries have the correct substs let value = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
ecx.push_stack_frame( Ok((value, instance_ty))
instance,
mir.span,
mir,
Place::from_ptr(ptr),
cleanup,
)?;
}
let value = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
Ok((value, instance_ty))
})();
(try, ecx)
} }
pub fn eval_body_as_integer<'a, 'tcx>( pub fn eval_body_as_integer<'a, 'tcx>(
@ -89,8 +98,9 @@ pub fn eval_body_as_integer<'a, 'tcx>(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
instance: Instance<'tcx>, instance: Instance<'tcx>,
) -> EvalResult<'tcx, ConstInt> { ) -> EvalResult<'tcx, ConstInt> {
let (ptr_ty, ecx) = eval_body(tcx, instance, param_env); let ptr_ty = eval_body(tcx, instance, param_env);
let (ptr, ty) = ptr_ty?; let (ptr, ty) = ptr_ty?;
let ecx = mk_eval_cx(tcx, instance, param_env)?;
let prim = match ecx.read_maybe_aligned(ptr.aligned, |ectx| ectx.try_read_value(ptr.ptr, ty))? { let prim = match ecx.read_maybe_aligned(ptr.aligned, |ectx| ectx.try_read_value(ptr.ptr, ty))? {
Some(Value::ByVal(prim)) => prim.to_bytes()?, Some(Value::ByVal(prim)) => prim.to_bytes()?,
_ => return err!(TypeNotPrimitive(ty)), _ => return err!(TypeNotPrimitive(ty)),
@ -340,20 +350,19 @@ pub fn const_eval_provider<'a, 'tcx>(
trace!("const eval instance: {:?}, {:?}", instance, key.param_env); trace!("const eval instance: {:?}, {:?}", instance, key.param_env);
let miri_result = ::interpret::eval_body(tcx, instance, key.param_env); let miri_result = ::interpret::eval_body(tcx, instance, key.param_env);
match (miri_result, old_result) { match (miri_result, old_result) {
((Err(err), ecx), Ok(ok)) => { (Err(err), Ok(ok)) => {
trace!("miri failed, ctfe returned {:?}", ok); trace!("miri failed, ctfe returned {:?}", ok);
tcx.sess.span_warn( tcx.sess.span_warn(
tcx.def_span(key.value.0), tcx.def_span(key.value.0),
"miri failed to eval, while ctfe succeeded", "miri failed to eval, while ctfe succeeded",
); );
let ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
let () = unwrap_miri(&ecx, Err(err)); let () = unwrap_miri(&ecx, Err(err));
Ok(ok) Ok(ok)
}, },
((Ok(_), _), Err(err)) => { (_, Err(err)) => Err(err),
Err(err) (Ok((miri_val, miri_ty)), Ok(ctfe)) => {
}, let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
((Err(_), _), Err(err)) => Err(err),
((Ok((miri_val, miri_ty)), mut ecx), Ok(ctfe)) => {
check_ctfe_against_miri(&mut ecx, miri_val, miri_ty, ctfe.val); check_ctfe_against_miri(&mut ecx, miri_val, miri_ty, ctfe.val);
Ok(ctfe) Ok(ctfe)
} }

@ -1 +1 @@
Subproject commit bde093fa140cbf95023482a94b92b0b16af4b521 Subproject commit 2671cf34a58b11f995add8402e75c1cd94ed051e