Skip to content

Commit d2e4cbe

Browse files
authored
Rollup merge of rust-lang#71100 - RalfJung:miri-frame-hook, r=oli-obk
Miri: expand frame hooks This is needed to make rust-lang/miri#1330 work. r? @oli-obk @eddyb
2 parents 7b43cfd + f2d4c93 commit d2e4cbe

File tree

8 files changed

+88
-46
lines changed

8 files changed

+88
-46
lines changed

src/librustc_mir/const_eval/eval_queries.rs

+22-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{error_to_const_error, CompileTimeEvalContext, CompileTimeInterpreter, MemoryExtra};
22
use crate::interpret::eval_nullary_intrinsic;
33
use crate::interpret::{
4-
intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, ImmTy, Immediate, InternKind,
4+
intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind,
55
InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar,
66
ScalarMaybeUndef, StackPopCleanup,
77
};
@@ -147,25 +147,28 @@ pub(super) fn op_to_const<'tcx>(
147147
match immediate {
148148
Ok(mplace) => to_const_value(mplace),
149149
// see comment on `let try_as_immediate` above
150-
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
151-
ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
152-
ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
150+
Err(imm) => match *imm {
151+
Immediate::Scalar(x) => match x {
152+
ScalarMaybeUndef::Scalar(s) => ConstValue::Scalar(s),
153+
ScalarMaybeUndef::Undef => to_const_value(op.assert_mem_place(ecx)),
154+
},
155+
Immediate::ScalarPair(a, b) => {
156+
let (data, start) = match a.not_undef().unwrap() {
157+
Scalar::Ptr(ptr) => {
158+
(ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
159+
}
160+
Scalar::Raw { .. } => (
161+
ecx.tcx
162+
.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
163+
0,
164+
),
165+
};
166+
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
167+
let start = start.try_into().unwrap();
168+
let len: usize = len.try_into().unwrap();
169+
ConstValue::Slice { data, start, end: start + len }
170+
}
153171
},
154-
Err(ImmTy { imm: Immediate::ScalarPair(a, b), .. }) => {
155-
let (data, start) = match a.not_undef().unwrap() {
156-
Scalar::Ptr(ptr) => {
157-
(ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), ptr.offset.bytes())
158-
}
159-
Scalar::Raw { .. } => (
160-
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])),
161-
0,
162-
),
163-
};
164-
let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
165-
let start = start.try_into().unwrap();
166-
let len: usize = len.try_into().unwrap();
167-
ConstValue::Slice { data, start, end: start + len }
168-
}
169172
}
170173
}
171174

src/librustc_mir/const_eval/machine.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use rustc_middle::mir::AssertMessage;
1313
use rustc_span::symbol::Symbol;
1414

1515
use crate::interpret::{
16-
self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy,
17-
PlaceTy, Pointer, Scalar,
16+
self, AllocId, Allocation, Frame, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
17+
OpTy, PlaceTy, Pointer, Scalar,
1818
};
1919

2020
use super::error::*;
@@ -342,8 +342,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
342342
}
343343

344344
#[inline(always)]
345-
fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
346-
Ok(())
345+
fn init_frame_extra(
346+
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
347+
frame: Frame<'mir, 'tcx>,
348+
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
349+
Ok(frame)
347350
}
348351

349352
fn before_access_global(

src/librustc_mir/interpret/eval_context.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,21 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
159159
}
160160
}
161161

162+
impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
163+
pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'mir, 'tcx, Tag, Extra> {
164+
Frame {
165+
body: self.body,
166+
instance: self.instance,
167+
return_to_block: self.return_to_block,
168+
return_place: self.return_place,
169+
locals: self.locals,
170+
block: self.block,
171+
stmt: self.stmt,
172+
extra,
173+
}
174+
}
175+
}
176+
162177
impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
163178
/// Return the `SourceInfo` of the current instruction.
164179
pub fn current_source_info(&self) -> Option<mir::SourceInfo> {
@@ -586,8 +601,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
586601
::log_settings::settings().indentation += 1;
587602

588603
// first push a stack frame so we have access to the local substs
589-
let extra = M::stack_push(self)?;
590-
self.stack.push(Frame {
604+
let pre_frame = Frame {
591605
body,
592606
block: Some(mir::START_BLOCK),
593607
return_to_block,
@@ -597,8 +611,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
597611
locals: IndexVec::new(),
598612
instance,
599613
stmt: 0,
600-
extra,
601-
});
614+
extra: (),
615+
};
616+
let frame = M::init_frame_extra(self, pre_frame)?;
617+
self.stack.push(frame);
602618

603619
// don't allocate at all for trivial constants
604620
if body.local_decls.len() > 1 {
@@ -630,6 +646,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
630646
self.frame_mut().locals = locals;
631647
}
632648

649+
M::after_stack_push(self)?;
633650
info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
634651

635652
if self.stack.len() > *self.tcx.sess.recursion_limit.get() {
@@ -725,16 +742,17 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
725742
}
726743

727744
// Cleanup: deallocate all locals that are backed by an allocation.
728-
for local in frame.locals {
745+
for local in &frame.locals {
729746
self.deallocate_local(local.value)?;
730747
}
731748

732-
if M::stack_pop(self, frame.extra, unwinding)? == StackPopJump::NoJump {
749+
let return_place = frame.return_place;
750+
if M::after_stack_pop(self, frame, unwinding)? == StackPopJump::NoJump {
733751
// The hook already did everything.
734752
// We want to skip the `info!` below, hence early return.
735753
return Ok(());
736754
}
737-
// Normal return.
755+
// Normal return, figure out where to jump.
738756
if unwinding {
739757
// Follow the unwind edge.
740758
let unwind = next_block.expect("Encountered StackPopCleanup::None when unwinding!");
@@ -743,7 +761,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
743761
// Follow the normal return edge.
744762
// Validate the return value. Do this after deallocating so that we catch dangling
745763
// references.
746-
if let Some(return_place) = frame.return_place {
764+
if let Some(return_place) = return_place {
747765
if M::enforce_validity(self) {
748766
// Data got changed, better make sure it matches the type!
749767
// It is still possible that the return place held invalid data while

src/librustc_mir/interpret/machine.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,21 @@ pub trait Machine<'mir, 'tcx>: Sized {
279279
Ok(())
280280
}
281281

282-
/// Called immediately before a new stack frame got pushed.
283-
fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>;
282+
/// Called immediately before a new stack frame gets pushed.
283+
fn init_frame_extra(
284+
ecx: &mut InterpCx<'mir, 'tcx, Self>,
285+
frame: Frame<'mir, 'tcx, Self::PointerTag>,
286+
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>>;
287+
288+
/// Called immediately after a stack frame got pushed and its locals got initialized.
289+
fn after_stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
290+
Ok(())
291+
}
284292

285-
/// Called immediately after a stack frame gets popped
286-
fn stack_pop(
293+
/// Called immediately after a stack frame got popped, but before jumping back to the caller.
294+
fn after_stack_pop(
287295
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
288-
_extra: Self::FrameExtra,
296+
_frame: Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
289297
_unwinding: bool,
290298
) -> InterpResult<'tcx, StackPopJump> {
291299
// By default, we do not support unwinding from panics

src/librustc_mir/interpret/operand.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<'tcx, Tag> Immediate<Tag> {
8787
// as input for binary and cast operations.
8888
#[derive(Copy, Clone, Debug)]
8989
pub struct ImmTy<'tcx, Tag = ()> {
90-
pub(crate) imm: Immediate<Tag>,
90+
imm: Immediate<Tag>,
9191
pub layout: TyAndLayout<'tcx>,
9292
}
9393

@@ -183,6 +183,11 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> {
183183
ImmTy { imm: val.into(), layout }
184184
}
185185

186+
#[inline]
187+
pub fn from_immediate(imm: Immediate<Tag>, layout: TyAndLayout<'tcx>) -> Self {
188+
ImmTy { imm, layout }
189+
}
190+
186191
#[inline]
187192
pub fn try_from_uint(i: impl Into<u128>, layout: TyAndLayout<'tcx>) -> Option<Self> {
188193
Some(Self::from_scalar(Scalar::try_from_uint(i, layout.size)?, layout))
@@ -424,7 +429,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
424429
Ok(OpTy { op, layout })
425430
}
426431

427-
/// Every place can be read from, so we can turn them into an operand
432+
/// Every place can be read from, so we can turn them into an operand.
433+
/// This will definitely return `Indirect` if the place is a `Ptr`, i.e., this
434+
/// will never actually read from memory.
428435
#[inline(always)]
429436
pub fn place_to_op(
430437
&self,

src/librustc_mir/interpret/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ impl<'tcx, Tag: ::std::fmt::Debug + Copy> OpTy<'tcx, Tag> {
247247
Operand::Immediate(_) if self.layout.is_zst() => {
248248
Ok(MPlaceTy::dangling(self.layout, cx))
249249
}
250-
Operand::Immediate(imm) => Err(ImmTy { imm, layout: self.layout }),
250+
Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
251251
}
252252
}
253253

src/librustc_mir/interpret/terminator.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
407407
let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
408408
// Adjust receiver argument.
409409
args[0] =
410-
OpTy::from(ImmTy { layout: this_receiver_ptr, imm: receiver_place.ptr.into() });
410+
OpTy::from(ImmTy::from_immediate(receiver_place.ptr.into(), this_receiver_ptr));
411411
trace!("Patched self operand to {:#?}", args[0]);
412412
// recurse with concrete function
413413
self.eval_fn_call(drop_fn, caller_abi, &args, ret, unwind)
@@ -436,10 +436,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
436436
_ => (instance, place),
437437
};
438438

439-
let arg = ImmTy {
440-
imm: place.to_ref(),
441-
layout: self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
442-
};
439+
let arg = ImmTy::from_immediate(
440+
place.to_ref(),
441+
self.layout_of(self.tcx.mk_mut_ptr(place.layout.ty))?,
442+
);
443443

444444
let ty = self.tcx.mk_unit(); // return type is ()
445445
let dest = MPlaceTy::dangling(self.layout_of(ty)?, self);

src/librustc_mir/transform/const_prop.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
290290
}
291291

292292
#[inline(always)]
293-
fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
294-
Ok(())
293+
fn init_frame_extra(
294+
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
295+
frame: Frame<'mir, 'tcx>,
296+
) -> InterpResult<'tcx, Frame<'mir, 'tcx>> {
297+
Ok(frame)
295298
}
296299
}
297300

0 commit comments

Comments
 (0)