refactor goto_block and also add unwind_to_block
This commit is contained in:
parent
d9025395c8
commit
7bfed2e32a
@ -338,7 +338,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
// 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.goto_block(ret)?; // fully evaluated and done
|
||||
ecx.return_to_block(ret)?; // callee is fully evaluated and done
|
||||
Ok(None)
|
||||
} else {
|
||||
throw_unsup_format!("calling non-const function `{}`", instance)
|
||||
|
@ -553,6 +553,37 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Jump to the given block.
|
||||
#[inline]
|
||||
pub fn go_to_block(&mut self, target: mir::BasicBlock) {
|
||||
let frame = self.frame_mut();
|
||||
frame.block = Some(target);
|
||||
frame.stmt = 0;
|
||||
}
|
||||
|
||||
/// *Return* to the given `target` basic block.
|
||||
/// Do *not* use for unwinding! Use `unwind_to_block` instead.
|
||||
///
|
||||
/// If `target` is `None`, that indicates the function cannot return, so we raise UB.
|
||||
pub fn return_to_block(&mut self, target: Option<mir::BasicBlock>) -> InterpResult<'tcx> {
|
||||
if let Some(target) = target {
|
||||
Ok(self.go_to_block(target))
|
||||
} else {
|
||||
throw_ub!(Unreachable)
|
||||
}
|
||||
}
|
||||
|
||||
/// *Unwind* to the given `target` basic block.
|
||||
/// Do *not* use for returning! Use `return_to_block` instead.
|
||||
///
|
||||
/// If `target` is `None`, that indicates the function does not need cleanup during
|
||||
/// unwinding, and we will just keep propagating that upwards.
|
||||
pub fn unwind_to_block(&mut self, target: Option<mir::BasicBlock>) {
|
||||
let frame = self.frame_mut();
|
||||
frame.block = target;
|
||||
frame.stmt = 0;
|
||||
}
|
||||
|
||||
/// Pops the current frame from the stack, deallocating the
|
||||
/// memory for allocated locals.
|
||||
///
|
||||
@ -628,10 +659,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
if cur_unwinding {
|
||||
// Follow the unwind edge.
|
||||
let unwind = next_block.expect("Encounted StackPopCleanup::None when unwinding!");
|
||||
let next_frame = self.frame_mut();
|
||||
// If `unwind` is `None`, we'll leave that function immediately again.
|
||||
next_frame.block = unwind;
|
||||
next_frame.stmt = 0;
|
||||
self.unwind_to_block(unwind);
|
||||
} else {
|
||||
// Follow the normal return edge.
|
||||
// Validate the return value. Do this after deallocating so that we catch dangling
|
||||
@ -658,7 +686,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
// Jump to new block -- *after* validation so that the spans make more sense.
|
||||
if let Some(ret) = next_block {
|
||||
self.goto_block(ret)?;
|
||||
self.return_to_block(ret)?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,17 +12,6 @@ use super::{
|
||||
};
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
#[inline]
|
||||
pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> InterpResult<'tcx> {
|
||||
if let Some(target) = target {
|
||||
self.frame_mut().block = Some(target);
|
||||
self.frame_mut().stmt = 0;
|
||||
Ok(())
|
||||
} else {
|
||||
throw_ub!(Unreachable)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn eval_terminator(
|
||||
&mut self,
|
||||
terminator: &mir::Terminator<'tcx>,
|
||||
@ -34,7 +23,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
self.pop_stack_frame(/* unwinding */ false)?
|
||||
}
|
||||
|
||||
Goto { target } => self.goto_block(Some(target))?,
|
||||
Goto { target } => self.go_to_block(target),
|
||||
|
||||
SwitchInt {
|
||||
ref discr,
|
||||
@ -60,7 +49,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
self.goto_block(Some(target_block))?;
|
||||
self.go_to_block(target_block);
|
||||
}
|
||||
|
||||
Call {
|
||||
@ -133,7 +122,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let cond_val = self.read_immediate(self.eval_operand(cond, None)?)?
|
||||
.to_scalar()?.to_bool()?;
|
||||
if expected == cond_val {
|
||||
self.goto_block(Some(target))?;
|
||||
self.go_to_block(target);
|
||||
} else {
|
||||
// Compute error message
|
||||
use rustc::mir::interpret::PanicInfo::*;
|
||||
@ -272,7 +261,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// No stack frame gets pushed, the main loop will just act as if the
|
||||
// call completed.
|
||||
if ret.is_some() {
|
||||
self.goto_block(ret)?;
|
||||
self.return_to_block(ret)?;
|
||||
} else {
|
||||
// If this intrinsic call doesn't have a ret block,
|
||||
// then the intrinsic implementation should have
|
||||
|
Loading…
x
Reference in New Issue
Block a user