//! The memory subsystem.
//!
//! Generally, we use `Pointer` to denote memory addresses. However, some operations
//! have a "size"-like parameter, and they take `Scalar` for the address because
//! if the size is 0, then the pointer can also be a (properly aligned, non-null)
//! integer. It is crucial that these operations call `check_align` *before*
//! short-circuiting the empty case!

use std::borrow::{Borrow, Cow};
use std::cell::Cell;
use std::collections::VecDeque;
use std::{assert_matches, fmt, ptr};

use rustc_abi::{Align, HasDataLayout, Size};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_middle::bug;
use rustc_middle::mir::display_allocation;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use tracing::{debug, instrument, trace};

use super::{
    AllocBytes, AllocId, AllocInit, AllocMap, AllocRange, Allocation, CheckAlignMsg,
    CheckInAllocMsg, CtfeProvenance, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine,
    MayLeak, Misalignment, Pointer, PointerArithmetic, Provenance, Scalar, alloc_range, err_ub,
    err_ub_format, interp_ok, throw_ub, throw_ub_format, throw_unsup, throw_unsup_format,
};
use crate::const_eval::ConstEvalErrKind;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum MemoryKind<T> {
    /// Stack memory. Error if deallocated except during a stack pop.
    Stack,
    /// Memory allocated by `caller_location` intrinsic. Error if ever deallocated.
    CallerLocation,
    /// Additional memory kinds a machine wishes to distinguish from the builtin ones.
    Machine(T),
}

impl<T: MayLeak> MayLeak for MemoryKind<T> {
    #[inline]
    fn may_leak(self) -> bool {
        match self {
            MemoryKind::Stack => false,
            MemoryKind::CallerLocation => true,
            MemoryKind::Machine(k) => k.may_leak(),
        }
    }
}

impl<T: fmt::Display> fmt::Display for MemoryKind<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            MemoryKind::Stack => write!(f, "stack variable"),
            MemoryKind::CallerLocation => write!(f, "caller location"),
            MemoryKind::Machine(m) => write!(f, "{m}"),
        }
    }
}

/// The return value of `get_alloc_info` indicates the "kind" of the allocation.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum AllocKind {
    /// A regular live data allocation.
    LiveData,
    /// A function allocation (that fn ptrs point to).
    Function,
    /// A variable argument list allocation (used by c-variadic functions).
    VaList,
    /// A vtable allocation.
    VTable,
    /// A TypeId allocation.
    TypeId,
    /// A dead allocation.
    Dead,
}

/// Metadata about an `AllocId`.
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct AllocInfo {
    pub size: Size,
    pub align: Align,
    pub kind: AllocKind,
    pub mutbl: Mutability,
}

impl AllocInfo {
    fn new(size: Size, align: Align, kind: AllocKind, mutbl: Mutability) -> Self {
        Self { size, align, kind, mutbl }
    }
}

/// The value of a function pointer.
#[derive(Debug, Copy, Clone)]
pub enum FnVal<'tcx, Other> {
    Instance(Instance<'tcx>),
    Other(Other),
}

impl<'tcx, Other> FnVal<'tcx, Other> {
    pub fn as_instance(self) -> InterpResult<'tcx, Instance<'tcx>> {
        match self {
            FnVal::Instance(instance) => interp_ok(instance),
            FnVal::Other(_) => {
                throw_unsup_format!("'foreign' function pointers are not supported in this context")
            }
        }
    }
}

// `Memory` has to depend on the `Machine` because some of its operations
// (e.g., `get`) call a `Machine` hook.
pub struct Memory<'tcx, M: Machine<'tcx>> {
    /// Allocations local to this instance of the interpreter. The kind
    /// helps ensure that the same mechanism is used for allocation and
    /// deallocation. When an allocation is not found here, it is a
    /// global and looked up in the `tcx` for read access. Some machines may
    /// have to mutate this map even on a read-only access to a global (because
    /// they do pointer provenance tracking and the allocations in `tcx` have
    /// the wrong type), so we let the machine override this type.
    /// Either way, if the machine allows writing to a global, doing so will
    /// create a copy of the global allocation here.
    // FIXME: this should not be public, but interning currently needs access to it
    pub(super) alloc_map: M::MemoryMap,

    /// Map for "extra" function pointers.
    extra_fn_ptr_map: FxIndexMap<AllocId, M::ExtraFnVal>,

    /// Map storing variable argument lists.
    va_list_map: FxIndexMap<AllocId, VecDeque<MPlaceTy<'tcx, M::Provenance>>>,

    /// To be able to compare pointers with null, and to check alignment for accesses
    /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
    /// that do not exist any more.
    // FIXME: this should not be public, but interning currently needs access to it
    pub(super) dead_alloc_map: FxIndexMap<AllocId, (Size, Align)>,

    /// This stores whether we are currently doing reads/writes that aren't "real".
    /// Those accesses do not trigger the machine's hooks.
    /// Needless to say, this must only be set with great care!
    ghost_mode: Cell<bool>,
}

/// A reference to some allocation that was already bounds-checked for the given region
/// and had the on-access machine hooks run.
#[derive(Copy, Clone)]
pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
    alloc: &'a Allocation<Prov, Extra, Bytes>,
    range: AllocRange,
    tcx: TyCtxt<'tcx>,
    alloc_id: AllocId,
}
/// A reference to some allocation that was already bounds-checked for the given region
/// and had the on-access machine hooks run.
pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
    alloc: &'a mut Allocation<Prov, Extra, Bytes>,
    range: AllocRange,
    tcx: TyCtxt<'tcx>,
    alloc_id: AllocId,
}

impl<'tcx, M: Machine<'tcx>> Memory<'tcx, M> {
    pub fn new() -> Self {
        Memory {
            alloc_map: M::MemoryMap::default(),
            extra_fn_ptr_map: FxIndexMap::default(),
            va_list_map: FxIndexMap::default(),
            dead_alloc_map: FxIndexMap::default(),
            ghost_mode: Cell::new(false),
        }
    }

    /// This is used by [priroda](https://github.com/oli-obk/priroda)
    pub fn alloc_map(&self) -> &M::MemoryMap {
        &self.alloc_map
    }
}

impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// Call this to turn untagged "global" pointers (obtained via `tcx`) into
    /// the machine pointer to the allocation. Must never be used
    /// for any other pointers, nor for TLS statics.
    ///
    /// Using the resulting pointer represents a *direct* access to that memory
    /// (e.g. by directly using a `static`),
    /// as opposed to access through a pointer that was created by the program.
    ///
    /// This function can fail only if `ptr` points to an `extern static`.
    #[inline]
    pub fn global_root_pointer(
        &self,
        ptr: Pointer<CtfeProvenance>,
    ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
        let alloc_id = ptr.provenance.alloc_id();
        // We need to handle `extern static`.
        match self.tcx.try_get_global_alloc(alloc_id) {
            Some(GlobalAlloc::Static(def_id)) if self.tcx.is_thread_local_static(def_id) => {
                // Thread-local statics do not have a constant address. They *must* be accessed via
                // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
                bug!("global memory cannot point to thread-local static")
            }
            Some(GlobalAlloc::Static(def_id)) if self.tcx.is_foreign_item(def_id) => {
                return M::extern_static_pointer(self, def_id);
            }
            None => {
                let is_fn_ptr = self.memory.extra_fn_ptr_map.contains_key(&alloc_id);
                let is_va_list = self.memory.va_list_map.contains_key(&alloc_id);
                assert!(
                    is_fn_ptr || is_va_list,
                    "{alloc_id:?} is neither global, va_list nor a function pointer"
                );
            }
            _ => {}
        }
        // And we need to get the provenance.
        M::adjust_alloc_root_pointer(self, ptr, M::GLOBAL_KIND.map(MemoryKind::Machine))
    }

    pub fn fn_ptr(&mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>) -> Pointer<M::Provenance> {
        let id = match fn_val {
            FnVal::Instance(instance) => {
                let salt = M::get_global_alloc_salt(self, Some(instance));
                self.tcx.reserve_and_set_fn_alloc(instance, salt)
            }
            FnVal::Other(extra) => {
                // FIXME(RalfJung): Should we have a cache here?
                let id = self.tcx.reserve_alloc_id();
                let old = self.memory.extra_fn_ptr_map.insert(id, extra);
                assert!(old.is_none());
                id
            }
        };
        // Functions are global allocations, so make sure we get the right root pointer.
        // We know this is not an `extern static` so this cannot fail.
        self.global_root_pointer(Pointer::from(id)).unwrap()
    }

    /// Insert a new variable argument list in the global map of variable argument lists.
    pub fn va_list_ptr(
        &mut self,
        varargs: VecDeque<MPlaceTy<'tcx, M::Provenance>>,
    ) -> Pointer<M::Provenance> {
        let id = self.tcx.reserve_alloc_id();
        let old = self.memory.va_list_map.insert(id, varargs);
        assert!(old.is_none());
        // Variable argument lists are global allocations, so make sure we get the right root
        // pointer. We know this is not an `extern static` so this cannot fail.
        self.global_root_pointer(Pointer::from(id)).unwrap()
    }

    pub fn allocate_ptr(
        &mut self,
        size: Size,
        align: Align,
        kind: MemoryKind<M::MemoryKind>,
        init: AllocInit,
    ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
        let params = self.machine.get_default_alloc_params();
        let alloc = if M::PANIC_ON_ALLOC_FAIL {
            Allocation::new(size, align, init, params)
        } else {
            Allocation::try_new(size, align, init, params)?
        };
        self.insert_allocation(alloc, kind)
    }

    pub fn allocate_bytes_ptr(
        &mut self,
        bytes: &[u8],
        align: Align,
        kind: MemoryKind<M::MemoryKind>,
        mutability: Mutability,
    ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
        let params = self.machine.get_default_alloc_params();
        let alloc = Allocation::from_bytes(bytes, align, mutability, params);
        self.insert_allocation(alloc, kind)
    }

    pub fn insert_allocation(
        &mut self,
        alloc: Allocation<M::Provenance, (), M::Bytes>,
        kind: MemoryKind<M::MemoryKind>,
    ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
        assert!(alloc.size() <= self.max_size_of_val());
        let id = self.tcx.reserve_alloc_id();
        debug_assert_ne!(
            Some(kind),
            M::GLOBAL_KIND.map(MemoryKind::Machine),
            "dynamically allocating global memory"
        );
        // This cannot be merged with the `adjust_global_allocation` code path
        // since here we have an allocation that already uses `M::Bytes`.
        let extra = M::init_local_allocation(self, id, kind, alloc.size(), alloc.align)?;
        let alloc = alloc.with_extra(extra);
        self.memory.alloc_map.insert(id, (kind, alloc));
        M::adjust_alloc_root_pointer(self, Pointer::from(id), Some(kind))
    }

    /// If this grows the allocation, `init_growth` determines
    /// whether the additional space will be initialized.
    pub fn reallocate_ptr(
        &mut self,
        ptr: Pointer<Option<M::Provenance>>,
        old_size_and_align: Option<(Size, Align)>,
        new_size: Size,
        new_align: Align,
        kind: MemoryKind<M::MemoryKind>,
        init_growth: AllocInit,
    ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
        let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
        if offset.bytes() != 0 {
            throw_ub_format!(
                "reallocating {ptr} which does not point to the beginning of an object"
            );
        }

        // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
        // This happens so rarely, the perf advantage is outweighed by the maintenance cost.
        // If requested, we zero-init the entire allocation, to ensure that a growing
        // allocation has its new bytes properly set. For the part that is copied,
        // `mem_copy` below will de-initialize things as necessary.
        let new_ptr = self.allocate_ptr(new_size, new_align, kind, init_growth)?;
        let old_size = match old_size_and_align {
            Some((size, _align)) => size,
            None => self.get_alloc_raw(alloc_id)?.size(),
        };
        // This will also call the access hooks.
        self.mem_copy(ptr, new_ptr.into(), old_size.min(new_size), /*nonoverlapping*/ true)?;
        self.deallocate_ptr(ptr, old_size_and_align, kind)?;

        interp_ok(new_ptr)
    }

    /// Mark the `const_allocate`d allocation `ptr` points to as immutable so we can intern it.
    pub fn make_const_heap_ptr_global(
        &mut self,
        ptr: Pointer<Option<CtfeProvenance>>,
    ) -> InterpResult<'tcx>
    where
        M: Machine<'tcx, MemoryKind = crate::const_eval::MemoryKind, Provenance = CtfeProvenance>,
    {
        let (alloc_id, offset, _) = self.ptr_get_alloc_id(ptr, 0)?;
        if offset.bytes() != 0 {
            return Err(ConstEvalErrKind::ConstMakeGlobalWithOffset(ptr)).into();
        }

        if self.tcx.try_get_global_alloc(alloc_id).is_some() {
            // This points to something outside the current interpreter.
            return Err(ConstEvalErrKind::ConstMakeGlobalPtrIsNonHeap(ptr)).into();
        }

        // If we can't find it in `alloc_map` it must be dangling (because we don't use
        // `extra_fn_ptr_map` in const-eval).
        let (kind, alloc) = self
            .memory
            .alloc_map
            .get_mut_or(alloc_id, || Err(ConstEvalErrKind::ConstMakeGlobalWithDanglingPtr(ptr)))?;

        // Ensure this is actually a *heap* allocation, and record it as made-global.
        match kind {
            MemoryKind::Stack | MemoryKind::CallerLocation => {
                return Err(ConstEvalErrKind::ConstMakeGlobalPtrIsNonHeap(ptr)).into();
            }
            MemoryKind::Machine(crate::const_eval::MemoryKind::Heap { was_made_global }) => {
                if *was_made_global {
                    return Err(ConstEvalErrKind::ConstMakeGlobalPtrAlreadyMadeGlobal(alloc_id))
                        .into();
                }
                *was_made_global = true;
            }
        }

        // Prevent further mutation, this is now an immutable global.
        alloc.mutability = Mutability::Not;

        interp_ok(())
    }

    #[instrument(skip(self), level = "debug")]
    pub fn deallocate_ptr(
        &mut self,
        ptr: Pointer<Option<M::Provenance>>,
        old_size_and_align: Option<(Size, Align)>,
        kind: MemoryKind<M::MemoryKind>,
    ) -> InterpResult<'tcx> {
        let (alloc_id, offset, prov) = self.ptr_get_alloc_id(ptr, 0)?;
        trace!("deallocating: {alloc_id}");

        if offset.bytes() != 0 {
            throw_ub_format!(
                "deallocating {ptr} which does not point to the beginning of an object"
            );
        }

        let Some((alloc_kind, mut alloc)) = self.memory.alloc_map.remove(&alloc_id) else {
            // Deallocating global memory -- always an error
            return Err(match self.tcx.try_get_global_alloc(alloc_id) {
                Some(GlobalAlloc::Function { .. }) => {
                    err_ub_format!("deallocating {alloc_id}, which is a function")
                }
                Some(GlobalAlloc::VTable(..)) => {
                    err_ub_format!("deallocating {alloc_id}, which is a vtable")
                }
                Some(GlobalAlloc::TypeId { .. }) => {
                    err_ub_format!("deallocating {alloc_id}, which is a type id")
                }
                Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
                    err_ub_format!("deallocating {alloc_id}, which is static memory")
                }
                None => err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccess)),
            })
            .into();
        };

        if alloc.mutability.is_not() {
            throw_ub_format!("deallocating immutable allocation {alloc_id}");
        }
        if alloc_kind != kind {
            throw_ub_format!(
                "deallocating {alloc_id}, which is {alloc_kind} memory, using {kind} deallocation operation",
            );
        }
        if let Some((size, align)) = old_size_and_align {
            if size != alloc.size() || align != alloc.align {
                throw_ub_format!(
                    "incorrect layout on deallocation: {alloc_id} has size {size} and alignment {align}, but gave size {size_found} and alignment {align_found}",
                    size = alloc.size().bytes(),
                    align = alloc.align.bytes(),
                    size_found = size.bytes(),
                    align_found = align.bytes(),
                )
            }
        }

        // Let the machine take some extra action
        let size = alloc.size();
        M::before_memory_deallocation(
            self.tcx,
            &mut self.machine,
            &mut alloc.extra,
            ptr,
            (alloc_id, prov),
            size,
            alloc.align,
            kind,
        )?;

        // Don't forget to remember size and align of this now-dead allocation
        let old = self.memory.dead_alloc_map.insert(alloc_id, (size, alloc.align));
        if old.is_some() {
            bug!("Nothing can be deallocated twice");
        }

        interp_ok(())
    }

    /// Internal helper function to determine the allocation and offset of a pointer (if any).
    #[inline(always)]
    fn get_ptr_access(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        size: Size,
    ) -> InterpResult<'tcx, Option<(AllocId, Size, M::ProvenanceExtra)>> {
        let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
        Self::check_and_deref_ptr(
            self,
            ptr,
            size,
            CheckInAllocMsg::MemoryAccess,
            |this, alloc_id, offset, prov| {
                let (size, align) =
                    this.get_live_alloc_size_and_align(alloc_id, CheckInAllocMsg::MemoryAccess)?;
                interp_ok((size, align, (alloc_id, offset, prov)))
            },
        )
    }

    /// Check if the given pointer points to live memory of the given `size`.
    /// The caller can control the error message for the out-of-bounds case.
    #[inline(always)]
    pub fn check_ptr_access(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        size: Size,
        msg: CheckInAllocMsg,
    ) -> InterpResult<'tcx> {
        let size = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
        Self::check_and_deref_ptr(self, ptr, size, msg, |this, alloc_id, _, _| {
            let (size, align) = this.get_live_alloc_size_and_align(alloc_id, msg)?;
            interp_ok((size, align, ()))
        })?;
        interp_ok(())
    }

    /// Check whether the given pointer points to live memory for a signed amount of bytes.
    /// A negative amounts means that the given range of memory to the left of the pointer
    /// needs to be dereferenceable.
    pub fn check_ptr_access_signed(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        size: i64,
        msg: CheckInAllocMsg,
    ) -> InterpResult<'tcx> {
        Self::check_and_deref_ptr(self, ptr, size, msg, |this, alloc_id, _, _| {
            let (size, align) = this.get_live_alloc_size_and_align(alloc_id, msg)?;
            interp_ok((size, align, ()))
        })?;
        interp_ok(())
    }

    /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference
    /// to the allocation it points to. Supports both shared and mutable references, as the actual
    /// checking is offloaded to a helper closure. Supports signed sizes for checks "to the left" of
    /// a pointer.
    ///
    /// `alloc_size` will only get called for non-zero-sized accesses.
    ///
    /// Returns `None` if and only if the size is 0.
    fn check_and_deref_ptr<T, R: Borrow<Self>>(
        this: R,
        ptr: Pointer<Option<M::Provenance>>,
        size: i64,
        msg: CheckInAllocMsg,
        alloc_size: impl FnOnce(
            R,
            AllocId,
            Size,
            M::ProvenanceExtra,
        ) -> InterpResult<'tcx, (Size, Align, T)>,
    ) -> InterpResult<'tcx, Option<T>> {
        // Everything is okay with size 0.
        if size == 0 {
            return interp_ok(None);
        }

        interp_ok(match this.borrow().ptr_try_get_alloc_id(ptr, size) {
            Err(addr) => {
                // We couldn't get a proper allocation.
                throw_ub!(DanglingIntPointer { addr, inbounds_size: size, msg });
            }
            Ok((alloc_id, offset, prov)) => {
                let tcx = this.borrow().tcx;
                let (alloc_size, _alloc_align, ret_val) = alloc_size(this, alloc_id, offset, prov)?;
                let offset = offset.bytes();
                // Compute absolute begin and end of the range.
                let (begin, end) = if size >= 0 {
                    (Some(offset), offset.checked_add(size as u64))
                } else {
                    (offset.checked_sub(size.unsigned_abs()), Some(offset))
                };
                // Ensure both are within bounds.
                let in_bounds = begin.is_some() && end.is_some_and(|e| e <= alloc_size.bytes());
                if !in_bounds {
                    throw_ub!(PointerOutOfBounds {
                        alloc_id,
                        alloc_size,
                        ptr_offset: tcx.sign_extend_to_target_isize(offset),
                        inbounds_size: size,
                        msg,
                    })
                }

                Some(ret_val)
            }
        })
    }

    pub(super) fn check_misalign(
        &self,
        misaligned: Option<Misalignment>,
        msg: CheckAlignMsg,
    ) -> InterpResult<'tcx> {
        if let Some(misaligned) = misaligned {
            throw_ub!(AlignmentCheckFailed(misaligned, msg))
        }
        interp_ok(())
    }

    pub(super) fn is_ptr_misaligned(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        align: Align,
    ) -> Option<Misalignment> {
        if !M::enforce_alignment(self) || align.bytes() == 1 {
            return None;
        }

        #[inline]
        fn is_offset_misaligned(offset: u64, align: Align) -> Option<Misalignment> {
            if offset.is_multiple_of(align.bytes()) {
                None
            } else {
                // The biggest power of two through which `offset` is divisible.
                let offset_pow2 = 1 << offset.trailing_zeros();
                Some(Misalignment { has: Align::from_bytes(offset_pow2).unwrap(), required: align })
            }
        }

        match self.ptr_try_get_alloc_id(ptr, 0) {
            Err(addr) => is_offset_misaligned(addr, align),
            Ok((alloc_id, offset, _prov)) => {
                let alloc_info = self.get_alloc_info(alloc_id);
                if let Some(misalign) = M::alignment_check(
                    self,
                    alloc_id,
                    alloc_info.align,
                    alloc_info.kind,
                    offset,
                    align,
                ) {
                    Some(misalign)
                } else if M::Provenance::OFFSET_IS_ADDR {
                    is_offset_misaligned(ptr.addr().bytes(), align)
                } else {
                    // Check allocation alignment and offset alignment.
                    if alloc_info.align.bytes() < align.bytes() {
                        Some(Misalignment { has: alloc_info.align, required: align })
                    } else {
                        is_offset_misaligned(offset.bytes(), align)
                    }
                }
            }
        }
    }

    /// Checks a pointer for misalignment.
    ///
    /// The error assumes this is checking the pointer used directly for an access.
    pub fn check_ptr_align(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        align: Align,
    ) -> InterpResult<'tcx> {
        self.check_misalign(self.is_ptr_misaligned(ptr, align), CheckAlignMsg::AccessedPtr)
    }
}

impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// This function is used by Miri's provenance GC to remove unreachable entries from the dead_alloc_map.
    pub fn remove_unreachable_allocs(&mut self, reachable_allocs: &FxHashSet<AllocId>) {
        // Unlike all the other GC helpers where we check if an `AllocId` is found in the interpreter or
        // is live, here all the IDs in the map are for dead allocations so we don't
        // need to check for liveness.
        self.memory.dead_alloc_map.retain(|id, _| reachable_allocs.contains(id));
    }
}

/// Allocation accessors
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// Helper function to obtain a global (tcx) allocation.
    /// This attempts to return a reference to an existing allocation if
    /// one can be found in `tcx`. That, however, is only possible if `tcx` and
    /// this machine use the same pointer provenance, so it is indirected through
    /// `M::adjust_allocation`.
    fn get_global_alloc(
        &self,
        id: AllocId,
        is_write: bool,
    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra, M::Bytes>>> {
        let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) {
            Some(GlobalAlloc::Memory(mem)) => {
                // Memory of a constant or promoted or anonymous memory referenced by a static.
                (mem, None)
            }
            Some(GlobalAlloc::Function { .. }) => throw_ub!(DerefFunctionPointer(id)),
            Some(GlobalAlloc::VTable(..)) => throw_ub!(DerefVTablePointer(id)),
            Some(GlobalAlloc::TypeId { .. }) => throw_ub!(DerefTypeIdPointer(id)),
            None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccess)),
            Some(GlobalAlloc::Static(def_id)) => {
                assert!(self.tcx.is_static(def_id));
                // Thread-local statics do not have a constant address. They *must* be accessed via
                // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value.
                assert!(!self.tcx.is_thread_local_static(def_id));
                // Notice that every static has two `AllocId` that will resolve to the same
                // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
                // and the other one is maps to `GlobalAlloc::Memory`, this is returned by
                // `eval_static_initializer` and it is the "resolved" ID.
                // The resolved ID is never used by the interpreted program, it is hidden.
                // This is relied upon for soundness of const-patterns; a pointer to the resolved
                // ID would "sidestep" the checks that make sure consts do not point to statics!
                // The `GlobalAlloc::Memory` branch here is still reachable though; when a static
                // contains a reference to memory that was created during its evaluation (i.e., not
                // to another static), those inner references only exist in "resolved" form.
                if self.tcx.is_foreign_item(def_id) {
                    // This is unreachable in Miri, but can happen in CTFE where we actually *do* support
                    // referencing arbitrary (declared) extern statics.
                    throw_unsup!(ExternStatic(def_id));
                }

                // We don't give a span -- statics don't need that, they cannot be generic or associated.
                let val = self.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
                (val, Some(def_id))
            }
        };
        M::before_access_global(self.tcx, &self.machine, id, alloc, def_id, is_write)?;
        // We got tcx memory. Let the machine initialize its "extra" stuff.
        M::adjust_global_allocation(
            self,
            id, // always use the ID we got as input, not the "hidden" one.
            alloc.inner(),
        )
    }

    /// Gives raw access to the `Allocation`, without bounds or alignment checks.
    /// The caller is responsible for calling the access hooks!
    ///
    /// You almost certainly want to use `get_ptr_alloc`/`get_ptr_alloc_mut` instead.
    pub fn get_alloc_raw(
        &self,
        id: AllocId,
    ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> {
        // The error type of the inner closure here is somewhat funny. We have two
        // ways of "erroring": An actual error, or because we got a reference from
        // `get_global_alloc` that we can actually use directly without inserting anything anywhere.
        // So the error type is `InterpResult<'tcx, &Allocation<M::Provenance>>`.
        let a = self.memory.alloc_map.get_or(id, || {
            // We have to funnel the `InterpErrorInfo` through a `Result` to match the `get_or` API,
            // so we use `report_err` for that.
            let alloc = self.get_global_alloc(id, /*is_write*/ false).report_err().map_err(Err)?;
            match alloc {
                Cow::Borrowed(alloc) => {
                    // We got a ref, cheaply return that as an "error" so that the
                    // map does not get mutated.
                    Err(Ok(alloc))
                }
                Cow::Owned(alloc) => {
                    // Need to put it into the map and return a ref to that
                    let kind = M::GLOBAL_KIND.expect(
                        "I got a global allocation that I have to copy but the machine does \
                            not expect that to happen",
                    );
                    Ok((MemoryKind::Machine(kind), alloc))
                }
            }
        });
        // Now unpack that funny error type
        match a {
            Ok(a) => interp_ok(&a.1),
            Err(a) => a.into(),
        }
    }

    /// Gives raw, immutable access to the `Allocation` address, without bounds or alignment checks.
    /// The caller is responsible for calling the access hooks!
    pub fn get_alloc_bytes_unchecked_raw(&self, id: AllocId) -> InterpResult<'tcx, *const u8> {
        let alloc = self.get_alloc_raw(id)?;
        interp_ok(alloc.get_bytes_unchecked_raw())
    }

    /// Bounds-checked *but not align-checked* allocation access.
    pub fn get_ptr_alloc<'a>(
        &'a self,
        ptr: Pointer<Option<M::Provenance>>,
        size: Size,
    ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
    {
        let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
        let ptr_and_alloc = Self::check_and_deref_ptr(
            self,
            ptr,
            size_i64,
            CheckInAllocMsg::MemoryAccess,
            |this, alloc_id, offset, prov| {
                let alloc = this.get_alloc_raw(alloc_id)?;
                interp_ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc)))
            },
        )?;
        // We want to call the hook on *all* accesses that involve an AllocId, including zero-sized
        // accesses. That means we cannot rely on the closure above or the `Some` branch below. We
        // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked.
        if !self.memory.ghost_mode.get() {
            if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) {
                M::before_alloc_access(self.tcx, &self.machine, alloc_id)?;
            }
        }

        if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
            let range = alloc_range(offset, size);
            if !self.memory.ghost_mode.get() {
                M::before_memory_read(
                    self.tcx,
                    &self.machine,
                    &alloc.extra,
                    ptr,
                    (alloc_id, prov),
                    range,
                )?;
            }
            interp_ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id }))
        } else {
            interp_ok(None)
        }
    }

    /// Return the `extra` field of the given allocation.
    pub fn get_alloc_extra<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, &'a M::AllocExtra> {
        interp_ok(&self.get_alloc_raw(id)?.extra)
    }

    /// Return the `mutability` field of the given allocation.
    pub fn get_alloc_mutability<'a>(&'a self, id: AllocId) -> InterpResult<'tcx, Mutability> {
        interp_ok(self.get_alloc_raw(id)?.mutability)
    }

    /// Gives raw mutable access to the `Allocation`, without bounds or alignment checks.
    /// The caller is responsible for calling the access hooks!
    ///
    /// Also returns a ptr to `self.extra` so that the caller can use it in parallel with the
    /// allocation.
    ///
    /// You almost certainly want to use `get_ptr_alloc`/`get_ptr_alloc_mut` instead.
    pub fn get_alloc_raw_mut(
        &mut self,
        id: AllocId,
    ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> {
        // We have "NLL problem case #3" here, which cannot be worked around without loss of
        // efficiency even for the common case where the key is in the map.
        // <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
        // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`, and that boils down to
        // Miri's `adjust_alloc_root_pointer` needing to look up the size of the allocation.
        // It could be avoided with a totally separate codepath in Miri for handling the absolute address
        // of global allocations, but that's not worth it.)
        if self.memory.alloc_map.get_mut(id).is_none() {
            // Slow path.
            // Allocation not found locally, go look global.
            let alloc = self.get_global_alloc(id, /*is_write*/ true)?;
            let kind = M::GLOBAL_KIND.expect(
                "I got a global allocation that I have to copy but the machine does \
                    not expect that to happen",
            );
            self.memory.alloc_map.insert(id, (MemoryKind::Machine(kind), alloc.into_owned()));
        }

        let (_kind, alloc) = self.memory.alloc_map.get_mut(id).unwrap();
        if alloc.mutability.is_not() {
            throw_ub!(WriteToReadOnly(id))
        }
        interp_ok((alloc, &mut self.machine))
    }

    /// Gives raw, mutable access to the `Allocation` address, without bounds or alignment checks.
    /// The caller is responsible for calling the access hooks!
    pub fn get_alloc_bytes_unchecked_raw_mut(
        &mut self,
        id: AllocId,
    ) -> InterpResult<'tcx, *mut u8> {
        let alloc = self.get_alloc_raw_mut(id)?.0;
        interp_ok(alloc.get_bytes_unchecked_raw_mut())
    }

    /// Bounds-checked *but not align-checked* allocation access.
    pub fn get_ptr_alloc_mut<'a>(
        &'a mut self,
        ptr: Pointer<Option<M::Provenance>>,
        size: Size,
    ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
    {
        let tcx = self.tcx;
        let validation_in_progress = self.memory.ghost_mode.get();

        let size_i64 = i64::try_from(size.bytes()).unwrap(); // it would be an error to even ask for more than isize::MAX bytes
        let ptr_and_alloc = Self::check_and_deref_ptr(
            self,
            ptr,
            size_i64,
            CheckInAllocMsg::MemoryAccess,
            |this, alloc_id, offset, prov| {
                let (alloc, machine) = this.get_alloc_raw_mut(alloc_id)?;
                interp_ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc, machine)))
            },
        )?;

        if let Some((alloc_id, offset, prov, alloc, machine)) = ptr_and_alloc {
            let range = alloc_range(offset, size);
            if !validation_in_progress {
                // For writes, it's okay to only call those when there actually is a non-zero
                // amount of bytes to be written: a zero-sized write doesn't manifest anything.
                M::before_alloc_access(tcx, machine, alloc_id)?;
                M::before_memory_write(
                    tcx,
                    machine,
                    &mut alloc.extra,
                    ptr,
                    (alloc_id, prov),
                    range,
                )?;
            }
            interp_ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id }))
        } else {
            interp_ok(None)
        }
    }

    /// Return the `extra` field of the given allocation.
    pub fn get_alloc_extra_mut<'a>(
        &'a mut self,
        id: AllocId,
    ) -> InterpResult<'tcx, (&'a mut M::AllocExtra, &'a mut M)> {
        let (alloc, machine) = self.get_alloc_raw_mut(id)?;
        interp_ok((&mut alloc.extra, machine))
    }

    /// Check whether an allocation is live. This is faster than calling
    /// [`InterpCx::get_alloc_info`] if all you need to check is whether the kind is
    /// [`AllocKind::Dead`] because it doesn't have to look up the type and layout of statics.
    pub fn is_alloc_live(&self, id: AllocId) -> bool {
        self.memory.alloc_map.contains_key_ref(&id)
            || self.memory.extra_fn_ptr_map.contains_key(&id)
            || self.memory.va_list_map.contains_key(&id)
            // We check `tcx` last as that has to acquire a lock in `many-seeds` mode.
            // This also matches the order in `get_alloc_info`.
            || self.tcx.try_get_global_alloc(id).is_some()
    }

    /// Obtain the size and alignment of an allocation, even if that allocation has
    /// been deallocated.
    pub fn get_alloc_info(&self, id: AllocId) -> AllocInfo {
        // # Regular allocations
        // Don't use `self.get_raw` here as that will
        // a) cause cycles in case `id` refers to a static
        // b) duplicate a global's allocation in miri
        if let Some((_, alloc)) = self.memory.alloc_map.get(id) {
            return AllocInfo::new(
                alloc.size(),
                alloc.align,
                AllocKind::LiveData,
                alloc.mutability,
            );
        }

        // # Function pointers
        // (both global from `alloc_map` and local from `extra_fn_ptr_map`)
        if let Some(fn_val) = self.get_fn_alloc(id) {
            let align = match fn_val {
                FnVal::Instance(_instance) => {
                    // FIXME: Until we have a clear design for the effects of align(N) functions
                    // on the address of function pointers, we don't consider the align(N)
                    // attribute on functions in the interpreter.
                    // See <https://github.com/rust-lang/rust/issues/144661> for more context.
                    Align::ONE
                }
                // Machine-specific extra functions currently do not support alignment restrictions.
                FnVal::Other(_) => Align::ONE,
            };

            return AllocInfo::new(Size::ZERO, align, AllocKind::Function, Mutability::Not);
        }

        // # Variable argument lists
        if self.memory.va_list_map.contains_key(&id) {
            return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::VaList, Mutability::Not);
        }

        // # Global allocations
        if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) {
            // NOTE: `static` alignment from attributes has already been applied to the allocation.
            let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
            let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
            let kind = match global_alloc {
                GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
                GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
                GlobalAlloc::VTable { .. } => AllocKind::VTable,
                GlobalAlloc::TypeId { .. } => AllocKind::TypeId,
            };
            return AllocInfo::new(size, align, kind, mutbl);
        }

        // # Dead pointers
        let (size, align) = *self
            .memory
            .dead_alloc_map
            .get(&id)
            .expect("deallocated pointers should all be recorded in `dead_alloc_map`");
        AllocInfo::new(size, align, AllocKind::Dead, Mutability::Not)
    }

    /// Obtain the size and alignment of a *live* allocation.
    fn get_live_alloc_size_and_align(
        &self,
        id: AllocId,
        msg: CheckInAllocMsg,
    ) -> InterpResult<'tcx, (Size, Align)> {
        let info = self.get_alloc_info(id);
        if info.kind == AllocKind::Dead {
            throw_ub!(PointerUseAfterFree(id, msg))
        }
        interp_ok((info.size, info.align))
    }

    fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
        if let Some(extra) = self.memory.extra_fn_ptr_map.get(&id) {
            Some(FnVal::Other(*extra))
        } else {
            match self.tcx.try_get_global_alloc(id) {
                Some(GlobalAlloc::Function { instance, .. }) => Some(FnVal::Instance(instance)),
                _ => None,
            }
        }
    }

    /// Takes a pointer that is the first chunk of a `TypeId` and return the type that its
    /// provenance refers to, as well as the segment of the hash that this pointer covers.
    pub fn get_ptr_type_id(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
    ) -> InterpResult<'tcx, (Ty<'tcx>, u64)> {
        let (alloc_id, offset, _meta) = self.ptr_get_alloc_id(ptr, 0)?;
        let Some(GlobalAlloc::TypeId { ty }) = self.tcx.try_get_global_alloc(alloc_id) else {
            throw_ub_format!("invalid `TypeId` value: not all bytes carry type id metadata")
        };
        interp_ok((ty, offset.bytes()))
    }

    pub fn get_ptr_fn(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
    ) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
        trace!("get_ptr_fn({:?})", ptr);
        let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
        if offset.bytes() != 0 {
            throw_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset)))
        }
        self.get_fn_alloc(alloc_id)
            .ok_or_else(|| err_ub!(InvalidFunctionPointer(Pointer::new(alloc_id, offset))))
            .into()
    }

    pub fn get_ptr_va_list(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
    ) -> InterpResult<'tcx, &VecDeque<MPlaceTy<'tcx, M::Provenance>>> {
        trace!("get_ptr_va_list({:?})", ptr);
        let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
        if offset.bytes() != 0 {
            throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
        }

        let Some(va_list) = self.memory.va_list_map.get(&alloc_id) else {
            throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
        };

        interp_ok(va_list)
    }

    /// Removes this VaList from the global map of variable argument lists. This does not deallocate
    /// the VaList elements, that happens when the Frame is popped.
    pub fn deallocate_va_list(
        &mut self,
        ptr: Pointer<Option<M::Provenance>>,
    ) -> InterpResult<'tcx, VecDeque<MPlaceTy<'tcx, M::Provenance>>> {
        trace!("deallocate_va_list({:?})", ptr);
        let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr, 0)?;
        if offset.bytes() != 0 {
            throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
        }

        let Some(va_list) = self.memory.va_list_map.swap_remove(&alloc_id) else {
            throw_ub!(InvalidVaListPointer(Pointer::new(alloc_id, offset)))
        };

        self.memory.dead_alloc_map.insert(alloc_id, (Size::ZERO, Align::ONE));
        interp_ok(va_list)
    }

    /// Get the dynamic type of the given vtable pointer.
    /// If `expected_trait` is `Some`, it must be a vtable for the given trait.
    pub fn get_ptr_vtable_ty(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        expected_trait: Option<&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>>,
    ) -> InterpResult<'tcx, Ty<'tcx>> {
        trace!("get_ptr_vtable({:?})", ptr);
        let (alloc_id, offset, _tag) = self.ptr_get_alloc_id(ptr, 0).map_err_kind(|err| {
            let err_ub!(DanglingIntPointer { addr, .. }) = err else { bug!() };
            err_ub!(InvalidVTablePointer(Pointer::without_provenance(addr)))
        })?;
        if offset.bytes() != 0 {
            throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset).into()))
        }
        let Some(GlobalAlloc::VTable(ty, vtable_dyn_type)) =
            self.tcx.try_get_global_alloc(alloc_id)
        else {
            throw_ub!(InvalidVTablePointer(Pointer::new(alloc_id, offset).into()))
        };
        if let Some(expected_dyn_type) = expected_trait {
            self.check_vtable_for_type(vtable_dyn_type, expected_dyn_type)?;
        }
        interp_ok(ty)
    }

    pub fn alloc_mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> {
        self.get_alloc_raw_mut(id)?.0.mutability = Mutability::Not;
        interp_ok(())
    }

    /// Visit all allocations reachable from the given start set, by recursively traversing the
    /// provenance information of those allocations.
    pub fn visit_reachable_allocs(
        &mut self,
        start: Vec<AllocId>,
        mut visit: impl FnMut(&mut Self, AllocId, &AllocInfo) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let mut done = FxHashSet::default();
        let mut todo = start;
        while let Some(id) = todo.pop() {
            if !done.insert(id) {
                // We already saw this allocation before, don't process it again.
                continue;
            }
            let info = self.get_alloc_info(id);

            // Recurse, if there is data here.
            // Do this *before* invoking the callback, as the callback might mutate the
            // allocation and e.g. replace all provenance by wildcards!
            if info.kind == AllocKind::LiveData {
                let alloc = self.get_alloc_raw(id)?;
                for prov in alloc.provenance().provenances() {
                    if let Some(id) = prov.get_alloc_id() {
                        todo.push(id);
                    }
                }
            }

            // Call the callback.
            visit(self, id, &info)?;
        }
        interp_ok(())
    }

    /// Create a lazy debug printer that prints the given allocation and all allocations it points
    /// to, recursively.
    #[must_use]
    pub fn dump_alloc<'a>(&'a self, id: AllocId) -> DumpAllocs<'a, 'tcx, M> {
        self.dump_allocs(vec![id])
    }

    /// Create a lazy debug printer for a list of allocations and all allocations they point to,
    /// recursively.
    #[must_use]
    pub fn dump_allocs<'a>(&'a self, mut allocs: Vec<AllocId>) -> DumpAllocs<'a, 'tcx, M> {
        allocs.sort();
        allocs.dedup();
        DumpAllocs { ecx: self, allocs }
    }

    /// Print the allocation's bytes, without any nested allocations.
    pub fn print_alloc_bytes_for_diagnostics(&self, id: AllocId) -> String {
        // Using the "raw" access to avoid the `before_alloc_read` hook, we specifically
        // want to be able to read all memory for diagnostics, even if that is cyclic.
        let alloc = self.get_alloc_raw(id).unwrap();
        let mut bytes = String::new();
        if alloc.size() != Size::ZERO {
            bytes = "\n".into();
            // FIXME(translation) there might be pieces that are translatable.
            rustc_middle::mir::pretty::write_allocation_bytes(*self.tcx, alloc, &mut bytes, "    ")
                .unwrap();
        }
        bytes
    }

    /// Find leaked allocations, remove them from memory and return them. Allocations reachable from
    /// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose
    /// kind's `may_leak()` returns true.
    ///
    /// This is highly destructive, no more execution can happen after this!
    pub fn take_leaked_allocations(
        &mut self,
        static_roots: impl FnOnce(&Self) -> &[AllocId],
    ) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)>
    {
        // Collect the set of allocations that are *reachable* from `Global` allocations.
        let reachable = {
            let mut reachable = FxHashSet::default();
            let global_kind = M::GLOBAL_KIND.map(MemoryKind::Machine);
            let mut todo: Vec<_> =
                self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
                    if Some(kind) == global_kind { Some(id) } else { None }
                });
            todo.extend(static_roots(self));
            while let Some(id) = todo.pop() {
                if reachable.insert(id) {
                    // This is a new allocation, add the allocations it points to `todo`.
                    // We only need to care about `alloc_map` memory here, as entirely unchanged
                    // global memory cannot point to memory relevant for the leak check.
                    if let Some((_, alloc)) = self.memory.alloc_map.get(id) {
                        todo.extend(
                            alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id()),
                        );
                    }
                }
            }
            reachable
        };

        // All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
        let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| {
            if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
        });
        let mut result = Vec::new();
        for &id in leaked.iter() {
            let (kind, alloc) = self.memory.alloc_map.remove(&id).unwrap();
            result.push((id, kind, alloc));
        }
        result
    }

    /// Runs the closure in "ghost" mode, which means the machine's memory read hooks will be
    /// suppressed. Needless to say, this must only be set with great care! Cannot be nested.
    ///
    /// We do this so Miri's allocation access tracking does not show the validation
    /// reads as spurious accesses as those aren't "real" reads. Also useful for debuggers
    /// that want to just display the Miri machine state.
    pub fn ghost_run_mut<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
        // This deliberately uses `==` on `bool` to follow the pattern
        // `assert!(val.replace(new) == old)`.
        assert!(self.memory.ghost_mode.replace(true) == false, "`ghost_mode` was already set");
        let res = f(self);
        assert!(
            self.memory.ghost_mode.replace(false) == true,
            "`ghost_mode` was unset by someone else"
        );
        res
    }

    /// Runs the closure in "ghost" mode, which means the machine's memory read hooks will be
    /// suppressed. Needless to say, this must only be set with great care! Cannot be nested.
    ///
    /// We do this so Miri's allocation access tracking does not show the validation
    /// reads as spurious accesses as those aren't "real" reads. Also useful for debuggers
    /// that want to just display the Miri machine state.
    pub fn ghost_run<R>(&self, f: impl FnOnce(&Self) -> R) -> R {
        // This deliberately uses `==` on `bool` to follow the pattern
        // `assert!(val.replace(new) == old)`.
        assert!(self.memory.ghost_mode.replace(true) == false, "`ghost_mode` was already set");
        let res = f(self);
        assert!(
            self.memory.ghost_mode.replace(false) == true,
            "`ghost_mode` was unset by someone else"
        );
        res
    }

    pub(super) fn validation_in_progress(&self) -> bool {
        self.memory.ghost_mode.get()
    }
}

#[doc(hidden)]
/// There's no way to use this directly, it's just a helper struct for the `dump_alloc(s)` methods.
pub struct DumpAllocs<'a, 'tcx, M: Machine<'tcx>> {
    ecx: &'a InterpCx<'tcx, M>,
    allocs: Vec<AllocId>,
}

impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // Cannot be a closure because it is generic in `Prov`, `Extra`.
        fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
            fmt: &mut std::fmt::Formatter<'_>,
            tcx: TyCtxt<'tcx>,
            allocs_to_print: &mut VecDeque<AllocId>,
            alloc: &Allocation<Prov, Extra, Bytes>,
        ) -> std::fmt::Result {
            for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id())
            {
                allocs_to_print.push_back(alloc_id);
            }
            write!(fmt, "{}", display_allocation(tcx, alloc))
        }

        let mut allocs_to_print: VecDeque<_> = self.allocs.iter().copied().collect();
        // `allocs_printed` contains all allocations that we have already printed.
        let mut allocs_printed = FxHashSet::default();

        while let Some(id) = allocs_to_print.pop_front() {
            if !allocs_printed.insert(id) {
                // Already printed, so skip this.
                continue;
            }

            write!(fmt, "{id:?}")?;
            match self.ecx.memory.alloc_map.get(id) {
                Some((kind, alloc)) => {
                    // normal alloc
                    write!(fmt, " ({kind}, ")?;
                    write_allocation_track_relocs(
                        &mut *fmt,
                        *self.ecx.tcx,
                        &mut allocs_to_print,
                        alloc,
                    )?;
                }
                None => {
                    // global alloc
                    match self.ecx.tcx.try_get_global_alloc(id) {
                        Some(GlobalAlloc::Memory(alloc)) => {
                            write!(fmt, " (unchanged global, ")?;
                            write_allocation_track_relocs(
                                &mut *fmt,
                                *self.ecx.tcx,
                                &mut allocs_to_print,
                                alloc.inner(),
                            )?;
                        }
                        Some(GlobalAlloc::Function { instance, .. }) => {
                            write!(fmt, " (fn: {instance})")?;
                        }
                        Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
                            write!(fmt, " (vtable: impl {dyn_ty} for {ty})")?;
                        }
                        Some(GlobalAlloc::TypeId { ty }) => {
                            write!(fmt, " (typeid for {ty})")?;
                        }
                        Some(GlobalAlloc::Static(did)) => {
                            write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?;
                        }
                        None => {
                            write!(fmt, " (deallocated)")?;
                        }
                    }
                }
            }
            writeln!(fmt)?;
        }
        Ok(())
    }
}

/// Reading and writing.
impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>
    AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
{
    pub fn as_ref<'b>(&'b self) -> AllocRef<'b, 'tcx, Prov, Extra, Bytes> {
        AllocRef { alloc: self.alloc, range: self.range, tcx: self.tcx, alloc_id: self.alloc_id }
    }

    /// `range` is relative to this allocation reference, not the base of the allocation.
    pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
        let range = self.range.subrange(range);
        debug!("write_scalar at {:?}{range:?}: {val:?}", self.alloc_id);

        self.alloc
            .write_scalar(&self.tcx, range, val)
            .map_err(|e| e.to_interp_error(self.alloc_id))
            .into()
    }

    /// `offset` is relative to this allocation reference, not the base of the allocation.
    pub fn write_ptr_sized(&mut self, offset: Size, val: Scalar<Prov>) -> InterpResult<'tcx> {
        self.write_scalar(alloc_range(offset, self.tcx.data_layout().pointer_size()), val)
    }

    /// Mark the given sub-range (relative to this allocation reference) as uninitialized.
    pub fn write_uninit(&mut self, range: AllocRange) {
        let range = self.range.subrange(range);

        self.alloc.write_uninit(&self.tcx, range);
    }

    /// Mark the entire referenced range as uninitialized
    pub fn write_uninit_full(&mut self) {
        self.alloc.write_uninit(&self.tcx, self.range);
    }

    /// Remove all provenance in the reference range.
    pub fn clear_provenance(&mut self) {
        self.alloc.clear_provenance(&self.tcx, self.range);
    }
}

impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
    /// `range` is relative to this allocation reference, not the base of the allocation.
    pub fn read_scalar(
        &self,
        range: AllocRange,
        read_provenance: bool,
    ) -> InterpResult<'tcx, Scalar<Prov>> {
        let range = self.range.subrange(range);
        self.alloc
            .read_scalar(&self.tcx, range, read_provenance)
            .map_err(|e| e.to_interp_error(self.alloc_id))
            .into()
    }

    /// `range` is relative to this allocation reference, not the base of the allocation.
    pub fn read_integer(&self, range: AllocRange) -> InterpResult<'tcx, Scalar<Prov>> {
        self.read_scalar(range, /*read_provenance*/ false)
    }

    /// `offset` is relative to this allocation reference, not the base of the allocation.
    pub fn read_pointer(&self, offset: Size) -> InterpResult<'tcx, Scalar<Prov>> {
        self.read_scalar(
            alloc_range(offset, self.tcx.data_layout().pointer_size()),
            /*read_provenance*/ true,
        )
    }

    /// `range` is relative to this allocation reference, not the base of the allocation.
    pub fn get_bytes_strip_provenance<'b>(&'b self) -> InterpResult<'tcx, &'a [u8]> {
        self.alloc
            .get_bytes_strip_provenance(&self.tcx, self.range)
            .map_err(|e| e.to_interp_error(self.alloc_id))
            .into()
    }

    /// Returns whether the allocation has provenance anywhere in the range of the `AllocRef`.
    pub fn has_provenance(&self) -> bool {
        !self.alloc.provenance().range_empty(self.range, &self.tcx)
    }
}

impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// Reads the given number of bytes from memory, and strips their provenance if possible.
    /// Returns them as a slice.
    ///
    /// Performs appropriate bounds checks.
    pub fn read_bytes_ptr_strip_provenance(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        size: Size,
    ) -> InterpResult<'tcx, &[u8]> {
        let Some(alloc_ref) = self.get_ptr_alloc(ptr, size)? else {
            // zero-sized access
            return interp_ok(&[]);
        };
        // Side-step AllocRef and directly access the underlying bytes more efficiently.
        // (We are staying inside the bounds here so all is good.)
        interp_ok(
            alloc_ref
                .alloc
                .get_bytes_strip_provenance(&alloc_ref.tcx, alloc_ref.range)
                .map_err(|e| e.to_interp_error(alloc_ref.alloc_id))?,
        )
    }

    /// Writes the given stream of bytes into memory.
    ///
    /// Performs appropriate bounds checks.
    pub fn write_bytes_ptr(
        &mut self,
        ptr: Pointer<Option<M::Provenance>>,
        src: impl IntoIterator<Item = u8>,
    ) -> InterpResult<'tcx> {
        let mut src = src.into_iter();
        let (lower, upper) = src.size_hint();
        let len = upper.expect("can only write bounded iterators");
        assert_eq!(lower, len, "can only write iterators with a precise length");

        let size = Size::from_bytes(len);
        let Some(alloc_ref) = self.get_ptr_alloc_mut(ptr, size)? else {
            // zero-sized access
            assert_matches!(src.next(), None, "iterator said it was empty but returned an element");
            return interp_ok(());
        };

        // Side-step AllocRef and directly access the underlying bytes more efficiently.
        // (We are staying inside the bounds here and all bytes do get overwritten so all is good.)
        let bytes =
            alloc_ref.alloc.get_bytes_unchecked_for_overwrite(&alloc_ref.tcx, alloc_ref.range);
        // `zip` would stop when the first iterator ends; we want to definitely
        // cover all of `bytes`.
        for dest in bytes {
            *dest = src.next().expect("iterator was shorter than it said it would be");
        }
        assert_matches!(src.next(), None, "iterator was longer than it said it would be");
        interp_ok(())
    }

    pub fn mem_copy(
        &mut self,
        src: Pointer<Option<M::Provenance>>,
        dest: Pointer<Option<M::Provenance>>,
        size: Size,
        nonoverlapping: bool,
    ) -> InterpResult<'tcx> {
        self.mem_copy_repeatedly(src, dest, size, 1, nonoverlapping)
    }

    /// Performs `num_copies` many copies of `size` many bytes from `src` to `dest + i*size` (where
    /// `i` is the index of the copy).
    ///
    /// Either `nonoverlapping` must be true or `num_copies` must be 1; doing repeated copies that
    /// may overlap is not supported.
    pub fn mem_copy_repeatedly(
        &mut self,
        src: Pointer<Option<M::Provenance>>,
        dest: Pointer<Option<M::Provenance>>,
        size: Size,
        num_copies: u64,
        nonoverlapping: bool,
    ) -> InterpResult<'tcx> {
        let tcx = self.tcx;
        // We need to do our own bounds-checks.
        let src_parts = self.get_ptr_access(src, size)?;
        let dest_parts = self.get_ptr_access(dest, size * num_copies)?; // `Size` multiplication

        // Similar to `get_ptr_alloc`, we need to call `before_alloc_access` even for zero-sized
        // reads. However, just like in `get_ptr_alloc_mut`, the write part is okay to skip for
        // zero-sized writes.
        if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(src, size.bytes().try_into().unwrap())
        {
            M::before_alloc_access(tcx, &self.machine, alloc_id)?;
        }

        // FIXME: we look up both allocations twice here, once before for the `check_ptr_access`
        // and once below to get the underlying `&[mut] Allocation`.

        // Source alloc preparations and access hooks.
        let Some((src_alloc_id, src_offset, src_prov)) = src_parts else {
            // Zero-sized *source*, that means dest is also zero-sized and we have nothing to do.
            return interp_ok(());
        };
        let src_alloc = self.get_alloc_raw(src_alloc_id)?;
        let src_range = alloc_range(src_offset, size);
        assert!(!self.memory.ghost_mode.get(), "we can't be copying during validation");

        // Trigger read hook.
        // For the overlapping case, it is crucial that we trigger the read hook
        // before the write hook -- the aliasing model cares about the order.
        M::before_memory_read(
            tcx,
            &self.machine,
            &src_alloc.extra,
            src,
            (src_alloc_id, src_prov),
            src_range,
        )?;
        // We need the `dest` ptr for the next operation, so we get it now.
        // We already did the source checks and called the hooks so we are good to return early.
        let Some((dest_alloc_id, dest_offset, dest_prov)) = dest_parts else {
            // Zero-sized *destination*.
            return interp_ok(());
        };

        // Prepare getting source provenance.
        let src_bytes = src_alloc.get_bytes_unchecked(src_range).as_ptr(); // raw ptr, so we can also get a ptr to the destination allocation
        // First copy the provenance to a temporary buffer, because
        // `get_bytes_unchecked_for_overwrite_ptr` will clear the provenance (in preparation for
        // inserting the new provenance), and that can overlap with the source range.
        let provenance = src_alloc.provenance_prepare_copy(src_range, self);
        // Prepare a copy of the initialization mask.
        let init = src_alloc.init_mask().prepare_copy(src_range);

        // Destination alloc preparations...
        let (dest_alloc, machine) = self.get_alloc_raw_mut(dest_alloc_id)?;
        let dest_range = alloc_range(dest_offset, size * num_copies);
        // ...and access hooks.
        M::before_alloc_access(tcx, machine, dest_alloc_id)?;
        M::before_memory_write(
            tcx,
            machine,
            &mut dest_alloc.extra,
            dest,
            (dest_alloc_id, dest_prov),
            dest_range,
        )?;
        // Yes we do overwrite all bytes in `dest_bytes`.
        let dest_bytes =
            dest_alloc.get_bytes_unchecked_for_overwrite_ptr(&tcx, dest_range).as_mut_ptr();

        if init.no_bytes_init() {
            // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range
            // is marked as uninitialized but we otherwise omit changing the byte representation which may
            // be arbitrary for uninitialized bytes.
            // This also avoids writing to the target bytes so that the backing allocation is never
            // touched if the bytes stay uninitialized for the whole interpreter execution. On contemporary
            // operating system this can avoid physically allocating the page.
            dest_alloc.write_uninit(&tcx, dest_range);
            // `write_uninit` also resets the provenance, so we are done.
            return interp_ok(());
        }

        // SAFE: The above indexing would have panicked if there weren't at least `size` bytes
        // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
        // `dest` could possibly overlap.
        // The pointers above remain valid even if the `HashMap` table is moved around because they
        // point into the `Vec` storing the bytes.
        unsafe {
            if src_alloc_id == dest_alloc_id {
                if nonoverlapping {
                    // `Size` additions
                    if (src_offset <= dest_offset && src_offset + size > dest_offset)
                        || (dest_offset <= src_offset && dest_offset + size > src_offset)
                    {
                        throw_ub_format!("`copy_nonoverlapping` called on overlapping ranges");
                    }
                }
            }
            if num_copies > 1 {
                assert!(nonoverlapping, "multi-copy only supported in non-overlapping mode");
            }

            let size_in_bytes = size.bytes_usize();
            // For particularly large arrays (where this is perf-sensitive) it's common that
            // we're writing a single byte repeatedly. So, optimize that case to a memset.
            if size_in_bytes == 1 {
                debug_assert!(num_copies >= 1); // we already handled the zero-sized cases above.
                // SAFETY: `src_bytes` would be read from anyway by `copy` below (num_copies >= 1).
                let value = *src_bytes;
                dest_bytes.write_bytes(value, (size * num_copies).bytes_usize());
            } else if src_alloc_id == dest_alloc_id {
                let mut dest_ptr = dest_bytes;
                for _ in 0..num_copies {
                    // Here we rely on `src` and `dest` being non-overlapping if there is more than
                    // one copy.
                    ptr::copy(src_bytes, dest_ptr, size_in_bytes);
                    dest_ptr = dest_ptr.add(size_in_bytes);
                }
            } else {
                let mut dest_ptr = dest_bytes;
                for _ in 0..num_copies {
                    ptr::copy_nonoverlapping(src_bytes, dest_ptr, size_in_bytes);
                    dest_ptr = dest_ptr.add(size_in_bytes);
                }
            }
        }

        // now fill in all the "init" data
        dest_alloc.init_mask_apply_copy(
            init,
            alloc_range(dest_offset, size), // just a single copy (i.e., not full `dest_range`)
            num_copies,
        );
        // copy the provenance to the destination
        dest_alloc.provenance_apply_copy(provenance, alloc_range(dest_offset, size), num_copies);

        interp_ok(())
    }
}

/// Machine pointer introspection.
impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// Test if this value might be null.
    /// If the machine does not support ptr-to-int casts, this is conservative.
    pub fn scalar_may_be_null(&self, scalar: Scalar<M::Provenance>) -> InterpResult<'tcx, bool> {
        match scalar.try_to_scalar_int() {
            Ok(int) => interp_ok(int.is_null()),
            Err(_) => {
                // We can't cast this pointer to an integer. Can only happen during CTFE.
                let ptr = scalar.to_pointer(self);
                match self.ptr_try_get_alloc_id(ptr, 0) {
                    Ok((alloc_id, offset, _)) => {
                        let info = self.get_alloc_info(alloc_id);
                        if info.kind == AllocKind::TypeId {
                            // We *could* actually precisely answer this question since here,
                            // the offset *is* the integer value. But the entire point of making
                            // this a pointer is not to leak the integer value, so we say everything
                            // might be null.
                            return interp_ok(true);
                        }
                        // If the pointer is in-bounds (including "at the end"), it is definitely not null.
                        if offset <= info.size {
                            return interp_ok(false);
                        }
                        // If the allocation is N-aligned, and the offset is not divisible by N,
                        // then `base + offset` has a non-zero remainder after division by `N`,
                        // which means `base + offset` cannot be null.
                        if !offset.bytes().is_multiple_of(info.align.bytes()) {
                            return interp_ok(false);
                        }
                        // We don't know enough, this might be null.
                        interp_ok(true)
                    }
                    Err(_offset) => bug!("a non-int scalar is always a pointer"),
                }
            }
        }
    }

    /// Turning a "maybe pointer" into a proper pointer (and some information
    /// about where it points), or an absolute address.
    ///
    /// `size` says how many bytes of memory are expected at that pointer. This is largely only used
    /// for error messages; however, the *sign* of `size` can be used to disambiguate situations
    /// where a wildcard pointer sits right in between two allocations.
    /// It is almost always okay to just set the size to 0; this will be treated like a positive size
    /// for handling wildcard pointers.
    ///
    /// The result must be used immediately; it is not allowed to convert
    /// the returned data back into a `Pointer` and store that in machine state.
    /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and
    /// we don't have an operation to turn it back into `M::Provenance`.)
    pub fn ptr_try_get_alloc_id(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        size: i64,
    ) -> Result<(AllocId, Size, M::ProvenanceExtra), u64> {
        match ptr.into_pointer_or_addr() {
            Ok(ptr) => match M::ptr_get_alloc(self, ptr, size) {
                Some((alloc_id, offset, extra)) => Ok((alloc_id, offset, extra)),
                None => {
                    assert!(M::Provenance::OFFSET_IS_ADDR);
                    // Offset is absolute, as we just asserted.
                    let (_, addr) = ptr.into_raw_parts();
                    Err(addr.bytes())
                }
            },
            Err(addr) => Err(addr.bytes()),
        }
    }

    /// Turning a "maybe pointer" into a proper pointer (and some information about where it points).
    ///
    /// `size` says how many bytes of memory are expected at that pointer. This is largely only used
    /// for error messages; however, the *sign* of `size` can be used to disambiguate situations
    /// where a wildcard pointer sits right in between two allocations.
    /// It is almost always okay to just set the size to 0; this will be treated like a positive size
    /// for handling wildcard pointers.
    ///
    /// The result must be used immediately; it is not allowed to convert
    /// the returned data back into a `Pointer` and store that in machine state.
    /// (In fact that's not even possible since `M::ProvenanceExtra` is generic and
    /// we don't have an operation to turn it back into `M::Provenance`.)
    #[inline(always)]
    pub fn ptr_get_alloc_id(
        &self,
        ptr: Pointer<Option<M::Provenance>>,
        size: i64,
    ) -> InterpResult<'tcx, (AllocId, Size, M::ProvenanceExtra)> {
        self.ptr_try_get_alloc_id(ptr, size)
            .map_err(|addr| {
                err_ub!(DanglingIntPointer {
                    addr,
                    inbounds_size: size,
                    msg: CheckInAllocMsg::Dereferenceable("pointer")
                })
            })
            .into()
    }
}
