use super::{
Immediate, Operand, MemPlace, MPlaceTy, Place, PlaceTy, ScalarMaybeUndef,
- Memory, Machine, PointerArithmetic, FnVal, StackPopInfo
+ Memory, Machine, StackPopInfo
};
pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
/// The block that is currently executed (or will be executed after the above call stacks
/// return).
/// If this is `None`, we are unwinding and this function doesn't need any clean-up.
- /// Just continue the same as with
+ /// Just continue the same as with `Resume`.
pub block: Option<mir::BasicBlock>,
/// The index of the currently evaluated statement.
/// Jump to the next block in the caller, or cause UB if None (that's a function
/// that may never return). Also store layout of return place so
/// we can validate it at that layout.
- /// 'ret' stores the block we jump to on a normal return, while 'unwind'
+ /// `ret` stores the block we jump to on a normal return, while 'unwind'
/// stores the block used for cleanup during unwinding
Goto { ret: Option<mir::BasicBlock>, unwind: Option<mir::BasicBlock> },
/// Just do nohing: Used by Main and for the box_alloc hook in miri.
}
}
+ /// Pops the current frame from the stack, deallocating the
+ /// memory for allocated locals.
+ ///
+ /// If `unwinding` is `false`, then we are performing a normal return
+ /// from a function. In this case, we jump back into the frame of the caller,
+ /// and continue execution as normal.
+ ///
+ /// If `unwinding` is `true`, then we are in the middle of a panic,
+ /// and need to unwind this frame. In this case, we jump to the
+ /// `cleanup` block for the function, which is responsible for running
+ /// `Drop` impls for any locals that have been initialized at this point.
+ /// The cleanup block ends with a special `Resume` terminator, which will
+ /// cause us to continue unwinding.
pub(super) fn pop_stack_frame(
&mut self,
unwinding: bool
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
frames
}
-
- /// Resolve the function at the specified slot in the provided
- /// vtable. An index of '0' corresponds to the first method
- /// declared in the trait of the provided vtable
- pub fn get_vtable_slot(
- &self,
- vtable: Scalar<M::PointerTag>,
- idx: usize
- ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
- let ptr_size = self.pointer_size();
- // Skip over the 'drop_ptr', 'size', and 'align' fields
- let vtable_slot = vtable.ptr_offset(ptr_size * (idx as u64 + 3), self)?;
- let vtable_slot = self.memory.check_ptr_access(
- vtable_slot,
- ptr_size,
- self.tcx.data_layout.pointer_align.abi,
- )?.expect("cannot be a ZST");
- let fn_ptr = self.memory.get(vtable_slot.alloc_id)?
- .read_ptr_sized(self, vtable_slot)?.not_undef()?;
- Ok(self.memory.get_fn(fn_ptr)?)
- }
}