//! 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::{enter_trace_span, errors};

// 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 fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
        let span = self.span;
        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::Closure {
            errors::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.
            errors::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(body.span), // 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)?;
        self.frame_mut().loc = Left(mir::Location::START);
        // `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)
        }
    }

    /// In the current stack frame, mark all locals as live that are not arguments and don't have
    /// `Storage*` annotations (this includes the return place).
    pub(crate) fn storage_live_for_always_live_locals(&mut self) -> InterpResult<'tcx> {
        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)?;
            }
        }
        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(())
    }
}
