Skip to content

Commit

Permalink
miri: couple ret place and ret block together (they both exist or bot…
Browse files Browse the repository at this point in the history
…h don't)
  • Loading branch information
RalfJung committed Nov 25, 2019
1 parent 419d3fc commit b91bf7a
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 67 deletions.
15 changes: 6 additions & 9 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: Option<PlaceTy<'tcx>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock> // unwinding is not supported in consts
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
debug!("eval_fn_call: {:?}", instance);
Expand All @@ -337,8 +336,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
// Some functions we support even if they are non-const -- but avoid testing
// that for const fn! We certainly do *not* want to actually call the fn
// though, so be sure we return here.
return if ecx.hook_panic_fn(instance, args, dest)? {
ecx.return_to_block(ret)?; // callee is fully evaluated and done
return if ecx.hook_panic_fn(instance, args, ret)? {
Ok(None)
} else {
throw_unsup_format!("calling non-const function `{}`", instance)
Expand All @@ -364,8 +362,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
fn_val: !,
_args: &[OpTy<'tcx>],
_dest: Option<PlaceTy<'tcx>>,
_ret: Option<mir::BasicBlock>,
_ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx> {
match fn_val {}
}
Expand All @@ -375,11 +373,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx>],
dest: Option<PlaceTy<'tcx>>,
_ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx> {
if ecx.emulate_intrinsic(span, instance, args, dest)? {
if ecx.emulate_intrinsic(span, instance, args, ret)? {
return Ok(());
}
// An intrinsic that we do not support
Expand Down
65 changes: 37 additions & 28 deletions src/librustc_mir/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use rustc::ty::layout::{LayoutOf, Primitive, Size};
use rustc::ty::subst::SubstsRef;
use rustc::hir::def_id::DefId;
use rustc::ty::TyCtxt;
use rustc::mir::BinOp;
use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
use rustc::mir::{
self, BinOp,
interpret::{InterpResult, Scalar, GlobalId, ConstValue}
};

use super::{
Machine, PlaceTy, OpTy, InterpCx, ImmTy,
Expand Down Expand Up @@ -91,13 +93,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, M::PointerTag>],
dest: Option<PlaceTy<'tcx, M::PointerTag>>,
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
) -> InterpResult<'tcx, bool> {
let substs = instance.substs;

// We currently do not handle any diverging intrinsics.
let dest = match dest {
Some(dest) => dest,
let (dest, ret) = match ret {
Some(p) => p,
None => return Ok(false)
};
let intrinsic_name = &*self.tcx.item_name(instance.def_id()).as_str();
Expand Down Expand Up @@ -268,34 +270,39 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// exception from the exception.)
// This is the dual to the special exception for offset-by-0
// in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
if a.is_bits() && b.is_bits() {
//
// Control flow is weird because we cannot early-return (to reach the
// `go_to_block` at the end).
let done = if a.is_bits() && b.is_bits() {
let a = a.to_machine_usize(self)?;
let b = b.to_machine_usize(self)?;
if a == b && a != 0 {
self.write_scalar(Scalar::from_int(0, isize_layout.size), dest)?;
return Ok(true);
}
}
true
} else { false }
} else { false };

// General case: we need two pointers.
let a = self.force_ptr(a)?;
let b = self.force_ptr(b)?;
if a.alloc_id != b.alloc_id {
throw_ub_format!(
"ptr_offset_from cannot compute offset of pointers into different \
allocations.",
);
if !done {
// General case: we need two pointers.
let a = self.force_ptr(a)?;
let b = self.force_ptr(b)?;
if a.alloc_id != b.alloc_id {
throw_ub_format!(
"ptr_offset_from cannot compute offset of pointers into different \
allocations.",
);
}
let usize_layout = self.layout_of(self.tcx.types.usize)?;
let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout);
let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout);
let (val, _overflowed, _ty) = self.overflowing_binary_op(
BinOp::Sub, a_offset, b_offset,
)?;
let pointee_layout = self.layout_of(substs.type_at(0))?;
let val = ImmTy::from_scalar(val, isize_layout);
let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
self.exact_div(val, size, dest)?;
}
let usize_layout = self.layout_of(self.tcx.types.usize)?;
let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout);
let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout);
let (val, _overflowed, _ty) = self.overflowing_binary_op(
BinOp::Sub, a_offset, b_offset,
)?;
let pointee_layout = self.layout_of(substs.type_at(0))?;
let val = ImmTy::from_scalar(val, isize_layout);
let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout);
self.exact_div(val, size, dest)?;
}

"transmute" => {
Expand Down Expand Up @@ -350,6 +357,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
_ => return Ok(false),
}

self.dump_place(*dest);
self.go_to_block(ret);
Ok(true)
}

Expand All @@ -360,7 +369,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, M::PointerTag>],
_dest: Option<PlaceTy<'tcx, M::PointerTag>>,
_ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
) -> InterpResult<'tcx, bool> {
let def_id = instance.def_id();
if Some(def_id) == self.tcx.lang_items().panic_fn() {
Expand Down
12 changes: 5 additions & 7 deletions src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
ret: Option<mir::BasicBlock>,
unwind: Option<mir::BasicBlock>
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>>;

/// Execute `fn_val`. It is the hook's responsibility to advance the instruction
Expand All @@ -161,8 +160,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
ecx: &mut InterpCx<'mir, 'tcx, Self>,
fn_val: Self::ExtraFnVal,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx>;

/// Directly process an intrinsic without pushing a stack frame. It is the hook's
Expand All @@ -172,8 +171,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Self::PointerTag>],
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx>;

Expand Down
30 changes: 13 additions & 17 deletions src/librustc_mir/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ref cleanup,
..
} => {
let (dest, ret) = match *destination {
Some((ref lv, target)) => (Some(self.eval_place(lv)?), Some(target)),
None => (None, None),
};

let func = self.eval_operand(func, None)?;
let (fn_val, abi) = match func.layout.ty.kind {
ty::FnPtr(sig) => {
Expand All @@ -81,12 +76,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
};
let args = self.eval_operands(args)?;
let ret = match destination {
Some((dest, ret)) => Some((self.eval_place(dest)?, *ret)),
None => None,
};
self.eval_fn_call(
fn_val,
terminator.source_info.span,
abi,
&args[..],
dest,
ret,
*cleanup
)?;
Expand Down Expand Up @@ -238,16 +236,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
span: Span,
caller_abi: Abi,
args: &[OpTy<'tcx, M::PointerTag>],
dest: Option<PlaceTy<'tcx, M::PointerTag>>,
ret: Option<mir::BasicBlock>,
ret: Option<(PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx> {
trace!("eval_fn_call: {:#?}", fn_val);

let instance = match fn_val {
FnVal::Instance(instance) => instance,
FnVal::Other(extra) => {
return M::call_extra_fn(self, extra, args, dest, ret);
return M::call_extra_fn(self, extra, args, ret, unwind);
}
};

Expand Down Expand Up @@ -278,7 +275,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match instance.def {
ty::InstanceDef::Intrinsic(..) => {
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
return M::call_intrinsic(self, span, instance, args, dest, ret, unwind);
return M::call_intrinsic(self, span, instance, args, ret, unwind);
}
ty::InstanceDef::VtableShim(..) |
ty::InstanceDef::ReifyShim(..) |
Expand All @@ -288,7 +285,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ty::InstanceDef::CloneShim(..) |
ty::InstanceDef::Item(_) => {
// We need MIR for this fn
let body = match M::find_fn(self, instance, args, dest, ret, unwind)? {
let body = match M::find_fn(self, instance, args, ret, unwind)? {
Some(body) => body,
None => return Ok(()),
};
Expand All @@ -297,8 +294,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
instance,
span,
body,
dest,
StackPopCleanup::Goto { ret, unwind }
ret.map(|p| p.0),
StackPopCleanup::Goto { ret: ret.map(|p| p.1), unwind }
)?;

// We want to pop this frame again in case there was an error, to put
Expand Down Expand Up @@ -381,7 +378,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
throw_unsup!(FunctionArgCountMismatch)
}
// Don't forget to check the return type!
if let Some(caller_ret) = dest {
if let Some((caller_ret, _)) = ret {
let callee_ret = self.eval_place(
&mir::Place::return_place()
)?;
Expand Down Expand Up @@ -447,7 +444,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
});
trace!("Patched self operand to {:#?}", args[0]);
// recurse with concrete function
self.eval_fn_call(drop_fn, span, caller_abi, &args, dest, ret, unwind)
self.eval_fn_call(drop_fn, span, caller_abi, &args, ret, unwind)
}
}
}
Expand Down Expand Up @@ -487,8 +484,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
span,
Abi::Rust,
&[arg.into()],
Some(dest.into()),
Some(target),
Some((dest.into(), target)),
unwind
)
}
Expand Down
10 changes: 4 additions & 6 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_instance: ty::Instance<'tcx>,
_args: &[OpTy<'tcx>],
_dest: Option<PlaceTy<'tcx>>,
_ret: Option<BasicBlock>,
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
_unwind: Option<BasicBlock>,
) -> InterpResult<'tcx, Option<&'mir Body<'tcx>>> {
Ok(None)
Expand All @@ -155,8 +154,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
fn_val: !,
_args: &[OpTy<'tcx>],
_dest: Option<PlaceTy<'tcx>>,
_ret: Option<BasicBlock>,
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
_unwind: Option<BasicBlock>
) -> InterpResult<'tcx> {
match fn_val {}
}
Expand All @@ -166,8 +165,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_span: Span,
_instance: ty::Instance<'tcx>,
_args: &[OpTy<'tcx>],
_dest: Option<PlaceTy<'tcx>>,
_ret: Option<BasicBlock>,
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
_unwind: Option<BasicBlock>
) -> InterpResult<'tcx> {
throw_unsup_format!("calling intrinsics isn't supported in ConstProp");
Expand Down

0 comments on commit b91bf7a

Please sign in to comment.