Skip to content

Commit 261faf3

Browse files
committed
machine hooks for stack push and pop, frame machine data
1 parent 53ed3b7 commit 261faf3

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

src/librustc_mir/const_eval.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
6565
return_place: None,
6666
return_to_block: StackPopCleanup::Goto(None), // never pop
6767
stmt: 0,
68+
extra: (),
6869
});
6970
Ok(ecx)
7071
}
@@ -353,9 +354,11 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
353354
for CompileTimeInterpreter<'a, 'mir, 'tcx>
354355
{
355356
type MemoryKinds = !;
357+
type PointerTag = ();
358+
359+
type FrameExtra = ();
356360
type MemoryExtra = ();
357361
type AllocExtra = ();
358-
type PointerTag = ();
359362

360363
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
361364

@@ -490,6 +493,22 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
490493
) -> EvalResult<'tcx, Pointer> {
491494
Ok(ptr)
492495
}
496+
497+
#[inline(always)]
498+
fn stack_push(
499+
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
500+
) -> EvalResult<'tcx> {
501+
Ok(())
502+
}
503+
504+
/// Called immediately before a stack frame gets popped
505+
#[inline(always)]
506+
fn stack_pop(
507+
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
508+
_extra: (),
509+
) -> EvalResult<'tcx> {
510+
Ok(())
511+
}
493512
}
494513

495514
/// Project to a field of a (variant of a) const

src/librustc_mir/interpret/eval_context.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
4949
pub(crate) memory: Memory<'a, 'mir, 'tcx, M>,
5050

5151
/// The virtual call stack.
52-
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag>>,
52+
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
5353

5454
/// A cache for deduplicating vtables
5555
pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
5656
}
5757

5858
/// A stack frame.
5959
#[derive(Clone)]
60-
pub struct Frame<'mir, 'tcx: 'mir, Tag=()> {
60+
pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
6161
////////////////////////////////////////////////////////////////////////////////
6262
// Function and callsite information
6363
////////////////////////////////////////////////////////////////////////////////
@@ -96,6 +96,9 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=()> {
9696

9797
/// The index of the currently evaluated statement.
9898
pub stmt: usize,
99+
100+
/// Extra data for the machine
101+
pub extra: Extra,
99102
}
100103

101104
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
@@ -196,7 +199,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
196199
}
197200

198201
#[inline(always)]
199-
pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag>] {
202+
pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] {
200203
&self.stack
201204
}
202205

@@ -207,12 +210,12 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
207210
}
208211

209212
#[inline(always)]
210-
pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag> {
213+
pub fn frame(&self) -> &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra> {
211214
self.stack.last().expect("no call frames exist")
212215
}
213216

214217
#[inline(always)]
215-
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag> {
218+
pub fn frame_mut(&mut self) -> &mut Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra> {
216219
self.stack.last_mut().expect("no call frames exist")
217220
}
218221

@@ -294,7 +297,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
294297

295298
pub fn layout_of_local(
296299
&self,
297-
frame: &Frame<'mir, 'tcx, M::PointerTag>,
300+
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
298301
local: mir::Local
299302
) -> EvalResult<'tcx, TyLayout<'tcx>> {
300303
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
424427
::log_settings::settings().indentation += 1;
425428

426429
// first push a stack frame so we have access to the local substs
430+
let extra = M::stack_push(self)?;
427431
self.stack.push(Frame {
428432
mir,
429433
block: mir::START_BLOCK,
@@ -435,6 +439,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
435439
span,
436440
instance,
437441
stmt: 0,
442+
extra,
438443
});
439444

440445
// 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
504509
let frame = self.stack.pop().expect(
505510
"tried to pop a stack frame, but there were none",
506511
);
512+
M::stack_pop(self, frame.extra)?;
507513
// Abort early if we do not want to clean up: We also avoid validation in that case,
508514
// because this is CTFE and the final value will be thoroughly validated anyway.
509515
match frame.return_to_block {

src/librustc_mir/interpret/machine.rs

+14
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
7777
/// The `default()` is used for pointers to consts, statics, vtables and functions.
7878
type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
7979

80+
/// Extra data stored in every call frame.
81+
type FrameExtra;
82+
8083
/// Extra data stored in memory. A reference to this is available when `AllocExtra`
8184
/// gets initialized, so you can e.g. have an `Rc` here if there is global state you
8285
/// need access to in the `AllocExtra` hooks.
@@ -213,4 +216,15 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
213216
) -> EvalResult<'tcx> {
214217
Ok(())
215218
}
219+
220+
/// Called immediately before a new stack frame got pushed
221+
fn stack_push(
222+
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
223+
) -> EvalResult<'tcx, Self::FrameExtra>;
224+
225+
/// Called immediately after a stack frame gets popped
226+
fn stack_pop(
227+
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
228+
extra: Self::FrameExtra,
229+
) -> EvalResult<'tcx>;
216230
}

src/librustc_mir/interpret/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
471471
/// When you know the layout of the local in advance, you can pass it as last argument
472472
pub fn access_local(
473473
&self,
474-
frame: &super::Frame<'mir, 'tcx, M::PointerTag>,
474+
frame: &super::Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
475475
local: mir::Local,
476476
layout: Option<TyLayout<'tcx>>,
477477
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {

src/librustc_mir/interpret/snapshot.rs

+2
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ impl_stable_hash_for!(impl<'tcx, 'mir: 'tcx> for struct Frame<'mir, 'tcx> {
323323
locals,
324324
block,
325325
stmt,
326+
extra,
326327
});
327328

328329
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>
340341
locals,
341342
block,
342343
stmt,
344+
extra: _,
343345
} = self;
344346

345347
FrameSnapshot {

0 commit comments

Comments
 (0)