use std::collections::hash_map::Entry;
use std::marker::PhantomData;
use std::ops::Range;

use rustc_abi::{BackendRepr, FieldIdx, FieldsShape, Size, VariantIdx};
use rustc_data_structures::fx::FxHashMap;
use rustc_index::IndexVec;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::{Instance, Ty};
use rustc_middle::{bug, mir, ty};
use rustc_session::config::DebugInfo;
use rustc_span::{BytePos, Span, Symbol, hygiene, sym};

use super::operand::{OperandRef, OperandValue};
use super::place::{PlaceRef, PlaceValue};
use super::{FunctionCx, LocalRef, PerLocalVarDebugInfoIndexVec};
use crate::traits::*;

pub struct FunctionDebugContext<'tcx, S, L> {
    /// Maps from source code to the corresponding debug info scope.
    pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,

    /// Maps from an inlined function to its debug info declaration.
    pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>,
}

#[derive(Copy, Clone)]
pub enum VariableKind {
    ArgumentVariable(usize /*index*/),
    LocalVariable,
}

/// Like `mir::VarDebugInfo`, but within a `mir::Local`.
#[derive(Clone)]
pub struct PerLocalVarDebugInfo<'tcx, D> {
    pub name: Symbol,
    pub source_info: mir::SourceInfo,

    /// `DIVariable` returned by `create_dbg_var`.
    pub dbg_var: Option<D>,

    /// Byte range in the `dbg_var` covered by this fragment,
    /// if this is a fragment of a composite `VarDebugInfo`.
    pub fragment: Option<Range<Size>>,

    /// `.place.projection` from `mir::VarDebugInfo`.
    pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
}

/// Information needed to emit a constant.
pub struct ConstDebugInfo<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
    pub name: String,
    pub source_info: mir::SourceInfo,
    pub operand: OperandRef<'tcx, Bx::Value>,
    pub dbg_var: Bx::DIVariable,
    pub dbg_loc: Bx::DILocation,
    pub fragment: Option<Range<Size>>,
    pub _phantom: PhantomData<&'a ()>,
}

#[derive(Clone, Copy, Debug)]
pub struct DebugScope<S, L> {
    pub dbg_scope: S,

    /// Call site location, if this scope was inlined from another function.
    pub inlined_at: Option<L>,

    // Start and end offsets of the file to which this DIScope belongs.
    // These are used to quickly determine whether some span refers to the same file.
    pub file_start_pos: BytePos,
    pub file_end_pos: BytePos,
}

impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
    /// DILocations inherit source file name from the parent DIScope. Due to macro expansions
    /// it may so happen that the current span belongs to a different file than the DIScope
    /// corresponding to span's containing source scope. If so, we need to create a DIScope
    /// "extension" into that file.
    pub fn adjust_dbg_scope_for_span<Cx: CodegenMethods<'tcx, DIScope = S, DILocation = L>>(
        &self,
        cx: &Cx,
        span: Span,
    ) -> S {
        let pos = span.lo();
        if pos < self.file_start_pos || pos >= self.file_end_pos {
            let sm = cx.sess().source_map();
            cx.extend_scope_to_file(self.dbg_scope, &sm.lookup_char_pos(pos).file)
        } else {
            self.dbg_scope
        }
    }
}

trait DebugInfoOffsetLocation<'tcx, Bx> {
    fn deref(&self, bx: &mut Bx) -> Self;
    fn layout(&self) -> TyAndLayout<'tcx>;
    fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self;
    fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self;
    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
}

impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
    for PlaceRef<'tcx, Bx::Value>
{
    fn deref(&self, bx: &mut Bx) -> Self {
        bx.load_operand(*self).deref(bx.cx())
    }

    fn layout(&self) -> TyAndLayout<'tcx> {
        self.layout
    }

    fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self {
        PlaceRef::project_field(*self, bx, field.index())
    }

    fn project_constant_index(&self, bx: &mut Bx, offset: u64) -> Self {
        let lloffset = bx.cx().const_usize(offset);
        self.project_index(bx, lloffset)
    }

    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
        self.project_downcast(bx, variant)
    }
}

impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
    for TyAndLayout<'tcx>
{
    fn deref(&self, bx: &mut Bx) -> Self {
        bx.cx().layout_of(
            self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
        )
    }

    fn layout(&self) -> TyAndLayout<'tcx> {
        *self
    }

    fn project_field(&self, bx: &mut Bx, field: FieldIdx) -> Self {
        self.field(bx.cx(), field.index())
    }

    fn project_constant_index(&self, bx: &mut Bx, index: u64) -> Self {
        self.field(bx.cx(), index as usize)
    }

    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
        self.for_variant(bx.cx(), variant)
    }
}

struct DebugInfoOffset<T> {
    /// Offset from the `base` used to calculate the debuginfo offset.
    direct_offset: Size,
    /// Each offset in this vector indicates one level of indirection from the base or previous
    /// indirect offset plus a dereference.
    indirect_offsets: Vec<Size>,
    /// The final location debuginfo should point to.
    result: T,
}

fn calculate_debuginfo_offset<
    'a,
    'tcx,
    Bx: BuilderMethods<'a, 'tcx>,
    L: DebugInfoOffsetLocation<'tcx, Bx>,
>(
    bx: &mut Bx,
    projection: &[mir::PlaceElem<'tcx>],
    base: L,
) -> DebugInfoOffset<L> {
    let mut direct_offset = Size::ZERO;
    // FIXME(eddyb) use smallvec here.
    let mut indirect_offsets = vec![];
    let mut place = base;

    for elem in projection {
        match *elem {
            mir::ProjectionElem::Deref => {
                indirect_offsets.push(Size::ZERO);
                place = place.deref(bx);
            }
            mir::ProjectionElem::Field(field, _) => {
                let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
                *offset += place.layout().fields.offset(field.index());
                place = place.project_field(bx, field);
            }
            mir::ProjectionElem::Downcast(_, variant) => {
                place = place.downcast(bx, variant);
            }
            mir::ProjectionElem::ConstantIndex {
                offset: index,
                min_length: _,
                from_end: false,
            } => {
                let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
                let FieldsShape::Array { stride, count: _ } = place.layout().fields else {
                    bug!("ConstantIndex on non-array type {:?}", place.layout())
                };
                *offset += stride * index;
                place = place.project_constant_index(bx, index);
            }
            _ => {
                // Sanity check for `can_use_in_debuginfo`.
                assert!(!elem.can_use_in_debuginfo());
                bug!("unsupported var debuginfo projection `{:?}`", projection)
            }
        }
    }

    DebugInfoOffset { direct_offset, indirect_offsets, result: place }
}

impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
    pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
        bx.set_span(source_info.span);
        if let Some(dbg_loc) = self.dbg_loc(source_info) {
            bx.set_dbg_loc(dbg_loc);
        }
    }

    fn dbg_loc(&self, source_info: mir::SourceInfo) -> Option<Bx::DILocation> {
        let (dbg_scope, inlined_at, span) = self.adjusted_span_and_dbg_scope(source_info)?;
        Some(self.cx.dbg_loc(dbg_scope, inlined_at, span))
    }

    fn adjusted_span_and_dbg_scope(
        &self,
        source_info: mir::SourceInfo,
    ) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> {
        let scope = &self.debug_context.as_ref()?.scopes[source_info.scope];
        let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span);
        Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span))
    }

    fn spill_operand_to_stack(
        operand: OperandRef<'tcx, Bx::Value>,
        name: Option<String>,
        bx: &mut Bx,
    ) -> PlaceRef<'tcx, Bx::Value> {
        // "Spill" the value onto the stack, for debuginfo,
        // without forcing non-debuginfo uses of the local
        // to also load from the stack every single time.
        // FIXME(#68817) use `llvm.dbg.value` instead,
        // at least for the cases which LLVM handles correctly.
        let spill_slot = PlaceRef::alloca(bx, operand.layout);
        if let Some(name) = name {
            bx.set_var_name(spill_slot.val.llval, &(name + ".dbg.spill"));
        }
        operand.val.store(bx, spill_slot);
        spill_slot
    }

    // Indicates that local is set to a new value. The `layout` and `projection` are used to
    // calculate the offset.
    pub(crate) fn debug_new_val_to_local(
        &self,
        bx: &mut Bx,
        local: mir::Local,
        base: PlaceRef<'tcx, Bx::Value>,
        projection: &[mir::PlaceElem<'tcx>],
    ) {
        let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
        if !full_debug_info {
            return;
        }

        let vars = match &self.per_local_var_debug_info {
            Some(per_local) => &per_local[local],
            None => return,
        };

        let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
            calculate_debuginfo_offset(bx, projection, base.layout);
        for var in vars.iter() {
            let Some(dbg_var) = var.dbg_var else {
                continue;
            };
            let Some(dbg_loc) = self.dbg_loc(var.source_info) else {
                continue;
            };
            bx.dbg_var_value(
                dbg_var,
                dbg_loc,
                base.val.llval,
                direct_offset,
                &indirect_offsets,
                &var.fragment,
            );
        }
    }

    pub(crate) fn debug_poison_to_local(&self, bx: &mut Bx, local: mir::Local) {
        let ty = self.monomorphize(self.mir.local_decls[local].ty);
        let layout = bx.cx().layout_of(ty);
        let to_backend_ty = bx.cx().immediate_backend_type(layout);
        let place_ref = PlaceRef::new_sized(bx.cx().const_poison(to_backend_ty), layout);
        self.debug_new_val_to_local(bx, local, place_ref, &[]);
    }

    /// Apply debuginfo and/or name, after creating the `alloca` for a local,
    /// or initializing the local with an operand (whichever applies).
    pub(crate) fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
        let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;

        let vars = match &self.per_local_var_debug_info {
            Some(per_local) => &per_local[local],
            None => return,
        };
        let whole_local_var = vars.iter().find(|var| var.projection.is_empty()).cloned();
        let has_proj = || vars.iter().any(|var| !var.projection.is_empty());

        let fallback_var = if self.mir.local_kind(local) == mir::LocalKind::Arg {
            let arg_index = local.index() - 1;

            // Add debuginfo even to unnamed arguments.
            // FIXME(eddyb) is this really needed?
            if arg_index == 0 && has_proj() {
                // Hide closure environments from debuginfo.
                // FIXME(eddyb) shouldn't `ArgumentVariable` indices
                // be offset to account for the hidden environment?
                None
            } else if whole_local_var.is_some() {
                // No need to make up anything, there is a `mir::VarDebugInfo`
                // covering the whole local.
                // FIXME(eddyb) take `whole_local_var.source_info.scope` into
                // account, just in case it doesn't use `ArgumentVariable`
                // (after #67586 gets fixed).
                None
            } else {
                let name = sym::empty;
                let decl = &self.mir.local_decls[local];
                let dbg_var = if full_debug_info {
                    self.adjusted_span_and_dbg_scope(decl.source_info).map(
                        |(dbg_scope, _, span)| {
                            // FIXME(eddyb) is this `+ 1` needed at all?
                            let kind = VariableKind::ArgumentVariable(arg_index + 1);

                            let arg_ty = self.monomorphize(decl.ty);

                            self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
                        },
                    )
                } else {
                    None
                };

                Some(PerLocalVarDebugInfo {
                    name,
                    source_info: decl.source_info,
                    dbg_var,
                    fragment: None,
                    projection: ty::List::empty(),
                })
            }
        } else {
            None
        };

        let local_ref = &self.locals[local];

        let name = if bx.sess().fewer_names() {
            None
        } else {
            Some(match whole_local_var.or_else(|| fallback_var.clone()) {
                Some(var) if var.name != sym::empty => var.name.to_string(),
                _ => format!("{local:?}"),
            })
        };

        if let Some(name) = &name {
            match local_ref {
                LocalRef::Place(place) | LocalRef::UnsizedPlace(place) => {
                    bx.set_var_name(place.val.llval, name);
                }
                LocalRef::Operand(operand) => match operand.val {
                    OperandValue::Ref(PlaceValue { llval: x, .. }) | OperandValue::Immediate(x) => {
                        bx.set_var_name(x, name);
                    }
                    OperandValue::Pair(a, b) => {
                        // FIXME(eddyb) these are scalar components,
                        // maybe extract the high-level fields?
                        bx.set_var_name(a, &(name.clone() + ".0"));
                        bx.set_var_name(b, &(name.clone() + ".1"));
                    }
                    OperandValue::ZeroSized => {
                        // These never have a value to talk about
                    }
                },
                LocalRef::PendingOperand => {}
            }
        }

        if !full_debug_info || vars.is_empty() && fallback_var.is_none() {
            return;
        }

        let base = match local_ref {
            LocalRef::PendingOperand => return,

            LocalRef::Operand(operand) => {
                // Don't spill operands onto the stack in naked functions.
                // See: https://github.com/rust-lang/rust/issues/42779
                let attrs = bx.tcx().codegen_instance_attrs(self.instance.def);
                if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
                    return;
                }

                // Don't spill `<vscale x N x i1>` for `N != 16`:
                //
                // SVE predicates are only one bit for each byte in an SVE vector (which makes
                // sense, the predicate only needs to keep track of whether a lane is
                // enabled/disabled). i.e. a `<vscale x 16 x i8>` vector has a `<vscale x 16 x i1>`
                // predicate type. `<vscale x 16 x i1>` corresponds to two bytes of storage,
                // multiplied by the `vscale`, with one bit for each of the sixteen lanes.
                //
                // For a vector with fewer elements, such as `svint32_t`/`<vscale x 4 x i32>`,
                // while only a `<vscale x 4 x i1>` predicate type would be strictly necessary,
                // relevant intrinsics still take a `svbool_t`/`<vscale x 16 x i1>` - this is
                // because a `<vscale x 4 x i1>` is only half of a byte (for `vscale=1`), and with
                // memory being byte-addressable, it's unclear how to store that.
                //
                // Due to this, LLVM ultimately decided not to support stores of `<vscale x N x i1>`
                // for `N != 16`. As for `vscale=1` and `N` fewer than sixteen, partial bytes would
                // need to be stored (except for `N=8`, but that also isn't supported). `N` can
                // never be greater than sixteen as that ends up larger than the 128-bit increment
                // size.
                //
                // Internally, with an intrinsic operating on a `svint32_t`/`<vscale x 4 x i32>`
                // (for example), the intrinsic takes the `svbool_t`/`<vscale x 16 x i1>` predicate
                // and casts it to a `svbool4_t`/`<vscale x 4 x i1>`. Therefore, it's important that
                // the `<vscale x 4 x i1>` never spills because that'll cause errors during
                // instruction selection. Spilling to the stack to create debuginfo for these
                // intermediate values must be avoided and doing so won't affect the
                // debugging experience anyway.
                if operand.layout.ty.is_scalable_vector()
                    && bx.sess().target.arch == rustc_target::spec::Arch::AArch64
                {
                    let (count, element_ty, _) =
                        operand.layout.ty.scalable_vector_parts(bx.tcx()).unwrap();
                    // i.e. `<vscale x N x i1>` when `N != 16`
                    if element_ty.is_bool() && count != 16 {
                        return;
                    }
                }

                Self::spill_operand_to_stack(*operand, name, bx)
            }

            LocalRef::Place(place) => *place,

            // FIXME(eddyb) add debuginfo for unsized places too.
            LocalRef::UnsizedPlace(_) => return,
        };

        let vars = vars.iter().cloned().chain(fallback_var);

        for var in vars {
            self.debug_introduce_local_as_var(bx, local, base, var);
        }
    }

    fn debug_introduce_local_as_var(
        &self,
        bx: &mut Bx,
        local: mir::Local,
        base: PlaceRef<'tcx, Bx::Value>,
        var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
    ) {
        let Some(dbg_var) = var.dbg_var else { return };
        let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };

        let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
            calculate_debuginfo_offset(bx, var.projection, base.layout);

        // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
        // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
        // not DWARF and LLVM doesn't support translating the resulting
        // [DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref] debug info to CodeView.
        // Creating extra allocas on the stack makes the resulting debug info simple enough
        // that LLVM can generate correct CodeView records and thus the values appear in the
        // debugger. (#83709)
        let should_create_individual_allocas = bx.cx().sess().target.is_like_msvc
            && self.mir.local_kind(local) == mir::LocalKind::Arg
            // LLVM can handle simple things but anything more complex than just a direct
            // offset or one indirect offset of 0 is too complex for it to generate CV records
            // correctly.
            && (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));

        if should_create_individual_allocas {
            let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
                calculate_debuginfo_offset(bx, var.projection, base);

            // Create a variable which will be a pointer to the actual value
            let ptr_ty = Ty::new_mut_ptr(bx.tcx(), place.layout.ty);
            let ptr_layout = bx.layout_of(ptr_ty);
            let alloca = PlaceRef::alloca(bx, ptr_layout);
            bx.set_var_name(alloca.val.llval, &(var.name.to_string() + ".dbg.spill"));

            // Write the pointer to the variable
            bx.store_to_place(place.val.llval, alloca.val);

            // Point the debug info to `*alloca` for the current variable
            bx.dbg_var_addr(
                dbg_var,
                dbg_loc,
                alloca.val.llval,
                Size::ZERO,
                &[Size::ZERO],
                &var.fragment,
            );
        } else {
            bx.dbg_var_addr(
                dbg_var,
                dbg_loc,
                base.val.llval,
                direct_offset,
                &indirect_offsets,
                &var.fragment,
            );
        }
    }

    pub(crate) fn debug_introduce_locals(
        &self,
        bx: &mut Bx,
        consts: Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
    ) {
        if bx.sess().opts.debuginfo == DebugInfo::Full || !bx.sess().fewer_names() {
            for local in self.locals.indices() {
                self.debug_introduce_local(bx, local);
            }

            for ConstDebugInfo { name, source_info, operand, dbg_var, dbg_loc, fragment, .. } in
                consts.into_iter()
            {
                self.set_debug_loc(bx, source_info);
                let base = FunctionCx::spill_operand_to_stack(operand, Some(name), bx);
                bx.clear_dbg_loc();

                bx.dbg_var_addr(dbg_var, dbg_loc, base.val.llval, Size::ZERO, &[], &fragment);
            }
        }
    }

    /// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
    pub(crate) fn compute_per_local_var_debug_info(
        &self,
        bx: &mut Bx,
    ) -> Option<(
        PerLocalVarDebugInfoIndexVec<'tcx, Bx::DIVariable>,
        Vec<ConstDebugInfo<'a, 'tcx, Bx>>,
    )> {
        let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;

        let target_is_msvc = self.cx.sess().target.is_like_msvc;

        if !full_debug_info && self.cx.sess().fewer_names() {
            return None;
        }

        let mut per_local = IndexVec::from_elem(vec![], &self.mir.local_decls);
        let mut constants = vec![];
        let mut params_seen: FxHashMap<_, Bx::DIVariable> = Default::default();
        for var in &self.mir.var_debug_info {
            let dbg_scope_and_span = if full_debug_info {
                self.adjusted_span_and_dbg_scope(var.source_info)
            } else {
                None
            };

            let var_ty = if let Some(ref fragment) = var.composite {
                self.monomorphize(fragment.ty)
            } else {
                match var.value {
                    mir::VarDebugInfoContents::Place(place) => {
                        self.monomorphized_place_ty(place.as_ref())
                    }
                    mir::VarDebugInfoContents::Const(c) => self.monomorphize(c.ty()),
                }
            };

            let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
                let var_kind = if let Some(arg_index) = var.argument_index
                    && var.composite.is_none()
                    && let mir::VarDebugInfoContents::Place(place) = var.value
                    && place.projection.is_empty()
                {
                    let arg_index = arg_index as usize;
                    if target_is_msvc {
                        // ScalarPair parameters are spilled to the stack so they need to
                        // be marked as a `LocalVariable` for MSVC debuggers to visualize
                        // their data correctly. (See #81894 & #88625)
                        let var_ty_layout = self.cx.layout_of(var_ty);
                        if let BackendRepr::ScalarPair(_, _) = var_ty_layout.backend_repr {
                            VariableKind::LocalVariable
                        } else {
                            VariableKind::ArgumentVariable(arg_index)
                        }
                    } else {
                        // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
                        // offset in closures to account for the hidden environment?
                        VariableKind::ArgumentVariable(arg_index)
                    }
                } else {
                    VariableKind::LocalVariable
                };

                if let VariableKind::ArgumentVariable(arg_index) = var_kind {
                    match params_seen.entry((dbg_scope, arg_index)) {
                        Entry::Occupied(o) => o.get().clone(),
                        Entry::Vacant(v) => v
                            .insert(
                                self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span),
                            )
                            .clone(),
                    }
                } else {
                    self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
                }
            });

            let fragment = if let Some(ref fragment) = var.composite {
                let var_layout = self.cx.layout_of(var_ty);

                let DebugInfoOffset { direct_offset, indirect_offsets, result: fragment_layout } =
                    calculate_debuginfo_offset(bx, &fragment.projection, var_layout);
                assert!(indirect_offsets.is_empty());

                if fragment_layout.size == Size::ZERO {
                    // Fragment is a ZST, so does not represent anything. Avoid generating anything
                    // as this may conflict with a fragment that covers the entire variable.
                    continue;
                } else if fragment_layout.size == var_layout.size {
                    // Fragment covers entire variable, so as far as
                    // DWARF is concerned, it's not really a fragment.
                    None
                } else {
                    Some(direct_offset..direct_offset + fragment_layout.size)
                }
            } else {
                None
            };

            match var.value {
                mir::VarDebugInfoContents::Place(place) => {
                    per_local[place.local].push(PerLocalVarDebugInfo {
                        name: var.name,
                        source_info: var.source_info,
                        dbg_var,
                        fragment,
                        projection: place.projection,
                    });
                }
                mir::VarDebugInfoContents::Const(c) => {
                    if let Some(dbg_var) = dbg_var {
                        let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };

                        let operand = self.eval_mir_constant_to_operand(bx, &c);
                        constants.push(ConstDebugInfo {
                            name: var.name.to_string(),
                            source_info: var.source_info,
                            operand,
                            dbg_var,
                            dbg_loc,
                            fragment,
                            _phantom: PhantomData,
                        });
                    }
                }
            }
        }
        Some((per_local, constants))
    }
}
