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_index::bit_set::DenseBitSet;
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, DUMMY_SP, 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<
        'a,
        Bx: BuilderMethods<'a, 'tcx, DIScope = S, DILocation = L>,
    >(
        &self,
        bx: &mut Bx,
        span: Span,
    ) -> S {
        let pos = span.lo();
        if pos < self.file_start_pos || pos >= self.file_end_pos {
            let sm = bx.sess().source_map();
            bx.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(bx, source_info) {
            bx.set_dbg_loc(dbg_loc);
        }
    }

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

    fn adjusted_span_and_dbg_scope(
        &self,
        bx: &mut Bx,
        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(bx, 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.
    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(bx, var.source_info) else {
                continue;
            };
            bx.dbg_var_value(
                dbg_var,
                dbg_loc,
                base.val.llval,
                direct_offset,
                &indirect_offsets,
                &var.fragment,
            );
        }
    }

    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(bx, 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);

                            bx.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(bx, 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(bx, 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 { a: _, b: _, b_offset: _ } =
                            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(bx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span))
                            .clone(),
                    }
                } else {
                    bx.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(bx, 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))
    }

    pub(crate) fn codegen_stmt_debuginfo(
        &mut self,
        bx: &mut Bx,
        debuginfo: &mir::StmtDebugInfo<'tcx>,
    ) {
        match debuginfo {
            mir::StmtDebugInfo::AssignRef(dest, place) => {
                let local_ref = match self.locals[place.local] {
                    // For an rvalue like `&(_1.1)`, when `BackendRepr` is `BackendRepr::Memory`, we allocate a block of memory to this place.
                    // The place is an indirect pointer, we can refer to it directly.
                    LocalRef::Place(place_ref) => Some((place_ref, place.projection.as_slice())),
                    // For an rvalue like `&((*_1).1)`, we are calculating the address of `_1.1`.
                    // The deref projection is no-op here.
                    LocalRef::Operand(operand_ref) if place.is_indirect_first_projection() => {
                        Some((operand_ref.deref(bx.cx()), &place.projection[1..]))
                    }
                    // For an rvalue like `&1`, when `BackendRepr` is `BackendRepr::Scalar`,
                    // we cannot get the address.
                    // N.B. `non_ssa_locals` returns that this is an SSA local.
                    LocalRef::Operand(_) => None,
                    LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => None,
                }
                .filter(|(_, projection)| {
                    // Drop unsupported projections.
                    projection.iter().all(|p| p.can_use_in_debuginfo())
                });
                if let Some((base, projection)) = local_ref {
                    self.debug_new_val_to_local(bx, *dest, base, projection);
                } else {
                    // If the address cannot be calculated, use poison to indicate that the value has been optimized out.
                    self.debug_poison_to_local(bx, *dest);
                }
            }
            mir::StmtDebugInfo::InvalidAssign(local) => {
                self.debug_poison_to_local(bx, *local);
            }
        }
    }

    pub(crate) fn codegen_stmt_debuginfos(
        &mut self,
        bx: &mut Bx,
        debuginfos: &[mir::StmtDebugInfo<'tcx>],
    ) {
        for debuginfo in debuginfos {
            self.codegen_stmt_debuginfo(bx, debuginfo);
        }
    }

    /// Creates the function-specific debug context.
    ///
    /// Returns the FunctionDebugContext for the function which holds state needed
    /// for debug info creation, if it is enabled.
    pub(super) fn fill_function_debug_context(&mut self, bx: &mut Bx) {
        if self.cx.sess().opts.debuginfo == DebugInfo::None {
            return;
        }

        // Initialize fn debug context (including scopes).
        self.debug_context = Some(FunctionDebugContext {
            scopes: IndexVec::with_capacity(self.mir.source_scopes.len()),
            inlined_function_scopes: Default::default(),
        });

        // Find all scopes with variables defined in them.
        let variables = if self.cx.sess().opts.debuginfo == DebugInfo::Full {
            let mut vars = DenseBitSet::new_empty(self.mir.source_scopes.len());
            // FIXME(eddyb) take into account that arguments always have debuginfo,
            // irrespective of their name (assuming full debuginfo is enabled).
            // NOTE(eddyb) actually, on second thought, those are always in the
            // function scope, which always exists.
            for var_debug_info in &self.mir.var_debug_info {
                vars.insert(var_debug_info.source_info.scope);
            }
            Some(vars)
        } else {
            // Nothing to emit, of course.
            None
        };

        // Instantiate all scopes.
        let mut discriminators = FxHashMap::default();
        for scope in self.mir.source_scopes.indices() {
            let scope_data = self.make_mir_scope(bx, &variables, &mut discriminators, scope);
            let _s = self.debug_context.as_mut().unwrap().scopes.push(scope_data);
            debug_assert_eq!(_s, scope);
        }
    }

    fn make_mir_scope(
        &mut self,
        bx: &mut Bx,
        variables: &Option<DenseBitSet<mir::SourceScope>>,
        discriminators: &mut FxHashMap<BytePos, u32>,
        scope: mir::SourceScope,
    ) -> DebugScope<Bx::DIScope, Bx::DILocation> {
        let scope_data = &self.mir.source_scopes[scope];
        let parent_scope = if let Some(parent) = scope_data.parent_scope {
            debug_assert!(parent.as_u32() < scope.as_u32());
            self.debug_context.as_ref().unwrap().scopes[parent]
        } else {
            // The root is the function itself.
            let file = self.cx.sess().source_map().lookup_source_file(self.mir.span.lo());
            let dbg_scope = bx.dbg_scope_fn(self.instance, self.fn_abi, Some(self.llfn));
            return DebugScope {
                dbg_scope,
                inlined_at: None,
                file_start_pos: file.start_pos,
                file_end_pos: file.end_position(),
            };
        };

        if let Some(vars) = variables
            && !vars.contains(scope)
            && scope_data.inlined.is_none()
        {
            // Do not create a DIScope if there are no variables defined in this
            // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
            return parent_scope;
        }

        let dbg_scope = match scope_data.inlined {
            Some((callee, _)) => {
                let callee = self.monomorphize(callee);
                *self
                    .debug_context
                    .as_mut()
                    .unwrap()
                    .inlined_function_scopes
                    .entry(callee)
                    .or_insert_with(|| {
                        let callee_fn_abi = self.cx.fn_abi_of_instance(callee, ty::List::empty());
                        bx.dbg_scope_fn(callee, callee_fn_abi, None)
                    })
            }
            None => bx.dbg_create_lexical_block(scope_data.span.lo(), parent_scope.dbg_scope),
        };

        let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
            let callsite_span = hygiene::walk_chain_collapsed(callsite_span, self.mir.span);
            let callsite_scope = parent_scope.adjust_dbg_scope_for_span(bx, callsite_span);
            let loc = bx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span);

            // NB: In order to produce proper debug info for variables (particularly
            // arguments) in multiply-inlined functions, LLVM expects to see a single
            // DILocalVariable with multiple different DILocations in the IR. While
            // the source information for each DILocation would be identical, their
            // inlinedAt attributes will be unique to the particular callsite.
            //
            // We generate DILocations here based on the callsite's location in the
            // source code. A single location in the source code usually can't
            // produce multiple distinct calls so this mostly works, until
            // macros get involved. A macro can generate multiple calls
            // at the same span, which breaks the assumption that we're going to
            // produce a unique DILocation for every scope we process here. We
            // have to explicitly add discriminators if we see inlines into the
            // same source code location.
            //
            // Note further that we can't key this hashtable on the span itself,
            // because these spans could have distinct SyntaxContexts. We have
            // to key on exactly what we're giving to LLVM.
            match discriminators.entry(callsite_span.lo()) {
                Entry::Occupied(mut o) => {
                    *o.get_mut() += 1;
                    // NB: We have to emit *something* here or we'll fail LLVM IR verification
                    // in at least some circumstances (see issue #135322) so if the required
                    // discriminant cannot be encoded fall back to the dummy location.
                    bx.dbg_location_clone_with_discriminator(loc, *o.get()).unwrap_or_else(|| {
                        bx.dbg_loc(callsite_scope, parent_scope.inlined_at, DUMMY_SP)
                    })
                }
                Entry::Vacant(v) => {
                    v.insert(0);
                    loc
                }
            }
        });

        let file = self.cx.sess().source_map().lookup_source_file(scope_data.span.lo());
        DebugScope {
            dbg_scope,
            inlined_at: inlined_at.or(parent_scope.inlined_at),
            file_start_pos: file.start_pos,
            file_end_pos: file.end_position(),
        }
    }
}
