diff options
| author | bors <bors@rust-lang.org> | 2024-03-07 12:33:19 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-07 12:33:19 +0000 |
| commit | 52f8aec14c616387c5f793687f2d9026de6c78ca (patch) | |
| tree | c55fec4a963e041b0dab8762c57d6a224daeaee7 /compiler/rustc_const_eval/src | |
| parent | 8c9a75b3238b66592779d6b240dbf78eacefebb8 (diff) | |
| parent | 3f0b6a0d1c5ab7146035dd993113ff348aefe94f (diff) | |
| download | rust-52f8aec14c616387c5f793687f2d9026de6c78ca.tar.gz rust-52f8aec14c616387c5f793687f2d9026de6c78ca.zip | |
Auto merge of #121985 - RalfJung:interpret-return-place, r=oli-obk
interpret: avoid a long-lived PlaceTy in stack frames `PlaceTy` uses a representation that's not very stable under changes to the stack. I'd feel better if we didn't have one in the long-term machine state. r? `@oli-obk`
Diffstat (limited to 'compiler/rustc_const_eval/src')
6 files changed, 27 insertions, 31 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 946ffc05cc1..864241fbd4a 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -24,7 +24,7 @@ use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ self, compile_time_machine, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, FnVal, - Frame, ImmTy, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, PointerArithmetic, Scalar, + Frame, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, Scalar, }; use super::error::*; @@ -219,7 +219,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[FnArg<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> { let def_id = instance.def_id(); @@ -280,7 +280,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx, ControlFlow<()>> { assert_eq!(args.len(), 2); @@ -410,7 +410,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, orig_instance: ty::Instance<'tcx>, _abi: CallAbi, args: &[FnArg<'tcx>], - dest: &PlaceTy<'tcx>, + dest: &MPlaceTy<'tcx>, ret: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, // unwinding is not supported in consts ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { @@ -455,7 +455,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - dest: &PlaceTy<'tcx, Self::Provenance>, + dest: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cb308ab53ec..a484fbd892c 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -108,7 +108,7 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> { /// The location where the result of the current stack frame should be written to, /// and its layout in the caller. - pub return_place: PlaceTy<'tcx, Prov>, + pub return_place: MPlaceTy<'tcx, Prov>, /// The list of locals for this stack frame, stored in order as /// `[return_ptr, arguments..., variables..., temporaries...]`. @@ -771,7 +771,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, body: &'mir mir::Body<'tcx>, - return_place: &PlaceTy<'tcx, M::Provenance>, + return_place: &MPlaceTy<'tcx, M::Provenance>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { trace!("body: {:#?}", body); @@ -912,7 +912,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.copy_op_allow_transmute(&op, &dest) }; - trace!("return value: {:?}", self.dump_place(&dest)); + trace!("return value: {:?}", self.dump_place(&dest.into())); // We delay actually short-circuiting on this error until *after* the stack frame is // popped, since we want this error to be attributed to the caller, whose type defines // this transmute. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 1cb991b38f7..b68bfb4211d 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -21,7 +21,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::Size; use super::{ - util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy, + util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, MPlaceTy, Machine, OpTy, Pointer, }; @@ -104,7 +104,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::Provenance>], - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &MPlaceTy<'tcx, M::Provenance>, ret: Option<mir::BasicBlock>, ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; @@ -377,7 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); let elem = &args[2]; let (input, input_len) = self.operand_to_simd(&args[0])?; - let (dest, dest_len) = self.place_to_simd(dest)?; + let (dest, dest_len) = self.mplace_to_simd(dest)?; assert_eq!(input_len, dest_len, "Return vector length must match input length"); // Bounds are not checked by typeck so we have to do it ourselves. if index >= input_len { @@ -430,7 +430,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { _ => return Ok(false), } - trace!("{:?}", self.dump_place(dest)); + trace!("{:?}", self.dump_place(&dest.clone().into())); self.go_to_block(ret); Ok(true) } @@ -488,7 +488,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, a: &ImmTy<'tcx, M::Provenance>, b: &ImmTy<'tcx, M::Provenance>, - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &MPlaceTy<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { assert_eq!(a.layout.ty, b.layout.ty); assert!(matches!(a.layout.ty.kind(), ty::Int(..) | ty::Uint(..))); @@ -506,7 +506,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } // `Rem` says this is all right, so we can let `Div` do its job. - self.binop_ignore_overflow(BinOp::Div, a, b, dest) + self.binop_ignore_overflow(BinOp::Div, a, b, &dest.clone().into()) } pub fn saturating_arith( diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 0106ec425bc..ee5de44a651 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -196,7 +196,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { instance: ty::Instance<'tcx>, abi: CallAbi, args: &[FnArg<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>; @@ -208,7 +208,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { fn_val: Self::ExtraFnVal, abi: CallAbi, args: &[FnArg<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -219,7 +219,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, + destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx>; @@ -584,7 +584,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) { fn_val: !, _abi: CallAbi, _args: &[FnArg<$tcx>], - _destination: &PlaceTy<$tcx, Self::Provenance>, + _destination: &MPlaceTy<$tcx, Self::Provenance>, _target: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, ) -> InterpResult<$tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 672008edfd3..60f7710c11d 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -194,6 +194,12 @@ pub(super) enum Place<Prov: Provenance = CtfeProvenance> { Local { frame: usize, local: mir::Local, offset: Option<Size> }, } +/// An evaluated place, together with its type. +/// +/// This may reference a stack frame by its index, so `PlaceTy` should generally not be kept around +/// for longer than a single operation. Popping and then pushing a stack frame can make `PlaceTy` +/// point to the wrong destination. If the interpreter has multiple stacks, stack switching will +/// also invalidate a `PlaceTy`. #[derive(Clone)] pub struct PlaceTy<'tcx, Prov: Provenance = CtfeProvenance> { place: Place<Prov>, // Keep this private; it helps enforce invariants. @@ -495,16 +501,6 @@ where Ok((mplace, len)) } - /// Converts a repr(simd) place into a place where `place_index` accesses the SIMD elements. - /// Also returns the number of elements. - pub fn place_to_simd( - &mut self, - place: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, u64)> { - let mplace = self.force_allocation(place)?; - self.mplace_to_simd(&mplace) - } - pub fn local_to_place( &self, frame: usize, diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d29e69d753e..55f85573f38 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -153,7 +153,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), }; - let destination = self.eval_place(destination)?; + let destination = self.force_allocation(&self.eval_place(destination)?)?; self.eval_fn_call( fn_val, (fn_sig.abi, fn_abi), @@ -497,7 +497,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), args: &[FnArg<'tcx, M::Provenance>], with_caller_location: bool, - destination: &PlaceTy<'tcx, M::Provenance>, + destination: &MPlaceTy<'tcx, M::Provenance>, target: Option<mir::BasicBlock>, mut unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { @@ -726,7 +726,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }); } // Protect return place for in-place return value passing. - M::protect_in_place_function_argument(self, destination)?; + M::protect_in_place_function_argument(self, &destination.clone().into())?; // Don't forget to mark "initially live" locals as live. self.storage_live_for_always_live_locals()?; |
