Skip to content

Commit fa5f137

Browse files
committed
interpret: make MemPlace, Place, Operand types private to the interpreter
1 parent a989e25 commit fa5f137

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+417
-338
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
7979
intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
8080
// we leave alignment checks off, since this `ecx` will not be used for further evaluation anyway
8181

82-
debug!("eval_body_using_ecx done: {:?}", *ret);
82+
debug!("eval_body_using_ecx done: {:?}", ret);
8383
Ok(ret)
8484
}
8585

@@ -147,7 +147,7 @@ pub(super) fn op_to_const<'tcx>(
147147
// We know `offset` is relative to the allocation, so we can use `into_parts`.
148148
let to_const_value = |mplace: &MPlaceTy<'_>| {
149149
debug!("to_const_value(mplace: {:?})", mplace);
150-
match mplace.ptr.into_parts() {
150+
match mplace.ptr().into_parts() {
151151
(Some(alloc_id), offset) => {
152152
let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
153153
ConstValue::ByRef { alloc, offset }
@@ -370,7 +370,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
370370
inner = true;
371371
}
372372
};
373-
let alloc_id = mplace.ptr.provenance.unwrap();
373+
let alloc_id = mplace.ptr().provenance.unwrap();
374374

375375
// Validation failed, report an error. This is always a hard error.
376376
if let Err(error) = validation {

compiler/rustc_const_eval/src/const_eval/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub(crate) fn const_caller_location(
3030
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
3131
bug!("intern_const_alloc_recursive should not error in this case")
3232
}
33-
ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
33+
ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr(), &tcx))
3434
}
3535

3636
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.

compiler/rustc_const_eval/src/const_eval/valtrees.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::const_eval::CanAccessStatics;
55
use crate::interpret::MPlaceTy;
66
use crate::interpret::{
77
intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
8-
MemoryKind, Place, Projectable, Scalar,
8+
MemoryKind, PlaceTy, Projectable, Scalar,
99
};
1010
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
1111
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
@@ -318,7 +318,7 @@ fn valtree_into_mplace<'tcx>(
318318
let len_scalar = Scalar::from_target_usize(len as u64, &tcx);
319319

320320
Immediate::ScalarPair(
321-
Scalar::from_maybe_pointer((*pointee_place).ptr, &tcx),
321+
Scalar::from_maybe_pointer(pointee_place.ptr(), &tcx),
322322
len_scalar,
323323
)
324324
}
@@ -383,5 +383,5 @@ fn valtree_into_mplace<'tcx>(
383383
}
384384

385385
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx, 'tcx>, place: &MPlaceTy<'tcx>) {
386-
trace!("{:?}", ecx.dump_place(Place::Ptr(**place)));
386+
trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone())));
387387
}

compiler/rustc_const_eval/src/interpret/eval_context.rs

+45-16
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, PlaceTy, Pointer, PointerArithmetic,
25+
Projectable, Provenance, Scalar, StackPopJump,
2626
};
2727
use crate::errors::{self, ErroneousConstUsed};
2828
use crate::util;
@@ -155,17 +155,26 @@ pub enum StackPopCleanup {
155155
}
156156

157157
/// State of a local variable including a memoized layout
158-
#[derive(Clone, Debug)]
158+
#[derive(Clone)]
159159
pub struct LocalState<'tcx, Prov: Provenance = AllocId> {
160-
pub value: LocalValue<Prov>,
160+
value: LocalValue<Prov>,
161161
/// Don't modify if `Some`, this is only used to prevent computing the layout twice.
162162
/// Avoids computing the layout of locals that are never actually initialized.
163-
pub layout: Cell<Option<TyAndLayout<'tcx>>>,
163+
layout: Cell<Option<TyAndLayout<'tcx>>>,
164+
}
165+
166+
impl<Prov: Provenance> std::fmt::Debug for LocalState<'_, Prov> {
167+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168+
f.debug_struct("LocalState")
169+
.field("value", &self.value)
170+
.field("ty", &self.layout.get().map(|l| l.ty))
171+
.finish()
172+
}
164173
}
165174

166175
/// Current value of a local variable
167176
#[derive(Copy, Clone, Debug)] // Miri debug-prints these
168-
pub enum LocalValue<Prov: Provenance = AllocId> {
177+
pub(super) enum LocalValue<Prov: Provenance = AllocId> {
169178
/// This local is not currently alive, and cannot be used at all.
170179
Dead,
171180
/// A normal, live local.
@@ -176,10 +185,27 @@ pub enum LocalValue<Prov: Provenance = AllocId> {
176185
Live(Operand<Prov>),
177186
}
178187

179-
impl<'tcx, Prov: Provenance + 'static> LocalState<'tcx, Prov> {
188+
impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
189+
pub fn make_live_uninit(&mut self) {
190+
self.value = LocalValue::Live(Operand::Immediate(Immediate::Uninit));
191+
}
192+
193+
/// This is a hack because Miri needs a way to visit all the provenance in a `LocalState`
194+
/// without having a layout or `TyCtxt` available, and we want to keep the `Operand` type
195+
/// private.
196+
pub fn as_mplace_or_imm(
197+
&self,
198+
) -> Option<Either<(Pointer<Option<Prov>>, MemPlaceMeta<Prov>), Immediate<Prov>>> {
199+
match self.value {
200+
LocalValue::Dead => None,
201+
LocalValue::Live(Operand::Indirect(mplace)) => Some(Left((mplace.ptr, mplace.meta))),
202+
LocalValue::Live(Operand::Immediate(imm)) => Some(Right(imm)),
203+
}
204+
}
205+
180206
/// Read the local's value or error if the local is not yet live or not live anymore.
181207
#[inline(always)]
182-
pub fn access(&self) -> InterpResult<'tcx, &Operand<Prov>> {
208+
pub(super) fn access(&self) -> InterpResult<'tcx, &Operand<Prov>> {
183209
match &self.value {
184210
LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
185211
LocalValue::Live(val) => Ok(val),
@@ -189,10 +215,10 @@ impl<'tcx, Prov: Provenance + 'static> LocalState<'tcx, Prov> {
189215
/// Overwrite the local. If the local can be overwritten in place, return a reference
190216
/// to do so; otherwise return the `MemPlace` to consult instead.
191217
///
192-
/// Note: This may only be invoked from the `Machine::access_local_mut` hook and not from
193-
/// anywhere else. You may be invalidating machine invariants if you do!
218+
/// Note: Before calling this, call the `before_access_local_mut` machine hook! You may be
219+
/// invalidating machine invariants otherwise!
194220
#[inline(always)]
195-
pub fn access_mut(&mut self) -> InterpResult<'tcx, &mut Operand<Prov>> {
221+
pub(super) fn access_mut(&mut self) -> InterpResult<'tcx, &mut Operand<Prov>> {
196222
match &mut self.value {
197223
LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
198224
LocalValue::Live(val) => Ok(val),
@@ -694,7 +720,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
694720
&self,
695721
mplace: &MPlaceTy<'tcx, M::Provenance>,
696722
) -> InterpResult<'tcx, Option<(Size, Align)>> {
697-
self.size_and_align_of(&mplace.meta, &mplace.layout)
723+
self.size_and_align_of(&mplace.meta(), &mplace.layout)
698724
}
699725

700726
#[instrument(skip(self, body, return_place, return_to_block), level = "debug")]
@@ -826,7 +852,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
826852
.expect("return place should always be live");
827853
let dest = self.frame().return_place.clone();
828854
let err = self.copy_op(&op, &dest, /*allow_transmute*/ true);
829-
trace!("return value: {:?}", self.dump_place(*dest));
855+
trace!("return value: {:?}", self.dump_place(&dest));
830856
// We delay actually short-circuiting on this error until *after* the stack frame is
831857
// popped, since we want this error to be attributed to the caller, whose type defines
832858
// this transmute.
@@ -974,7 +1000,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9741000
}
9751001
// Need to allocate some memory, since `Immediate::Uninit` cannot be unsized.
9761002
let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?;
977-
Operand::Indirect(*dest_place)
1003+
Operand::Indirect(*dest_place.mplace())
9781004
} else {
9791005
assert!(!meta.has_meta()); // we're dropping the metadata
9801006
// Just make this an efficient immediate.
@@ -1068,8 +1094,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
10681094
}
10691095

10701096
#[must_use]
1071-
pub fn dump_place(&self, place: Place<M::Provenance>) -> PlacePrinter<'_, 'mir, 'tcx, M> {
1072-
PlacePrinter { ecx: self, place }
1097+
pub fn dump_place(
1098+
&self,
1099+
place: &PlaceTy<'tcx, M::Provenance>,
1100+
) -> PlacePrinter<'_, 'mir, 'tcx, M> {
1101+
PlacePrinter { ecx: self, place: *place.place() }
10731102
}
10741103

10751104
#[must_use]

compiler/rustc_const_eval/src/interpret/intern.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_ast::Mutability;
2525

2626
use super::{
2727
AllocId, Allocation, ConstAllocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy,
28-
ValueVisitor,
28+
Projectable, ValueVisitor,
2929
};
3030
use crate::const_eval;
3131
use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer};
@@ -177,7 +177,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
177177
if let ty::Dynamic(_, _, ty::Dyn) =
178178
tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind()
179179
{
180-
let ptr = mplace.meta.unwrap_meta().to_pointer(&tcx)?;
180+
let ptr = mplace.meta().unwrap_meta().to_pointer(&tcx)?;
181181
if let Some(alloc_id) = ptr.provenance {
182182
// Explicitly choose const mode here, since vtables are immutable, even
183183
// if the reference of the fat pointer is mutable.
@@ -191,7 +191,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
191191
}
192192
// Check if we have encountered this pointer+layout combination before.
193193
// Only recurse for allocation-backed pointers.
194-
if let Some(alloc_id) = mplace.ptr.provenance {
194+
if let Some(alloc_id) = mplace.ptr().provenance {
195195
// Compute the mode with which we intern this. Our goal here is to make as many
196196
// statics as we can immutable so they can be placed in read-only memory by LLVM.
197197
let ref_mode = match self.mode {
@@ -267,7 +267,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
267267

268268
// If there is no provenance in this allocation, it does not contain references
269269
// that point to another allocation, and we can avoid the interning walk.
270-
if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr, size, align)? {
270+
if let Some(alloc) = self.ecx.get_ptr_alloc(mplace.ptr(), size, align)? {
271271
if !alloc.has_provenance() {
272272
return Ok(false);
273273
}
@@ -353,7 +353,7 @@ pub fn intern_const_alloc_recursive<
353353
leftover_allocations,
354354
// The outermost allocation must exist, because we allocated it with
355355
// `Memory::allocate`.
356-
ret.ptr.provenance.unwrap(),
356+
ret.ptr().provenance.unwrap(),
357357
base_intern_mode,
358358
Some(ret.layout.ty),
359359
);
@@ -466,7 +466,7 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
466466
) -> InterpResult<'tcx, ConstAllocation<'tcx>> {
467467
let dest = self.allocate(layout, MemoryKind::Stack)?;
468468
f(self, &dest.clone().into())?;
469-
let mut alloc = self.memory.alloc_map.remove(&dest.ptr.provenance.unwrap()).unwrap().1;
469+
let mut alloc = self.memory.alloc_map.remove(&dest.ptr().provenance.unwrap()).unwrap().1;
470470
alloc.mutability = Mutability::Not;
471471
Ok(self.tcx.mk_const_alloc(alloc))
472472
}

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
466466
_ => return Ok(false),
467467
}
468468

469-
trace!("{:?}", self.dump_place(**dest));
469+
trace!("{:?}", self.dump_place(dest));
470470
self.go_to_block(ret);
471471
Ok(true)
472472
}

compiler/rustc_const_eval/src/interpret/machine.rs

+9-9
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, MPlaceTy, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
21+
InterpResult, MPlaceTy, MemoryKind, OpTy, PlaceTy, Pointer, Provenance, Scalar,
2222
};
2323

2424
/// Data returned by Machine::stack_pop,
@@ -237,22 +237,22 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
237237
right: &ImmTy<'tcx, Self::Provenance>,
238238
) -> InterpResult<'tcx, (Scalar<Self::Provenance>, bool, Ty<'tcx>)>;
239239

240-
/// Called to write the specified `local` from the `frame`.
240+
/// Called before writing the specified `local` of the `frame`.
241241
/// Since writing a ZST is not actually accessing memory or locals, this is never invoked
242242
/// for ZST reads.
243243
///
244244
/// Due to borrow checker trouble, we indicate the `frame` as an index rather than an `&mut
245245
/// Frame`.
246-
#[inline]
247-
fn access_local_mut<'a>(
248-
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
249-
frame: usize,
250-
local: mir::Local,
251-
) -> InterpResult<'tcx, &'a mut Operand<Self::Provenance>>
246+
#[inline(always)]
247+
fn before_access_local_mut<'a>(
248+
_ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
249+
_frame: usize,
250+
_local: mir::Local,
251+
) -> InterpResult<'tcx>
252252
where
253253
'tcx: 'mir,
254254
{
255-
ecx.stack_mut()[frame].locals[local].access_mut()
255+
Ok(())
256256
}
257257

258258
/// Called before a basic block terminator is executed.

compiler/rustc_const_eval/src/interpret/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,21 @@ mod visitor;
2020

2121
pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
2222

23-
pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup};
23+
pub use self::eval_context::{Frame, FrameInfo, InterpCx, StackPopCleanup};
2424
pub use self::intern::{intern_const_alloc_recursive, InternKind};
2525
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
2626
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
27-
pub use self::operand::{ImmTy, Immediate, OpTy, Operand, Readable};
28-
pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy, Writeable};
27+
pub use self::operand::{ImmTy, Immediate, OpTy, Readable};
28+
pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable};
2929
pub use self::projection::Projectable;
3030
pub use self::terminator::FnArg;
3131
pub use self::validity::{CtfeValidationMode, RefTracking};
3232
pub use self::visitor::ValueVisitor;
3333

34+
use self::{
35+
operand::Operand,
36+
place::{MemPlace, Place},
37+
};
38+
3439
pub(crate) use self::intrinsics::eval_nullary_intrinsic;
3540
use eval_context::{from_known_layout, mir_assign_valid_types};

0 commit comments

Comments
 (0)