diff options
| author | Ralf Jung <post@ralfj.de> | 2018-11-15 17:14:53 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2018-11-25 10:49:43 +0100 |
| commit | 261faf3ce22ce930d48ecbbf872d46a613b1f0ab (patch) | |
| tree | 3a17816fb4027a5e6a0cfe51bf7e8c047e7bb0ca /src | |
| parent | 53ed3b79562fdbcbb1ca073cb48a6fea1e23d51a (diff) | |
| download | rust-261faf3ce22ce930d48ecbbf872d46a613b1f0ab.tar.gz rust-261faf3ce22ce930d48ecbbf872d46a613b1f0ab.zip | |
machine hooks for stack push and pop, frame machine data
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/const_eval.rs | 21 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 18 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/machine.rs | 14 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/operand.rs | 2 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/snapshot.rs | 2 |
5 files changed, 49 insertions, 8 deletions
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 30c06ba5659..291b5c170ef 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -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 diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 2eb5f7c853f..d36d530fe78 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -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 { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index bf260c86742..2c78807df45 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -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>; } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 539bc6d965f..83ceadada65 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -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>> { diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 4b63335ad96..f9ce7b4319f 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -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 { |
