//! Manages the low-level pushing and popping of stack frames and the (de)allocation of local variables.
//! For handling of argument passing and return values, see the `call` module.
use std::cell::Cell;
use std::{fmt, mem};

use either::{Either, Left, Right};
use rustc_hir as hir;
use rustc_hir::definitions::DefPathData;
use rustc_index::IndexVec;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, mir};
use rustc_mir_dataflow::impls::always_storage_live_locals;
use rustc_span::Span;
use rustc_target::callconv::ArgAbi;
use tracing::field::Empty;
use tracing::{info_span, instrument, trace};

use super::{
    AllocId, CtfeProvenance, FnArg, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace,
    MemPlaceMeta, MemoryKind, Operand, PlaceTy, Pointer, Provenance, ReturnAction, Scalar,
    from_known_layout, interp_ok, throw_ub, throw_unsup,
};
use crate::{diagnostics, enter_trace_span};

// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
// boundary and dropped in the other thread, it would exit the span in the other thread.
struct SpanGuard(tracing::Span, std::marker::PhantomData<*const u8>);

impl SpanGuard {
    /// By default a `SpanGuard` does nothing.
    fn new() -> Self {
        Self(tracing::Span::none(), std::marker::PhantomData)
    }

    /// If a span is entered, we exit the previous span (if any, normally none) and enter the
    /// new span. This is mainly so we don't have to use `Option` for the `tracing_span` field of
    /// `Frame` by creating a dummy span to being with and then entering it once the frame has
    /// been pushed.
    fn enter(&mut self, span: tracing::Span) {
        // This executes the destructor on the previous instance of `SpanGuard`, ensuring that
        // we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we
        // can't protect the tracing stack, but that'll just lead to weird logging, no actual
        // problems.
        *self = Self(span, std::marker::PhantomData);
        self.0.with_subscriber(|(id, dispatch)| {
            dispatch.enter(id);
        });
    }
}

impl Drop for SpanGuard {
    fn drop(&mut self) {
        self.0.with_subscriber(|(id, dispatch)| {
            dispatch.exit(id);
        });
    }
}

/// A stack frame.
pub struct Frame<'tcx, Prov: Provenance = CtfeProvenance, Extra = ()> {
    ////////////////////////////////////////////////////////////////////////////////
    // Function and callsite information
    ////////////////////////////////////////////////////////////////////////////////
    /// The MIR for the function called on this frame.
    pub(super) body: &'tcx mir::Body<'tcx>,

    /// The def_id and args of the current function.
    pub(super) instance: ty::Instance<'tcx>,

    /// Extra data for the machine.
    pub extra: Extra,

    ////////////////////////////////////////////////////////////////////////////////
    // Return place and locals
    ////////////////////////////////////////////////////////////////////////////////
    /// Where to continue when returning from this function.
    return_cont: ReturnContinuation,

    /// The location where the result of the current stack frame should be written to,
    /// and its layout in the caller. This place is to be interpreted relative to the
    /// *caller's* stack frame. We use a `PlaceTy` instead of an `MPlaceTy` since this
    /// avoids having to move *all* return places into Miri's memory.
    return_place: PlaceTy<'tcx, Prov>,

    /// The list of locals for this stack frame, stored in order as
    /// `[return_ptr, arguments..., variables..., temporaries...]`.
    /// The locals are stored as `Option<Value>`s.
    /// `None` represents a local that is currently dead, while a live local
    /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
    ///
    /// Do *not* access this directly; always go through the machine hook!
    pub locals: IndexVec<mir::Local, LocalState<'tcx, Prov>>,

    /// The complete variable argument list of this frame. Its elements must be dropped when the
    /// frame is popped.
    pub(super) va_list: Vec<MPlaceTy<'tcx, Prov>>,

    /// The span of the `tracing` crate is stored here.
    /// When the guard is dropped, the span is exited. This gives us
    /// a full stack trace on all tracing statements.
    tracing_span: SpanGuard,

    ////////////////////////////////////////////////////////////////////////////////
    // Current position within the function
    ////////////////////////////////////////////////////////////////////////////////
    /// If this is `Right`, we are not currently executing any particular statement in
    /// this frame (can happen e.g. during frame initialization, and during unwinding on
    /// frames without cleanup code).
    ///
    /// Needs to be public because ConstProp does unspeakable things to it.
    pub(super) loc: Either<mir::Location, Span>,
}

/// Where and how to continue when returning/unwinding from the current function.
#[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
pub enum ReturnContinuation {
    /// Jump to the next block in the caller, or cause UB if None (that's a function
    /// that may never return).
    /// `ret` stores the block we jump to on a normal return, while `unwind`
    /// stores the block used for cleanup during unwinding.
    Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction },
    /// The root frame of the stack: nowhere else to jump to, so we stop.
    /// `cleanup` says whether locals are deallocated. Static computation
    /// wants them leaked to intern what they need (and just throw away
    /// the entire `ecx` when it is done).
    Stop { cleanup: bool },
}

/// State of a local variable including a memoized layout
#[derive(Clone)]
pub struct LocalState<'tcx, Prov: Provenance = CtfeProvenance> {
    value: LocalValue<Prov>,
    /// Don't modify if `Some`, this is only used to prevent computing the layout twice.
    /// Avoids computing the layout of locals that are never actually initialized.
    layout: Cell<Option<TyAndLayout<'tcx>>>,
}

impl<Prov: Provenance> std::fmt::Debug for LocalState<'_, Prov> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("LocalState")
            .field("value", &self.value)
            .field("ty", &self.layout.get().map(|l| l.ty))
            .finish()
    }
}

/// Current value of a local variable
///
/// This does not store the type of the local; the type is given by `body.local_decls` and can never
/// change, so by not storing here we avoid having to maintain that as an invariant.
#[derive(Copy, Clone, Debug)] // Miri debug-prints these
pub(super) enum LocalValue<Prov: Provenance = CtfeProvenance> {
    /// This local is not currently alive, and cannot be used at all.
    Dead,
    /// A normal, live local.
    /// Mostly for convenience, we re-use the `Operand` type here.
    /// This is an optimization over just always having a pointer here;
    /// we can thus avoid doing an allocation when the local just stores
    /// immediate values *and* never has its address taken.
    Live(Operand<Prov>),
}

impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
    pub fn make_live_uninit(&mut self) {
        self.value = LocalValue::Live(Operand::Immediate(Immediate::Uninit));
    }

    /// This is a hack because Miri needs a way to visit all the provenance in a `LocalState`
    /// without having a layout or `TyCtxt` available, and we want to keep the `Operand` type
    /// private.
    pub fn as_mplace_or_imm(
        &self,
    ) -> Option<Either<(Pointer<Option<Prov>>, MemPlaceMeta<Prov>), Immediate<Prov>>> {
        match self.value {
            LocalValue::Dead => None,
            LocalValue::Live(Operand::Indirect(mplace)) => Some(Left((mplace.ptr, mplace.meta))),
            LocalValue::Live(Operand::Immediate(imm)) => Some(Right(imm)),
        }
    }

    /// Read the local's value or error if the local is not yet live or not live anymore.
    #[inline(always)]
    pub(super) fn access(&self) -> InterpResult<'tcx, &Operand<Prov>> {
        match &self.value {
            LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
            LocalValue::Live(val) => interp_ok(val),
        }
    }

    /// Overwrite the local. If the local can be overwritten in place, return a reference
    /// to do so; otherwise return the `MemPlace` to consult instead.
    #[inline(always)]
    pub(super) fn access_mut(&mut self) -> InterpResult<'tcx, &mut Operand<Prov>> {
        match &mut self.value {
            LocalValue::Dead => throw_ub!(DeadLocal), // could even be "invalid program"?
            LocalValue::Live(val) => interp_ok(val),
        }
    }
}

/// What we store about a frame in an interpreter backtrace.
#[derive(Clone, Debug)]
pub struct FrameInfo<'tcx> {
    pub instance: ty::Instance<'tcx>,
    pub span: Span,
}

// FIXME: only used by miri, should be removed once translatable.
impl<'tcx> fmt::Display for FrameInfo<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        ty::tls::with(|tcx| {
            if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
                write!(f, "inside closure")
            } else {
                // Note: this triggers a `must_produce_diag` state, which means that if we ever
                // get here we must emit a diagnostic. We should never display a `FrameInfo` unless
                // we actually want to emit a warning or error to the user.
                write!(f, "inside `{}`", self.instance)
            }
        })
    }
}

impl<'tcx> FrameInfo<'tcx> {
    pub(crate) fn as_note(&self, tcx: TyCtxt<'tcx>) -> diagnostics::FrameNote {
        let span = self.span;
        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
            diagnostics::FrameNote {
                where_: "closure",
                span,
                instance: String::new(),
                times: 0,
                has_label: false,
            }
        } else {
            let instance = format!("{}", self.instance);
            // Note: this triggers a `must_produce_diag` state, which means that if we ever get
            // here we must emit a diagnostic. We should never display a `FrameInfo` unless we
            // actually want to emit a warning or error to the user.
            diagnostics::FrameNote {
                where_: "instance",
                span,
                instance,
                times: 0,
                has_label: false,
            }
        }
    }
}

impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
    pub fn with_extra<Extra>(self, extra: Extra) -> Frame<'tcx, Prov, Extra> {
        Frame {
            body: self.body,
            instance: self.instance,
            return_cont: self.return_cont,
            return_place: self.return_place,
            locals: self.locals,
            va_list: self.va_list,
            loc: self.loc,
            extra,
            tracing_span: self.tracing_span,
        }
    }
}

impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
    /// Get the current location within the Frame.
    ///
    /// If this is `Right`, we are not currently executing any particular statement in
    /// this frame (can happen e.g. during frame initialization, and during unwinding on
    /// frames without cleanup code).
    ///
    /// Used by [priroda](https://github.com/oli-obk/priroda).
    pub fn current_loc(&self) -> Either<mir::Location, Span> {
        self.loc
    }

    pub fn body(&self) -> &'tcx mir::Body<'tcx> {
        self.body
    }

    pub fn instance(&self) -> ty::Instance<'tcx> {
        self.instance
    }

    pub fn return_place(&self) -> &PlaceTy<'tcx, Prov> {
        &self.return_place
    }

    pub fn return_cont(&self) -> ReturnContinuation {
        self.return_cont
    }

    /// Return the `SourceInfo` of the current instruction.
    pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
        self.loc.left().map(|loc| self.body.source_info(loc))
    }

    pub fn current_span(&self) -> Span {
        match self.loc {
            Left(loc) => self.body.source_info(loc).span,
            Right(span) => span,
        }
    }

    pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option<hir::HirId> {
        // We first try to get a HirId via the current source scope,
        // and fall back to `body.source`.
        self.current_source_info()
            .and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data {
                mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
                mir::ClearCrossCrate::Clear => None,
            })
            .or_else(|| {
                let def_id = self.body.source.def_id().as_local();
                def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
            })
    }

    /// Returns the address of the buffer where the locals are stored. This is used by `Place` as a
    /// sanity check to detect bugs where we mix up which stack frame a place refers to.
    #[inline(always)]
    pub(super) fn locals_addr(&self) -> usize {
        self.locals.raw.as_ptr().addr()
    }

    #[must_use]
    pub fn generate_stacktrace_from_stack(
        stack: &[Self],
        tcx: TyCtxt<'tcx>,
    ) -> Vec<FrameInfo<'tcx>> {
        let mut frames = Vec::new();
        // This deliberately does *not* honor `requires_caller_location` since it is used for much
        // more than just panics.
        for frame in stack.iter().rev() {
            let mut span = match frame.loc {
                Left(loc) => {
                    // If the stacktrace passes through MIR-inlined source scopes, add them.
                    let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc);
                    let mut scope_data = &frame.body.source_scopes[scope];
                    while let Some((instance, call_span)) = scope_data.inlined {
                        frames.push(FrameInfo { span, instance });
                        span = call_span;
                        scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()];
                    }
                    span
                }
                Right(span) => span,
            };
            if span.is_dummy() {
                // Some statements lack a proper span; point at the function instead.
                span = tcx.def_span(frame.instance.def_id());
            }
            frames.push(FrameInfo { span, instance: frame.instance });
        }
        trace!("generate stacktrace: {:#?}", frames);
        frames
    }
}

impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// Very low-level helper that pushes a stack frame without initializing
    /// the arguments or local variables.
    ///
    /// The high-level version of this is `init_stack_frame`.
    #[instrument(skip(self, body, return_place, return_cont), level = "debug")]
    pub(crate) fn push_stack_frame_raw(
        &mut self,
        instance: ty::Instance<'tcx>,
        body: &'tcx mir::Body<'tcx>,
        return_place: &PlaceTy<'tcx, M::Provenance>,
        return_cont: ReturnContinuation,
    ) -> InterpResult<'tcx> {
        trace!("body: {:#?}", body);

        // We can push a `Root` frame if and only if the stack is empty.
        debug_assert_eq!(
            self.stack().is_empty(),
            matches!(return_cont, ReturnContinuation::Stop { .. })
        );

        // First push a stack frame so we have access to `instantiate_from_current_frame` and other
        // `self.frame()`-based functions.
        let dead_local = LocalState { value: LocalValue::Dead, layout: Cell::new(None) };
        let locals = IndexVec::from_elem(dead_local, &body.local_decls);
        let pre_frame = Frame {
            body,
            loc: Right(self.tcx.def_span(body.source.def_id())), // Span used for errors caused during preamble.
            return_cont,
            return_place: return_place.clone(),
            locals,
            va_list: vec![],
            instance,
            tracing_span: SpanGuard::new(),
            extra: (),
        };
        let frame = M::init_frame(self, pre_frame)?;
        self.stack_mut().push(frame);

        // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
        for &const_ in body.required_consts() {
            // We can't use `eval_mir_constant` here as that assumes that all required consts have
            // already been checked, so we need a separate tracing call.
            let _trace = enter_trace_span!(M, const_eval::required_consts, ?const_.const_);
            let c =
                self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
            c.eval(*self.tcx, self.typing_env, const_.span).map_err(|err| {
                err.emit_note(*self.tcx);
                err
            })?;
        }

        // Finish things up.
        M::after_stack_push(self)?;
        // `tracing_separate_thread` is used to instruct the tracing_chrome [tracing::Layer] in Miri
        // to put the "frame" span on a separate trace thread/line than other spans, to make the
        // visualization in <https://ui.perfetto.dev> easier to interpret. It is set to a value of
        // [tracing::field::Empty] so that other tracing layers (e.g. the logger) will ignore it.
        let span = info_span!("frame", tracing_separate_thread = Empty, frame = %instance);
        self.frame_mut().tracing_span.enter(span);

        interp_ok(())
    }

    /// Low-level helper that pops a stack frame from the stack without any cleanup.
    /// This invokes `before_stack_pop`.
    /// After calling this function, you need to deal with the return value, and then
    /// invoke `cleanup_stack_frame`.
    pub(super) fn pop_stack_frame_raw(
        &mut self,
    ) -> InterpResult<'tcx, Frame<'tcx, M::Provenance, M::FrameExtra>> {
        M::before_stack_pop(self)?;
        let frame =
            self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
        interp_ok(frame)
    }

    /// Deallocate local variables in the stack frame, and invoke `after_stack_pop`.
    pub(super) fn cleanup_stack_frame(
        &mut self,
        unwinding: bool,
        frame: Frame<'tcx, M::Provenance, M::FrameExtra>,
    ) -> InterpResult<'tcx, ReturnAction> {
        let return_cont = frame.return_cont;

        // Cleanup: deallocate locals.
        // Usually we want to clean up (deallocate locals), but in a few rare cases we don't.
        // We do this while the frame is still on the stack, so errors point to the callee.
        let cleanup = match return_cont {
            ReturnContinuation::Goto { .. } => true,
            ReturnContinuation::Stop { cleanup, .. } => cleanup,
        };

        if cleanup {
            for local in &frame.locals {
                self.deallocate_local(local.value)?;
            }

            // Deallocate any c-variadic arguments.
            self.deallocate_varargs(&frame.va_list)?;

            // Call the machine hook, which determines the next steps.
            let return_action = M::after_stack_pop(self, frame, unwinding)?;
            assert_ne!(return_action, ReturnAction::NoCleanup);
            interp_ok(return_action)
        } else {
            // We also skip the machine hook when there's no cleanup. This not a real "pop" anyway.
            interp_ok(ReturnAction::NoCleanup)
        }
    }

    /// Call this after `push_stack_frame_raw` and when all the other setup that needs to be done
    /// is completed.
    pub(crate) fn push_stack_frame_done(&mut self) -> InterpResult<'tcx> {
        // Mark all locals as live that are not arguments and don't have `Storage*` annotations
        // (this includes the return place, but not the arguments).
        self.storage_live(mir::RETURN_PLACE)?;

        let body = self.body();
        let always_live = always_storage_live_locals(body);
        for local in body.vars_and_temps_iter() {
            if always_live.contains(local) {
                self.storage_live(local)?;
            }
        }

        // Get ready to execute the first instruction in the stack frame.
        self.frame_mut().loc = Left(mir::Location::START);

        interp_ok(())
    }

    pub fn storage_live_dyn(
        &mut self,
        local: mir::Local,
        meta: MemPlaceMeta<M::Provenance>,
    ) -> InterpResult<'tcx> {
        trace!("{:?} is now live", local);

        // We avoid `ty.is_trivially_sized` since that does something expensive for ADTs.
        fn is_very_trivially_sized(ty: Ty<'_>) -> bool {
            match ty.kind() {
                ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
                | ty::Uint(_)
                | ty::Int(_)
                | ty::Bool
                | ty::Float(_)
                | ty::FnDef(..)
                | ty::FnPtr(..)
                | ty::RawPtr(..)
                | ty::Char
                | ty::Ref(..)
                | ty::Coroutine(..)
                | ty::CoroutineWitness(..)
                | ty::Array(..)
                | ty::Closure(..)
                | ty::CoroutineClosure(..)
                | ty::Never
                | ty::Error(_) => true,

                ty::Str | ty::Slice(_) | ty::Dynamic(_, _) | ty::Foreign(..) => false,

                ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),

                ty::Pat(ty, ..) => is_very_trivially_sized(*ty),

                // We don't want to do any queries, so there is not much we can do with ADTs.
                ty::Adt(..) => false,

                ty::UnsafeBinder(ty) => is_very_trivially_sized(ty.skip_binder()),

                ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,

                ty::Infer(ty::TyVar(_)) => false,

                ty::Bound(..)
                | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                    bug!("`is_very_trivially_sized` applied to unexpected type: {}", ty)
                }
            }
        }

        // This is a hot function, we avoid computing the layout when possible.
        // `unsized_` will be `None` for sized types and `Some(layout)` for unsized types.
        let unsized_ = if is_very_trivially_sized(self.body().local_decls[local].ty) {
            None
        } else {
            // We need the layout.
            let layout = self.layout_of_local(self.frame(), local, None)?;
            if layout.is_sized() { None } else { Some(layout) }
        };

        let local_val = LocalValue::Live(if let Some(layout) = unsized_ {
            if !meta.has_meta() {
                throw_unsup!(UnsizedLocal);
            }
            // Need to allocate some memory, since `Immediate::Uninit` cannot be unsized.
            let dest_place = self.allocate_dyn(layout, MemoryKind::Stack, meta)?;
            Operand::Indirect(*dest_place.mplace())
        } else {
            // Just make this an efficient immediate.
            assert!(!meta.has_meta()); // we're dropping the metadata
            // Make sure the machine knows this "write" is happening. (This is important so that
            // races involving local variable allocation can be detected by Miri.)
            M::after_local_write(self, local, /*storage_live*/ true)?;
            // Note that not calling `layout_of` here does have one real consequence:
            // if the type is too big, we'll only notice this when the local is actually initialized,
            // which is a bit too late -- we should ideally notice this already here, when the memory
            // is conceptually allocated. But given how rare that error is and that this is a hot function,
            // we accept this downside for now.
            Operand::Immediate(Immediate::Uninit)
        });

        // If the local is already live, deallocate its old memory.
        let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
        self.deallocate_local(old)?;
        interp_ok(())
    }

    /// Mark a storage as live, killing the previous content.
    #[inline(always)]
    pub fn storage_live(&mut self, local: mir::Local) -> InterpResult<'tcx> {
        self.storage_live_dyn(local, MemPlaceMeta::None)
    }

    pub fn storage_dead(&mut self, local: mir::Local) -> InterpResult<'tcx> {
        assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
        trace!("{:?} is now dead", local);

        // If the local is already dead, this is a NOP.
        let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead);
        self.deallocate_local(old)?;
        interp_ok(())
    }

    fn deallocate_local(&mut self, local: LocalValue<M::Provenance>) -> InterpResult<'tcx> {
        if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
            // All locals have a backing allocation, even if the allocation is empty
            // due to the local having ZST type. Hence we can `unwrap`.
            trace!(
                "deallocating local {:?}: {:?}",
                local,
                // Locals always have a `alloc_id` (they are never the result of a int2ptr).
                self.dump_alloc(ptr.provenance.unwrap().get_alloc_id().unwrap())
            );
            self.deallocate_ptr(ptr, None, MemoryKind::Stack)?;
        };
        interp_ok(())
    }

    /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/)
    /// to analyze all the locals in a stack frame.
    #[inline(always)]
    pub fn layout_of_local(
        &self,
        frame: &Frame<'tcx, M::Provenance, M::FrameExtra>,
        local: mir::Local,
        layout: Option<TyAndLayout<'tcx>>,
    ) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
        let state = &frame.locals[local];
        if let Some(layout) = state.layout.get() {
            return interp_ok(layout);
        }

        let layout = from_known_layout(self.tcx, self.typing_env, layout, || {
            let local_ty = frame.body.local_decls[local].ty;
            let local_ty =
                self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
            self.layout_of(local_ty).into()
        })?;

        // Layouts of locals are requested a lot, so we cache them.
        state.layout.set(Some(layout));
        interp_ok(layout)
    }
}

impl<'a, 'tcx: 'a, M: Machine<'tcx>> InterpCx<'tcx, M> {
    /// Consume the arguments provided by the iterator and store them as a list
    /// of variadic arguments. Return a list of the places that hold those arguments.
    pub(crate) fn allocate_varargs<I, J>(
        &mut self,
        caller_args: I,
        mut callee_abis: J,
    ) -> InterpResult<'tcx, Vec<MPlaceTy<'tcx, M::Provenance>>>
    where
        I: Iterator<Item = (&'a FnArg<'tcx, M::Provenance>, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
        J: Iterator<Item = (usize, &'a ArgAbi<'tcx, Ty<'tcx>>)>,
    {
        // Consume the remaining arguments and store them in fresh allocations.
        let mut varargs = Vec::new();
        for (fn_arg, caller_abi) in caller_args {
            // The callee ABI is entirely computed based on which arguments the caller has
            // provided so it should not be possible to get a mismatch here.
            let (_idx, callee_abi) = callee_abis.next().unwrap();
            assert!(self.check_argument_compat(caller_abi, callee_abi)?);
            // FIXME: do we have to worry about in-place argument passing?
            let op = fn_arg.copy_fn_arg();
            let mplace = self.allocate(op.layout, MemoryKind::Stack)?;
            self.copy_op(&op, &mplace)?;

            varargs.push(mplace);
        }
        assert!(callee_abis.next().is_none());

        interp_ok(varargs)
    }

    /// Deallocate the variadic arguments in the list (that must have been created with `allocate_varargs`).
    fn deallocate_varargs(
        &mut self,
        varargs: &[MPlaceTy<'tcx, M::Provenance>],
    ) -> InterpResult<'tcx> {
        for vararg in varargs {
            let ptr = vararg.ptr();

            trace!(
                "deallocating vararg {:?}: {:?}",
                vararg,
                // Locals always have a `alloc_id` (they are never the result of a int2ptr).
                self.dump_alloc(ptr.provenance.unwrap().get_alloc_id().unwrap())
            );
            self.deallocate_ptr(ptr, None, MemoryKind::Stack)?;
        }

        interp_ok(())
    }
}

impl<'tcx, Prov: Provenance> LocalState<'tcx, Prov> {
    pub(super) fn print(
        &self,
        allocs: &mut Vec<Option<AllocId>>,
        fmt: &mut std::fmt::Formatter<'_>,
    ) -> std::fmt::Result {
        match self.value {
            LocalValue::Dead => write!(fmt, " is dead")?,
            LocalValue::Live(Operand::Immediate(Immediate::Uninit)) => {
                write!(fmt, " is uninitialized")?
            }
            LocalValue::Live(Operand::Indirect(mplace)) => {
                write!(
                    fmt,
                    " by {} ref {:?}:",
                    match mplace.meta {
                        MemPlaceMeta::Meta(meta) => format!(" meta({meta:?})"),
                        MemPlaceMeta::None => String::new(),
                    },
                    mplace.ptr,
                )?;
                allocs.extend(mplace.ptr.provenance.map(Provenance::get_alloc_id));
            }
            LocalValue::Live(Operand::Immediate(Immediate::Scalar(val))) => {
                write!(fmt, " {val:?}")?;
                if let Scalar::Ptr(ptr, _size) = val {
                    allocs.push(ptr.provenance.get_alloc_id());
                }
            }
            LocalValue::Live(Operand::Immediate(Immediate::ScalarPair(val1, val2))) => {
                write!(fmt, " ({val1:?}, {val2:?})")?;
                if let Scalar::Ptr(ptr, _size) = val1 {
                    allocs.push(ptr.provenance.get_alloc_id());
                }
                if let Scalar::Ptr(ptr, _size) = val2 {
                    allocs.push(ptr.provenance.get_alloc_id());
                }
            }
        }

        Ok(())
    }
}
