ecx: &mut InterpCx<'mir, 'tcx, Self>,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
- ecx.find_fn(instance, args, dest, ret, unwind)
+ ecx.find_fn(instance, args, ret, unwind)
}
#[inline(always)]
ecx: &mut InterpCx<'mir, 'tcx, Self>,
fn_val: Dlsym,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
+ _unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
- ecx.call_dlsym(fn_val, args, dest, ret)
+ ecx.call_dlsym(fn_val, args, ret)
}
#[inline(always)]
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>,
) -> InterpResult<'tcx> {
- ecx.call_intrinsic(span, instance, args, dest, ret, unwind)
+ ecx.call_intrinsic(span, instance, args, ret, unwind)
}
#[inline(always)]
&mut self,
dlsym: Dlsym,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
) -> InterpResult<'tcx> {
use self::Dlsym::*;
let this = self.eval_context_mut();
-
- let dest = dest.expect("we don't support any diverging dlsym");
- let ret = ret.expect("dest is `Some` but ret is `None`");
+ let (dest, ret) = ret.expect("we don't support any diverging dlsym");
match dlsym {
GetEntropy => {
}
}
- this.goto_block(Some(ret))?;
this.dump_place(*dest);
+ this.go_to_block(ret);
Ok(())
}
}
&mut self,
def_id: DefId,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
_unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
let this = self.eval_context_mut();
let tcx = &{ this.tcx.tcx };
// First: functions that diverge.
- match link_name {
+ let (dest, ret) = match link_name {
// Note that this matches calls to the *foreign* item `__rust_start_panic* -
// that is, calls to `extern "Rust" { fn __rust_start_panic(...) }`.
// We forward this to the underlying *implementation* in the panic runtime crate.
return Err(InterpError::Exit(code).into());
}
_ => {
- if dest.is_none() {
+ if let Some(p) = ret {
+ p
+ } else {
throw_unsup_format!("can't call (diverging) foreign function: {}", link_name);
}
}
- }
+ };
- // Next: functions that assume a ret and dest.
- let dest = dest.expect("we already checked for a dest");
- let ret = ret.expect("dest is `Some` but ret is `None`");
+ // Next: functions that return.
match link_name {
"malloc" => {
let size = this.read_scalar(args[0])?.to_machine_usize(this)?;
_ => throw_unsup_format!("can't call foreign function: {}", link_name),
}
- this.goto_block(Some(ret))?;
this.dump_place(*dest);
+ this.go_to_block(ret);
Ok(None)
}
span: Span,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- _ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
- if this.emulate_intrinsic(span, instance, args, dest)? {
+ if this.emulate_intrinsic(span, instance, args, ret)? {
return Ok(());
}
let tcx = &{this.tcx.tcx};
// that might still hang around!
let intrinsic_name = &*tcx.item_name(instance.def_id()).as_str();
- // Handle diverging intrinsics
- match intrinsic_name {
+ // Handle diverging intrinsics.
+ let (dest, ret) = match intrinsic_name {
"abort" => {
// FIXME: Add a better way of indicating 'abnormal' termination,
// since this is not really an 'unsupported' behavior
throw_unsup_format!("the evaluated program aborted!");
}
"miri_start_panic" => return this.handle_miri_start_panic(args, unwind),
- _ => {}
- }
-
- // Handle non-diverging intrinsics
- // The intrinsic itself cannot diverge (otherwise, we would have handled it above),
- // so if we got here without a return place that's UB (can happen e.g., for transmute returning `!`).
- let dest = match dest {
- Some(dest) => dest,
- None => throw_ub!(Unreachable)
+ _ => {
+ if let Some(p) = ret {
+ p
+ } else {
+ throw_unsup_format!("unimplemented (diverging) intrinsic: {}", intrinsic_name);
+ }
+ }
};
match intrinsic_name {
name => throw_unsup_format!("unimplemented intrinsic: {}", name),
}
+ this.dump_place(*dest);
+ this.go_to_block(ret);
Ok(())
}
}
&mut self,
instance: ty::Instance<'tcx>,
args: &[OpTy<'tcx, Tag>],
- dest: Option<PlaceTy<'tcx, Tag>>,
- ret: Option<mir::BasicBlock>,
+ ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
unwind: Option<mir::BasicBlock>
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
let this = self.eval_context_mut();
trace!(
"eval_fn_call: {:#?}, {:?}",
instance,
- dest.map(|place| *place)
+ ret.map(|p| *p.0)
);
// There are some more lang items we want to hook that CTFE does not hook (yet).
if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {
- let dest = dest.unwrap();
+ let (dest, ret) = ret.unwrap();
let n = this
.align_offset(args[0], args[1])?
.unwrap_or_else(|| this.truncate(u128::max_value(), dest.layout));
this.write_scalar(Scalar::from_uint(n, dest.layout.size), dest)?;
- this.goto_block(ret)?;
+ this.go_to_block(ret);
return Ok(None);
}
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
// foreign function
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
- return this.emulate_foreign_item(instance.def_id(), args, dest, ret, unwind);
+ return this.emulate_foreign_item(instance.def_id(), args, ret, unwind);
}
// Otherwise, load the MIR.
this.machine.panic_payload = Some(scalar);
// Jump to the unwind block to begin unwinding.
- // We don't use `goto_block` as that is just meant for normal returns.
- let next_frame = this.frame_mut();
- next_frame.block = unwind;
- next_frame.stmt = 0;
+ this.unwind_to_block(unwind);
return Ok(())
}