machine hooks for stack push and pop, frame machine data
This commit is contained in:
parent
53ed3b7956
commit
261faf3ce2
@ -65,6 +65,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
|
||||
return_place: None,
|
||||
return_to_block: StackPopCleanup::Goto(None), // never pop
|
||||
stmt: 0,
|
||||
extra: (),
|
||||
});
|
||||
Ok(ecx)
|
||||
}
|
||||
@ -353,9 +354,11 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
||||
for CompileTimeInterpreter<'a, 'mir, 'tcx>
|
||||
{
|
||||
type MemoryKinds = !;
|
||||
type PointerTag = ();
|
||||
|
||||
type FrameExtra = ();
|
||||
type MemoryExtra = ();
|
||||
type AllocExtra = ();
|
||||
type PointerTag = ();
|
||||
|
||||
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
|
||||
|
||||
@ -490,6 +493,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
||||
) -> EvalResult<'tcx, Pointer> {
|
||||
Ok(ptr)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn stack_push(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
) -> EvalResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Called immediately before a stack frame gets popped
|
||||
#[inline(always)]
|
||||
fn stack_pop(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_extra: (),
|
||||
) -> EvalResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Project to a field of a (variant of a) const
|
||||
|
@ -49,7 +49,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
|
||||
pub(crate) memory: Memory<'a, 'mir, 'tcx, M>,
|
||||
|
||||
/// The virtual call stack.
|
||||
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag>>,
|
||||
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
|
||||
|
||||
/// A cache for deduplicating vtables
|
||||
pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
|
||||
@ -57,7 +57,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
|
||||
|
||||
/// A stack frame.
|
||||
#[derive(Clone)]
|
||||
pub struct Frame<'mir, 'tcx: 'mir, Tag=()> {
|
||||
pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Function and callsite information
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -96,6 +96,9 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=()> {
|
||||
|
||||
/// The index of the currently evaluated statement.
|
||||
pub stmt: usize,
|
||||
|
||||
/// Extra data for the machine
|
||||
pub extra: Extra,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||
@ -196,7 +199,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag>] {
|
||||
pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] {
|
||||
&self.stack
|
||||
}
|
||||
|
||||
@ -207,12 +210,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag> {
|
||||
pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra> {
|
||||
self.stack.last().expect("no call frames exist")
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag> {
|
||||
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra> {
|
||||
self.stack.last_mut().expect("no call frames exist")
|
||||
}
|
||||
|
||||
@ -294,7 +297,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
|
||||
|
||||
pub fn layout_of_local(
|
||||
&self,
|
||||
frame: &Frame<'mir, 'tcx, M::PointerTag>,
|
||||
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
||||
local: mir::Local
|
||||
) -> EvalResult<'tcx, TyLayout<'tcx>> {
|
||||
let local_ty = frame.mir.local_decls[local].ty;
|
||||
@ -424,6 +427,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
|
||||
::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 {
|
||||
mir,
|
||||
block: mir::START_BLOCK,
|
||||
@ -435,6 +439,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
|
||||
span,
|
||||
instance,
|
||||
stmt: 0,
|
||||
extra,
|
||||
});
|
||||
|
||||
// don't allocate at all for trivial constants
|
||||
@ -504,6 +509,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
|
||||
let frame = self.stack.pop().expect(
|
||||
"tried to pop a stack frame, but there were none",
|
||||
);
|
||||
M::stack_pop(self, frame.extra)?;
|
||||
// Abort early if we do not want to clean up: We also avoid validation in that case,
|
||||
// because this is CTFE and the final value will be thoroughly validated anyway.
|
||||
match frame.return_to_block {
|
||||
|
@ -77,6 +77,9 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
||||
/// The `default()` is used for pointers to consts, statics, vtables and functions.
|
||||
type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
|
||||
|
||||
/// Extra data stored in every call frame.
|
||||
type FrameExtra;
|
||||
|
||||
/// Extra data stored in memory. A reference to this is available when `AllocExtra`
|
||||
/// gets initialized, so you can e.g. have an `Rc` here if there is global state you
|
||||
/// need access to in the `AllocExtra` hooks.
|
||||
@ -213,4 +216,15 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
||||
) -> EvalResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Called immediately before a new stack frame got pushed
|
||||
fn stack_push(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
) -> EvalResult<'tcx, Self::FrameExtra>;
|
||||
|
||||
/// Called immediately after a stack frame gets popped
|
||||
fn stack_pop(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
extra: Self::FrameExtra,
|
||||
) -> EvalResult<'tcx>;
|
||||
}
|
||||
|
@ -471,7 +471,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
||||
/// When you know the layout of the local in advance, you can pass it as last argument
|
||||
pub fn access_local(
|
||||
&self,
|
||||
frame: &super::Frame<'mir, 'tcx, M::PointerTag>,
|
||||
frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
||||
local: mir::Local,
|
||||
layout: Option<TyLayout<'tcx>>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
|
@ -323,6 +323,7 @@ impl_stable_hash_for!(impl<'tcx, 'mir: 'tcx> for struct Frame<'mir, 'tcx> {
|
||||
locals,
|
||||
block,
|
||||
stmt,
|
||||
extra,
|
||||
});
|
||||
|
||||
impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
|
||||
@ -340,6 +341,7 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
|
||||
locals,
|
||||
block,
|
||||
stmt,
|
||||
extra: _,
|
||||
} = self;
|
||||
|
||||
FrameSnapshot {
|
||||
|
Loading…
Reference in New Issue
Block a user