move interpret::MemoryKind::Heap to const eval
This commit is contained in:
parent
d015f0d921
commit
ff0ebd27a4
5 changed files with 48 additions and 21 deletions
|
@ -7,6 +7,7 @@ use std::collections::hash_map::Entry;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -179,6 +180,28 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
|
||||||
crate type CompileTimeEvalContext<'mir, 'tcx> =
|
crate type CompileTimeEvalContext<'mir, 'tcx> =
|
||||||
InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
|
InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub enum MemoryKind {
|
||||||
|
Heap,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MemoryKind {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
MemoryKind::Heap => write!(f, "heap allocation"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl interpret::MayLeak for MemoryKind {
|
||||||
|
#[inline(always)]
|
||||||
|
fn may_leak(self) -> bool {
|
||||||
|
match self {
|
||||||
|
MemoryKind::Heap => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl interpret::MayLeak for ! {
|
impl interpret::MayLeak for ! {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn may_leak(self) -> bool {
|
fn may_leak(self) -> bool {
|
||||||
|
@ -222,6 +245,8 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
|
||||||
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
|
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, 'tcx> {
|
||||||
compile_time_machine!(<'mir, 'tcx>);
|
compile_time_machine!(<'mir, 'tcx>);
|
||||||
|
|
||||||
|
type MemoryKind = MemoryKind;
|
||||||
|
|
||||||
type MemoryExtra = MemoryExtra;
|
type MemoryExtra = MemoryExtra;
|
||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
fn find_mir_or_eval_fn(
|
||||||
|
@ -317,7 +342,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||||
let ptr = ecx.memory.allocate(
|
let ptr = ecx.memory.allocate(
|
||||||
Size::from_bytes(size as u64),
|
Size::from_bytes(size as u64),
|
||||||
align,
|
align,
|
||||||
interpret::MemoryKind::ConstHeap,
|
interpret::MemoryKind::Machine(MemoryKind::Heap),
|
||||||
);
|
);
|
||||||
ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
|
ecx.write_scalar(Scalar::Ptr(ptr), dest)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,19 +25,20 @@ use rustc_target::abi::Size;
|
||||||
use rustc_ast::Mutability;
|
use rustc_ast::Mutability;
|
||||||
|
|
||||||
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
|
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, Scalar, ValueVisitor};
|
||||||
|
use crate::const_eval;
|
||||||
|
|
||||||
pub trait CompileTimeMachine<'mir, 'tcx> = Machine<
|
pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
|
||||||
'mir,
|
'mir,
|
||||||
'tcx,
|
'tcx,
|
||||||
MemoryKind = !,
|
MemoryKind = T,
|
||||||
PointerTag = (),
|
PointerTag = (),
|
||||||
ExtraFnVal = !,
|
ExtraFnVal = !,
|
||||||
FrameExtra = (),
|
FrameExtra = (),
|
||||||
AllocExtra = (),
|
AllocExtra = (),
|
||||||
MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>,
|
MemoryMap = FxHashMap<AllocId, (MemoryKind<T>, Allocation)>,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> {
|
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
|
||||||
/// The ectx from which we intern.
|
/// The ectx from which we intern.
|
||||||
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||||
/// Previously encountered safe references.
|
/// Previously encountered safe references.
|
||||||
|
@ -74,7 +75,7 @@ struct IsStaticOrFn;
|
||||||
/// `immutable` things might become mutable if `ty` is not frozen.
|
/// `immutable` things might become mutable if `ty` is not frozen.
|
||||||
/// `ty` can be `None` if there is no potential interior mutability
|
/// `ty` can be `None` if there is no potential interior mutability
|
||||||
/// to account for (e.g. for vtables).
|
/// to account for (e.g. for vtables).
|
||||||
fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
|
||||||
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
|
||||||
leftover_allocations: &'rt mut FxHashSet<AllocId>,
|
leftover_allocations: &'rt mut FxHashSet<AllocId>,
|
||||||
alloc_id: AllocId,
|
alloc_id: AllocId,
|
||||||
|
@ -105,7 +106,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
||||||
// changes in this function.
|
// changes in this function.
|
||||||
match kind {
|
match kind {
|
||||||
MemoryKind::Stack
|
MemoryKind::Stack
|
||||||
| MemoryKind::ConstHeap
|
| MemoryKind::Machine(const_eval::MemoryKind::Heap)
|
||||||
| MemoryKind::Vtable
|
| MemoryKind::Vtable
|
||||||
| MemoryKind::CallerLocation => {}
|
| MemoryKind::CallerLocation => {}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +142,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> {
|
impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
|
||||||
|
InternVisitor<'rt, 'mir, 'tcx, M>
|
||||||
|
{
|
||||||
fn intern_shallow(
|
fn intern_shallow(
|
||||||
&mut self,
|
&mut self,
|
||||||
alloc_id: AllocId,
|
alloc_id: AllocId,
|
||||||
|
@ -152,8 +155,8 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>
|
||||||
for InternVisitor<'rt, 'mir, 'tcx, M>
|
ValueVisitor<'mir, 'tcx, M> for InternVisitor<'rt, 'mir, 'tcx, M>
|
||||||
{
|
{
|
||||||
type V = MPlaceTy<'tcx>;
|
type V = MPlaceTy<'tcx>;
|
||||||
|
|
||||||
|
@ -290,7 +293,7 @@ pub enum InternKind {
|
||||||
/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
|
/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
|
||||||
/// are hard errors.
|
/// are hard errors.
|
||||||
#[tracing::instrument(skip(ecx))]
|
#[tracing::instrument(skip(ecx))]
|
||||||
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||||
intern_kind: InternKind,
|
intern_kind: InternKind,
|
||||||
ret: MPlaceTy<'tcx>,
|
ret: MPlaceTy<'tcx>,
|
||||||
|
@ -421,7 +424,9 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
||||||
|
InterpCx<'mir, 'tcx, M>
|
||||||
|
{
|
||||||
/// A helper function that allocates memory for the layout given and gives you access to mutate
|
/// A helper function that allocates memory for the layout given and gives you access to mutate
|
||||||
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
/// it. Once your own mutation code is done, the backing `Allocation` is removed from the
|
||||||
/// current `Memory` and returned.
|
/// current `Memory` and returned.
|
||||||
|
|
|
@ -366,9 +366,9 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||||
type PointerTag = ();
|
type PointerTag = ();
|
||||||
type ExtraFnVal = !;
|
type ExtraFnVal = !;
|
||||||
|
|
||||||
type MemoryKind = !;
|
type MemoryMap =
|
||||||
type MemoryMap = rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
|
rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
|
||||||
const GLOBAL_KIND: Option<!> = None; // no copying of globals from `tcx` to machine memory
|
const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory
|
||||||
|
|
||||||
type AllocExtra = ();
|
type AllocExtra = ();
|
||||||
type FrameExtra = ();
|
type FrameExtra = ();
|
||||||
|
@ -407,7 +407,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||||
_memory_extra: &Self::MemoryExtra,
|
_memory_extra: &Self::MemoryExtra,
|
||||||
_id: AllocId,
|
_id: AllocId,
|
||||||
alloc: Cow<'b, Allocation>,
|
alloc: Cow<'b, Allocation>,
|
||||||
_kind: Option<MemoryKind<!>>,
|
_kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||||
) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
|
) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
|
||||||
// We do not use a tag so we can just cheaply forward the allocation
|
// We do not use a tag so we can just cheaply forward the allocation
|
||||||
(alloc, ())
|
(alloc, ())
|
||||||
|
|
|
@ -27,9 +27,6 @@ use crate::util::pretty;
|
||||||
pub enum MemoryKind<T> {
|
pub enum MemoryKind<T> {
|
||||||
/// Stack memory. Error if deallocated except during a stack pop.
|
/// Stack memory. Error if deallocated except during a stack pop.
|
||||||
Stack,
|
Stack,
|
||||||
/// Heap memory.
|
|
||||||
/// FIXME: this variant should be in const_eval
|
|
||||||
ConstHeap,
|
|
||||||
/// Memory backing vtables. Error if ever deallocated.
|
/// Memory backing vtables. Error if ever deallocated.
|
||||||
Vtable,
|
Vtable,
|
||||||
/// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
|
/// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
|
||||||
|
@ -43,7 +40,6 @@ impl<T: MayLeak> MayLeak for MemoryKind<T> {
|
||||||
fn may_leak(self) -> bool {
|
fn may_leak(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
MemoryKind::Stack => false,
|
MemoryKind::Stack => false,
|
||||||
MemoryKind::ConstHeap => false,
|
|
||||||
MemoryKind::Vtable => true,
|
MemoryKind::Vtable => true,
|
||||||
MemoryKind::CallerLocation => true,
|
MemoryKind::CallerLocation => true,
|
||||||
MemoryKind::Machine(k) => k.may_leak(),
|
MemoryKind::Machine(k) => k.may_leak(),
|
||||||
|
@ -55,7 +51,6 @@ impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
MemoryKind::Stack => write!(f, "stack variable"),
|
MemoryKind::Stack => write!(f, "stack variable"),
|
||||||
MemoryKind::ConstHeap => write!(f, "heap allocation"),
|
|
||||||
MemoryKind::Vtable => write!(f, "vtable"),
|
MemoryKind::Vtable => write!(f, "vtable"),
|
||||||
MemoryKind::CallerLocation => write!(f, "caller location"),
|
MemoryKind::CallerLocation => write!(f, "caller location"),
|
||||||
MemoryKind::Machine(m) => write!(f, "{}", m),
|
MemoryKind::Machine(m) => write!(f, "{}", m),
|
||||||
|
|
|
@ -180,6 +180,8 @@ impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> {
|
||||||
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
|
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> {
|
||||||
compile_time_machine!(<'mir, 'tcx>);
|
compile_time_machine!(<'mir, 'tcx>);
|
||||||
|
|
||||||
|
type MemoryKind = !;
|
||||||
|
|
||||||
type MemoryExtra = ();
|
type MemoryExtra = ();
|
||||||
|
|
||||||
fn find_mir_or_eval_fn(
|
fn find_mir_or_eval_fn(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue