use rustc_span::symbol::Symbol;
use crate::interpret::{
- self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy,
- PlaceTy, Pointer, Scalar,
+ self, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
+ OpTy, PlaceTy, Pointer, Scalar,
};
use super::error::*;
}
#[inline(always)]
- fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
- Ok(())
+ fn init_frame_extra(
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ frame: Frame<'mir, 'tcx>,
+ ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
+ Ok(frame)
}
fn before_access_global(
}
}
+impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
+ pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'mir, 'tcx, Tag, Extra> {
+ Frame {
+ body: self.body,
+ instance: self.instance,
+ return_to_block: self.return_to_block,
+ return_place: self.return_place,
+ locals: self.locals,
+ block: self.block,
+ stmt: self.stmt,
+ extra,
+ }
+ }
+}
+
impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
/// Return the `SourceInfo` of the current instruction.
pub fn current_source_info(&self) -> Option<mir::SourceInfo> {
::log_settings::settings().indentation += 1;
// first push a stack frame so we have access to the local substs
- let extra = M::stack_push(self)?;
- self.stack.push(Frame {
+ let pre_frame = Frame {
body,
block: Some(mir::START_BLOCK),
return_to_block,
locals: IndexVec::new(),
instance,
stmt: 0,
- extra,
- });
+ extra: (),
+ };
+ let frame = M::init_frame_extra(self, pre_frame)?;
+ self.stack.push(frame);
// don't allocate at all for trivial constants
if body.local_decls.len() > 1 {
}
// Cleanup: deallocate all locals that are backed by an allocation.
- for local in frame.locals {
+ for local in &frame.locals {
self.deallocate_local(local.value)?;
}
- if M::stack_pop(self, frame.extra, unwinding)? == StackPopJump::NoJump {
+ let return_place = frame.return_place;
+ if M::after_stack_pop(self, frame, unwinding)? == StackPopJump::NoJump {
// The hook already did everything.
// We want to skip the `info!` below, hence early return.
return Ok(());
// Follow the normal return edge.
// Validate the return value. Do this after deallocating so that we catch dangling
// references.
- if let Some(return_place) = frame.return_place {
+ if let Some(return_place) = return_place {
if M::enforce_validity(self) {
// Data got changed, better make sure it matches the type!
// It is still possible that the return place held invalid data while
Ok(())
}
- /// Called immediately before a new stack frame got pushed.
- fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
+ /// Called immediately before a new stack frame gets pushed.
+ fn init_frame_extra(
+ ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ frame: Frame<'mir, 'tcx, Self::PointerTag>,
+ ) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>>;
- /// Called immediately after a stack frame gets popped
- fn stack_pop(
+ /// Called immediately after a stack frame got popped, but before jumping back to the caller.
+ fn after_stack_pop(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
- _extra: Self::FrameExtra,
+ _frame: Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
_unwinding: bool,
) -> InterpResult<'tcx, StackPopJump> {
// By default, we do not support unwinding from panics
}
#[inline(always)]
- fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
- Ok(())
+ fn init_frame_extra(
+ _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+ frame: Frame<'mir, 'tcx>,
+ ) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
+ Ok(frame)
}
}