interpret: remove LocalValue::Unallocated, add Operand::Uninit
Operand::Uninit is an *allocated* operand that is fully uninitialized. This lets us lazily allocate the actual backing store of *all* locals (no matter their ABI). I also reordered things in pop_stack_frame at the same time. I should probably have made that a separate commit...
This commit is contained in:
parent
049308cf8b
commit
8ef0caa23c
8 changed files with 179 additions and 175 deletions
|
@ -29,9 +29,8 @@ use rustc_trait_selection::traits;
|
|||
use crate::MirPass;
|
||||
use rustc_const_eval::interpret::{
|
||||
self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
|
||||
ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy,
|
||||
Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
|
||||
StackPopUnwind,
|
||||
ImmTy, Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemoryKind, OpTy, PlaceTy,
|
||||
Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind,
|
||||
};
|
||||
|
||||
/// The maximum number of bytes that we'll allocate space for a local or the return value.
|
||||
|
@ -237,15 +236,19 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp")
|
||||
}
|
||||
|
||||
fn access_local(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
|
||||
fn access_local<'a>(
|
||||
frame: &'a Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>,
|
||||
local: Local,
|
||||
) -> InterpResult<'tcx, InterpOperand<Self::PointerTag>> {
|
||||
) -> InterpResult<'tcx, &'a interpret::Operand<Self::PointerTag>> {
|
||||
let l = &frame.locals[local];
|
||||
|
||||
if l.value == LocalValue::Unallocated {
|
||||
throw_machine_stop_str!("tried to access an unallocated local")
|
||||
if matches!(
|
||||
l.value,
|
||||
LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit))
|
||||
) {
|
||||
// For us "uninit" means "we don't know its value, might be initiailized or not".
|
||||
// So stop here.
|
||||
throw_machine_stop_str!("tried to access alocal with unknown value ")
|
||||
}
|
||||
|
||||
l.access()
|
||||
|
@ -255,8 +258,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
|
|||
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||
frame: usize,
|
||||
local: Local,
|
||||
) -> InterpResult<'tcx, Result<&'a mut LocalValue<Self::PointerTag>, MemPlace<Self::PointerTag>>>
|
||||
{
|
||||
) -> InterpResult<'tcx, &'a mut interpret::Operand<Self::PointerTag>> {
|
||||
if ecx.machine.can_const_prop[local] == ConstPropMode::NoPropagation {
|
||||
throw_machine_stop_str!("tried to write to a local that is marked as not propagatable")
|
||||
}
|
||||
|
@ -436,8 +438,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
/// Remove `local` from the pool of `Locals`. Allows writing to them,
|
||||
/// but not reading from them anymore.
|
||||
fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) {
|
||||
ecx.frame_mut().locals[local] =
|
||||
LocalState { value: LocalValue::Unallocated, layout: Cell::new(None) };
|
||||
ecx.frame_mut().locals[local] = LocalState {
|
||||
value: LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit)),
|
||||
layout: Cell::new(None),
|
||||
};
|
||||
}
|
||||
|
||||
fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
|
||||
|
@ -1042,7 +1046,9 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
|
|||
let frame = self.ecx.frame_mut();
|
||||
frame.locals[local].value =
|
||||
if let StatementKind::StorageLive(_) = statement.kind {
|
||||
LocalValue::Unallocated
|
||||
LocalValue::Live(interpret::Operand::Immediate(
|
||||
interpret::Immediate::Uninit,
|
||||
))
|
||||
} else {
|
||||
LocalValue::Dead
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue