Skip to content

Commit dcd018c

Browse files
committed
interpret: make Place always refer to the current frame
1 parent 42f5419 commit dcd018c

15 files changed

+75
-88
lines changed

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
210210
if Some(def_id) == self.tcx.lang_items().panic_display()
211211
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
212212
{
213-
let args = self.copy_fn_args(args)?;
213+
let args = self.copy_fn_args(args);
214214
// &str or &&str
215215
assert!(args.len() == 1);
216216

@@ -237,7 +237,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
237237

238238
return Ok(Some(new_instance));
239239
} else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
240-
let args = self.copy_fn_args(args)?;
240+
let args = self.copy_fn_args(args);
241241
// For align_offset, we replace the function call if the pointer has no address.
242242
match self.align_offset(instance, &args, dest, ret)? {
243243
ControlFlow::Continue(()) => return Ok(Some(instance)),

compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
2121

2222
use super::{
2323
AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
24-
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance,
25-
Scalar, StackPopJump,
24+
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PointerArithmetic, Provenance, Scalar,
25+
StackPopJump,
2626
};
2727
use crate::errors::{self, ErroneousConstUsed};
2828
use crate::fluent_generated as fluent;
@@ -105,7 +105,7 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> {
105105

106106
/// The location where the result of the current stack frame should be written to,
107107
/// and its layout in the caller.
108-
pub return_place: PlaceTy<'tcx, Prov>,
108+
pub return_place: MPlaceTy<'tcx, Prov>,
109109

110110
/// The list of locals for this stack frame, stored in order as
111111
/// `[return_ptr, arguments..., variables..., temporaries...]`.
@@ -680,7 +680,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
680680
&mut self,
681681
instance: ty::Instance<'tcx>,
682682
body: &'mir mir::Body<'tcx>,
683-
return_place: &PlaceTy<'tcx, M::Provenance>,
683+
return_place: &MPlaceTy<'tcx, M::Provenance>,
684684
return_to_block: StackPopCleanup,
685685
) -> InterpResult<'tcx> {
686686
trace!("body: {:#?}", body);
@@ -810,7 +810,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
810810
let op = self
811811
.local_to_op(self.frame(), mir::RETURN_PLACE, None)
812812
.expect("return place should always be live");
813-
let dest = self.frame().return_place.clone();
813+
let dest = self.frame().return_place.into();
814814
let err = self.copy_op(&op, &dest, /*allow_transmute*/ true);
815815
trace!("return value: {:?}", self.dump_place(*dest));
816816
// We delay actually short-circuiting on this error until *after* the stack frame is
@@ -1014,15 +1014,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> std::fmt::Debug
10141014
{
10151015
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
10161016
match self.place {
1017-
Place::Local { frame, local } => {
1017+
Place::Local { local } => {
10181018
let mut allocs = Vec::new();
1019-
write!(fmt, "{:?}", local)?;
1020-
if frame != self.ecx.frame_idx() {
1021-
write!(fmt, " ({} frames up)", self.ecx.frame_idx() - frame)?;
1022-
}
1023-
write!(fmt, ":")?;
1019+
write!(fmt, "{:?}:", local)?;
10241020

1025-
match self.ecx.stack()[frame].locals[local].value {
1021+
match self.ecx.frame().locals[local].value {
10261022
LocalValue::Dead => write!(fmt, " is dead")?,
10271023
LocalValue::Live(Operand::Immediate(Immediate::Uninit)) => {
10281024
write!(fmt, " is uninitialized")?

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
1818

1919
use super::{
2020
AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx,
21-
InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
21+
InterpResult, MPlaceTy, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
2222
};
2323

2424
/// Data returned by Machine::stack_pop,
@@ -233,22 +233,18 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
233233
right: &ImmTy<'tcx, Self::Provenance>,
234234
) -> InterpResult<'tcx, (Scalar<Self::Provenance>, bool, Ty<'tcx>)>;
235235

236-
/// Called to write the specified `local` from the `frame`.
236+
/// Called to write the specified `local` from the current frame.
237237
/// Since writing a ZST is not actually accessing memory or locals, this is never invoked
238238
/// for ZST reads.
239-
///
240-
/// Due to borrow checker trouble, we indicate the `frame` as an index rather than an `&mut
241-
/// Frame`.
242239
#[inline]
243240
fn access_local_mut<'a>(
244241
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
245-
frame: usize,
246242
local: mir::Local,
247243
) -> InterpResult<'tcx, &'a mut Operand<Self::Provenance>>
248244
where
249245
'tcx: 'mir,
250246
{
251-
ecx.stack_mut()[frame].locals[local].access_mut()
247+
ecx.frame_mut().locals[local].access_mut()
252248
}
253249

254250
/// Called before a basic block terminator is executed.
@@ -424,10 +420,10 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
424420
/// argument/return value was actually copied or passed in-place..
425421
fn protect_in_place_function_argument(
426422
ecx: &mut InterpCx<'mir, 'tcx, Self>,
427-
place: &PlaceTy<'tcx, Self::Provenance>,
423+
place: &MPlaceTy<'tcx, Self::Provenance>,
428424
) -> InterpResult<'tcx> {
429425
// Without an aliasing model, all we can do is put `Uninit` into the place.
430-
ecx.write_uninit(place)
426+
ecx.write_uninit(&place.into())
431427
}
432428

433429
/// Called immediately before a new stack frame gets pushed.

compiler/rustc_const_eval/src/interpret/operand.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,9 +504,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
504504
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
505505
let op = match **place {
506506
Place::Ptr(mplace) => Operand::Indirect(mplace),
507-
Place::Local { frame, local } => {
508-
*self.local_to_op(&self.stack()[frame], local, None)?
509-
}
507+
Place::Local { local } => *self.local_to_op(&self.frame(), local, None)?,
510508
};
511509
Ok(OpTy { op, layout: place.layout, align: Some(place.align) })
512510
}

compiler/rustc_const_eval/src/interpret/place.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ pub enum Place<Prov: Provenance = AllocId> {
7575

7676
/// To support alloc-free locals, we are able to write directly to a local.
7777
/// (Without that optimization, we'd just always be a `MemPlace`.)
78-
Local { frame: usize, local: mir::Local },
78+
/// This always refers to a local in the current stack frame. That works because `Place` is
79+
/// never stored anywhere long-term, only for the duration of evaluating a single statement.
80+
Local { local: mir::Local },
7981
}
8082

8183
#[derive(Clone, Debug)]
@@ -169,9 +171,9 @@ impl<Prov: Provenance> Place<Prov> {
169171
/// Returns the frame idx and the variable idx.
170172
#[inline]
171173
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
172-
pub fn assert_local(&self) -> (usize, mir::Local) {
174+
pub fn assert_local(&self) -> mir::Local {
173175
match self {
174-
Place::Local { frame, local } => (*frame, *local),
176+
Place::Local { local } => *local,
175177
_ => bug!("assert_local: expected Place::Local, got {:?}", self),
176178
}
177179
}
@@ -283,10 +285,10 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
283285
impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> {
284286
/// A place is either an mplace or some local.
285287
#[inline]
286-
pub fn as_mplace_or_local(&self) -> Either<MPlaceTy<'tcx, Prov>, (usize, mir::Local)> {
288+
pub fn as_mplace_or_local(&self) -> Either<MPlaceTy<'tcx, Prov>, mir::Local> {
287289
match **self {
288290
Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout, align: self.align }),
289-
Place::Local { frame, local } => Right((frame, local)),
291+
Place::Local { local } => Right(local),
290292
}
291293
}
292294

@@ -348,7 +350,7 @@ where
348350
}
349351

350352
let mplace = self.ref_to_mplace(&val)?;
351-
self.check_mplace(mplace)?;
353+
self.check_mplace(&mplace)?;
352354
Ok(mplace)
353355
}
354356

@@ -379,7 +381,7 @@ where
379381
}
380382

381383
/// Check if this mplace is dereferenceable and sufficiently aligned.
382-
pub fn check_mplace(&self, mplace: MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
384+
pub fn check_mplace(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
383385
let (size, _align) = self
384386
.size_and_align_of_mplace(&mplace)?
385387
.unwrap_or((mplace.layout.size, mplace.layout.align.abi));
@@ -418,11 +420,10 @@ where
418420

419421
pub fn local_to_place(
420422
&self,
421-
frame: usize,
422423
local: mir::Local,
423424
) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
424-
let layout = self.layout_of_local(&self.stack()[frame], local, None)?;
425-
let place = Place::Local { frame, local };
425+
let layout = self.layout_of_local(&self.frame(), local, None)?;
426+
let place = Place::Local { local };
426427
Ok(PlaceTy { place, layout, align: layout.align.abi })
427428
}
428429

@@ -433,7 +434,7 @@ where
433434
&mut self,
434435
mir_place: mir::Place<'tcx>,
435436
) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
436-
let mut place = self.local_to_place(self.frame_idx(), mir_place.local)?;
437+
let mut place = self.local_to_place(mir_place.local)?;
437438
// Using `try_fold` turned out to be bad for performance, hence the loop.
438439
for elem in mir_place.projection.iter() {
439440
place = self.place_projection(&place, elem)?
@@ -509,8 +510,8 @@ where
509510
// See if we can avoid an allocation. This is the counterpart to `read_immediate_raw`,
510511
// but not factored as a separate function.
511512
let mplace = match dest.place {
512-
Place::Local { frame, local } => {
513-
match M::access_local_mut(self, frame, local)? {
513+
Place::Local { local } => {
514+
match M::access_local_mut(self, local)? {
514515
Operand::Immediate(local) => {
515516
// Local can be updated in-place.
516517
*local = src;
@@ -593,8 +594,8 @@ where
593594
pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
594595
let mplace = match dest.as_mplace_or_local() {
595596
Left(mplace) => mplace,
596-
Right((frame, local)) => {
597-
match M::access_local_mut(self, frame, local)? {
597+
Right(local) => {
598+
match M::access_local_mut(self, local)? {
598599
Operand::Immediate(local) => {
599600
*local = Immediate::Uninit;
600601
return Ok(());
@@ -728,16 +729,15 @@ where
728729
place: &PlaceTy<'tcx, M::Provenance>,
729730
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
730731
let mplace = match place.place {
731-
Place::Local { frame, local } => {
732-
match M::access_local_mut(self, frame, local)? {
732+
Place::Local { local } => {
733+
match M::access_local_mut(self, local)? {
733734
&mut Operand::Immediate(local_val) => {
734735
// We need to make an allocation.
735736

736737
// We need the layout of the local. We can NOT use the layout we got,
737738
// that might e.g., be an inner field of a struct with `Scalar` layout,
738739
// that has different alignment than the outer field.
739-
let local_layout =
740-
self.layout_of_local(&self.stack()[frame], local, None)?;
740+
let local_layout = self.layout_of_local(&self.frame(), local, None)?;
741741
if local_layout.is_unsized() {
742742
throw_unsup_format!("unsized locals are not supported");
743743
}
@@ -755,8 +755,7 @@ where
755755
}
756756
// Now we can call `access_mut` again, asserting it goes well,
757757
// and actually overwrite things.
758-
*M::access_local_mut(self, frame, local).unwrap() =
759-
Operand::Indirect(mplace);
758+
*M::access_local_mut(self, local).unwrap() = Operand::Indirect(mplace);
760759
mplace
761760
}
762761
&mut Operand::Indirect(mplace) => mplace, // this already was an indirect local

0 commit comments

Comments
 (0)