use std::borrow::Cow;
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::{assert_matches, iter, ptr};

use libc::{c_longlong, c_uint};
use rustc_abi::{Align, Layout, NumScalableVectors, Size};
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::ty::layout::{
    HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA,
};
use rustc_middle::ty::{
    self, AdtDef, AdtKind, ExistentialTraitRef, Instance, Ty, TyCtxt, Unnormalized, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::spec::{Arch, DebuginfoKind};
use smallvec::smallvec;
use tracing::{debug, instrument};

pub(crate) use self::type_map::TypeMap;
use self::type_map::{DINodeCreationResult, Stub, UniqueTypeId};
use super::CodegenUnitDebugContext;
use super::namespace::mangled_name_of_instance;
use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_name};
use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit};
use crate::common::{AsCCharPtr, CodegenCx};
use crate::debuginfo::metadata::type_map::build_type_with_children;
use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind};
use crate::debuginfo::{DIBuilderExt, dwarf_const};
use crate::llvm::debuginfo::{
    DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock,
    DIScope, DIType, DebugEmissionKind, DebugNameTableKind,
};
use crate::llvm::{self, FromGeneric, Value};

impl PartialEq for llvm::Metadata {
    fn eq(&self, other: &Self) -> bool {
        ptr::eq(self, other)
    }
}

impl Eq for llvm::Metadata {}

impl Hash for llvm::Metadata {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        (self as *const Self).hash(hasher);
    }
}

impl fmt::Debug for llvm::Metadata {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (self as *const Self).fmt(f)
    }
}

pub(super) const UNKNOWN_LINE_NUMBER: c_uint = 0;
pub(super) const UNKNOWN_COLUMN_NUMBER: c_uint = 0;

const NO_SCOPE_METADATA: Option<&DIScope> = None;
/// A function that returns an empty list of generic parameter debuginfo nodes.
const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<Option<&'ll DIType>> =
    |_| SmallVec::new();

// SmallVec is used quite a bit in this module, so create a shorthand.
// The actual number of elements is not so important.
type SmallVec<T> = smallvec::SmallVec<[T; 16]>;

mod enums;
mod type_map;

/// Returns from the enclosing function if the type debuginfo node with the given
/// unique ID can be found in the type map.
macro_rules! return_if_di_node_created_in_meantime {
    ($cx: expr, $unique_type_id: expr) => {
        if let Some(di_node) = debug_context($cx).type_map.di_node_for_unique_id($unique_type_id) {
            return DINodeCreationResult::new(di_node, true);
        }
    };
}

/// Extract size and alignment from a TyAndLayout.
#[inline]
fn size_and_align_of(ty_and_layout: TyAndLayout<'_>) -> (Size, Align) {
    (ty_and_layout.size, ty_and_layout.align.abi)
}

/// Creates debuginfo for a fixed size array (e.g. `[u64; 123]`).
/// For slices (that is, "arrays" of unknown size) use [build_slice_type_di_node].
fn build_fixed_size_array_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
    array_type: Ty<'tcx>,
    span: Span,
) -> DINodeCreationResult<'ll> {
    let ty::Array(element_type, len) = array_type.kind() else {
        bug!("build_fixed_size_array_di_node() called with non-ty::Array type `{:?}`", array_type)
    };

    let element_type_di_node = spanned_type_di_node(cx, *element_type, span);

    return_if_di_node_created_in_meantime!(cx, unique_type_id);

    let (size, align) = cx.spanned_size_and_align_of(array_type, span);

    let upper_bound = len
        .try_to_target_usize(cx.tcx)
        .expect("expected monomorphic const in codegen") as c_longlong;

    let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) };
    let subscripts = &[subrange];

    let di_node = unsafe {
        llvm::LLVMDIBuilderCreateArrayType(
            DIB(cx),
            size.bits(),
            align.bits() as u32,
            element_type_di_node,
            subscripts.as_ptr(),
            subscripts.len() as c_uint,
        )
    };

    DINodeCreationResult::new(di_node, false)
}

/// Creates debuginfo for built-in pointer-like things:
///
///  - ty::Ref
///  - ty::RawPtr
///  - ty::Adt in the case it's Box
///
/// At some point we might want to remove the special handling of Box
/// and treat it the same as other smart pointers (like Rc, Arc, ...).
fn build_pointer_or_reference_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    ptr_type: Ty<'tcx>,
    pointee_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
    span: Span,
) -> DINodeCreationResult<'ll> {
    // The debuginfo generated by this function is only valid if `ptr_type` is really just
    // a (wide) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
    assert_eq!(
        cx.size_and_align_of(ptr_type),
        cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
    );

    let pointee_type_di_node = match pointee_type.kind() {
        // `&[T]` will look like `{ data_ptr: *const T, length: usize }`
        ty::Slice(element_type) => spanned_type_di_node(cx, *element_type, span),
        // `&str` will look like `{ data_ptr: *const u8, length: usize }`
        ty::Str => type_di_node(cx, cx.tcx.types.u8),

        // `&dyn K` will look like `{ pointer: _, vtable: _}`
        // any Adt `Foo` containing an unsized type (eg `&[_]` or `&dyn _`)
        //   will look like `{ data_ptr: *const Foo, length: usize }`
        // and thin pointers `&Foo` will just look like `*const Foo`.
        //
        // in all those cases, we just use the pointee_type
        _ => spanned_type_di_node(cx, pointee_type, span),
    };

    return_if_di_node_created_in_meantime!(cx, unique_type_id);

    let data_layout = &cx.tcx.data_layout;
    let pointer_size = data_layout.pointer_size();
    let pointer_align = data_layout.pointer_align();
    let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);

    match wide_pointer_kind(cx, pointee_type) {
        None => {
            // This is a thin pointer. Create a regular pointer type and give it the correct name.
            assert_eq!(
                (pointer_size, pointer_align.abi),
                cx.size_and_align_of(ptr_type),
                "ptr_type={ptr_type}, pointee_type={pointee_type}",
            );

            let di_node = create_pointer_type(
                cx,
                pointee_type_di_node,
                pointer_size,
                pointer_align.abi,
                &ptr_type_debuginfo_name,
            );

            DINodeCreationResult { di_node, already_stored_in_typemap: false }
        }
        Some(wide_pointer_kind) => {
            type_map::build_type_with_children(
                cx,
                type_map::stub(
                    cx,
                    Stub::Struct,
                    unique_type_id,
                    &ptr_type_debuginfo_name,
                    None,
                    cx.size_and_align_of(ptr_type),
                    NO_SCOPE_METADATA,
                    DIFlags::FlagZero,
                ),
                |cx, owner| {
                    // FIXME: If this wide pointer is a `Box` then we don't want to use its
                    //        type layout and instead use the layout of the raw pointer inside
                    //        of it.
                    //        The proper way to handle this is to not treat Box as a pointer
                    //        at all and instead emit regular struct debuginfo for it. We just
                    //        need to make sure that we don't break existing debuginfo consumers
                    //        by doing that (at least not without a warning period).
                    let layout_type = if ptr_type.is_box() {
                        // The assertion at the start of this function ensures we have a ZST
                        // allocator. We'll make debuginfo "skip" all ZST allocators, not just the
                        // default allocator.
                        Ty::new_mut_ptr(cx.tcx, pointee_type)
                    } else {
                        ptr_type
                    };

                    let layout = cx.layout_of(layout_type);
                    let addr_field = layout.field(cx, WIDE_PTR_ADDR);
                    let extra_field = layout.field(cx, WIDE_PTR_EXTRA);

                    let (addr_field_name, extra_field_name) = match wide_pointer_kind {
                        WidePtrKind::Dyn => ("pointer", "vtable"),
                        WidePtrKind::Slice => ("data_ptr", "length"),
                    };

                    assert_eq!(WIDE_PTR_ADDR, 0);
                    assert_eq!(WIDE_PTR_EXTRA, 1);

                    // The data pointer type is a regular, thin pointer, regardless of whether this
                    // is a slice or a trait object.
                    let data_ptr_type_di_node = create_pointer_type(
                        cx,
                        pointee_type_di_node,
                        addr_field.size,
                        addr_field.align.abi,
                        "",
                    );

                    smallvec![
                        build_field_di_node(
                            cx,
                            owner,
                            addr_field_name,
                            addr_field,
                            layout.fields.offset(WIDE_PTR_ADDR),
                            DIFlags::FlagZero,
                            data_ptr_type_di_node,
                            None,
                        ),
                        build_field_di_node(
                            cx,
                            owner,
                            extra_field_name,
                            extra_field,
                            layout.fields.offset(WIDE_PTR_EXTRA),
                            DIFlags::FlagZero,
                            type_di_node(cx, extra_field.ty),
                            None,
                        ),
                    ]
                },
                NO_GENERICS,
            )
        }
    }
}

fn build_subroutine_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
) -> DINodeCreationResult<'ll> {
    // It's possible to create a self-referential type in Rust by using 'impl trait':
    //
    // fn foo() -> impl Copy { foo }
    //
    // Unfortunately LLVM's API does not allow us to create recursive subroutine types.
    // In order to work around that restriction we place a marker type in the type map,
    // before creating the actual type. If the actual type is recursive, it will hit the
    // marker type. So we end up with a type that looks like
    //
    // fn foo() -> <recursive_type>
    //
    // Once that is created, we replace the marker in the typemap with the actual type.
    debug_context(cx)
        .type_map
        .unique_id_to_di_node
        .borrow_mut()
        .insert(unique_type_id, recursion_marker_type_di_node(cx));

    let fn_ty = unique_type_id.expect_ty();
    let signature =
        cx.tcx.normalize_erasing_late_bound_regions(cx.typing_env(), fn_ty.fn_sig(cx.tcx));

    let signature_di_nodes: SmallVec<_> = iter::once(
        // return type
        match signature.output().kind() {
            ty::Tuple(tys) if tys.is_empty() => {
                // this is a "void" function
                None
            }
            _ => Some(type_di_node(cx, signature.output())),
        },
    )
    .chain(
        // regular arguments
        signature.inputs().iter().map(|&argument_type| Some(type_di_node(cx, argument_type))),
    )
    .collect();

    debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id);

    let fn_di_node = create_subroutine_type(cx, &signature_di_nodes[..]);

    // This is actually a function pointer, so wrap it in pointer DI.
    let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
    let (size, align) = match fn_ty.kind() {
        ty::FnDef(..) => (Size::ZERO, Align::ONE),
        ty::FnPtr(..) => {
            (cx.tcx.data_layout.pointer_size(), cx.tcx.data_layout.pointer_align().abi)
        }
        _ => unreachable!(),
    };
    let di_node = create_pointer_type(cx, fn_di_node, size, align, &name);

    DINodeCreationResult::new(di_node, false)
}

pub(super) fn create_subroutine_type<'ll>(
    cx: &CodegenCx<'ll, '_>,
    signature: &[Option<&'ll llvm::Metadata>],
) -> &'ll DICompositeType {
    unsafe {
        llvm::LLVMDIBuilderCreateSubroutineType(
            DIB(cx),
            None, // ("File" is ignored and has no effect)
            signature.as_ptr(),
            signature.len() as c_uint,
            DIFlags::FlagZero, // (default value)
        )
    }
}

fn create_pointer_type<'ll>(
    cx: &CodegenCx<'ll, '_>,
    pointee_ty: &'ll llvm::Metadata,
    size: Size,
    align: Align,
    name: &str,
) -> &'ll llvm::Metadata {
    unsafe {
        llvm::LLVMDIBuilderCreatePointerType(
            DIB(cx),
            pointee_ty,
            size.bits(),
            align.bits() as u32,
            0, // Ignore DWARF address space.
            name.as_ptr(),
            name.len(),
        )
    }
}

/// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
/// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync").
fn build_dyn_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    dyn_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
) -> DINodeCreationResult<'ll> {
    if let ty::Dynamic(..) = dyn_type.kind() {
        let type_name = compute_debuginfo_type_name(cx.tcx, dyn_type, true);
        type_map::build_type_with_children(
            cx,
            type_map::stub(
                cx,
                Stub::Struct,
                unique_type_id,
                &type_name,
                None,
                cx.size_and_align_of(dyn_type),
                NO_SCOPE_METADATA,
                DIFlags::FlagZero,
            ),
            |_, _| smallvec![],
            NO_GENERICS,
        )
    } else {
        bug!(
            "Only ty::Dynamic is valid for build_dyn_type_di_node(). Found {:?} instead.",
            dyn_type
        )
    }
}

/// Create debuginfo for `[T]` and `str`. These are unsized.
fn build_slice_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    slice_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
    span: Span,
) -> DINodeCreationResult<'ll> {
    let element_type = match slice_type.kind() {
        ty::Slice(element_type) => *element_type,
        ty::Str => cx.tcx.types.u8,
        _ => {
            bug!(
                "Only ty::Slice is valid for build_slice_type_di_node(). Found {:?} instead.",
                slice_type
            )
        }
    };

    let element_type_di_node = type_di_node(cx, element_type);
    return_if_di_node_created_in_meantime!(cx, unique_type_id);
    let (size, align) = cx.spanned_size_and_align_of(slice_type, span);
    let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, -1) };
    let subscripts = &[subrange];
    let di_node = unsafe {
        llvm::LLVMDIBuilderCreateArrayType(
            DIB(cx),
            size.bits(),
            align.bits() as u32,
            element_type_di_node,
            subscripts.as_ptr(),
            subscripts.len() as c_uint,
        )
    };
    DINodeCreationResult { di_node, already_stored_in_typemap: false }
}

/// Get the debuginfo node for the given type.
///
/// This function will look up the debuginfo node in the TypeMap. If it can't find it, it
/// will create the node by dispatching to the corresponding `build_*_di_node()` function.
pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
    spanned_type_di_node(cx, t, DUMMY_SP)
}

pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    t: Ty<'tcx>,
    span: Span,
) -> &'ll DIType {
    let unique_type_id = UniqueTypeId::for_ty(cx.tcx, t);

    if let Some(existing_di_node) = debug_context(cx).type_map.di_node_for_unique_id(unique_type_id)
    {
        return existing_di_node;
    }

    debug!("type_di_node: {:?} kind: {:?}", t, t.kind());

    let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() {
        ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
            build_basic_type_di_node(cx, t)
        }
        ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t),
        ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t, span),
        ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id, span),
        ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id),
        ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id),
        ty::RawPtr(pointee_type, _) | ty::Ref(_, pointee_type, _) => {
            build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id, span)
        }
        // Some `Box` are newtyped pointers, make debuginfo aware of that.
        // Only works if the allocator argument is a 1-ZST and hence irrelevant for layout
        // (or if there is no allocator argument).
        ty::Adt(def, args)
            if def.is_box()
                && args.get(1).is_none_or(|arg| cx.layout_of(arg.expect_ty()).is_1zst()) =>
        {
            build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id, span)
        }
        ty::FnDef(..) | ty::FnPtr(..) => build_subroutine_type_di_node(cx, unique_type_id),
        ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id),
        ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id),
        ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id),
        ty::Adt(def, ..) => match def.adt_kind() {
            AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id, span),
            AdtKind::Union => build_union_type_di_node(cx, unique_type_id, span),
            AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span),
        },
        ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
        ty::Pat(base, _) => return type_di_node(cx, base),
        ty::UnsafeBinder(_) => build_unsafe_binder_type_di_node(cx, t, unique_type_id),
        ty::Alias(..)
        | ty::Param(_)
        | ty::Bound(..)
        | ty::Infer(_)
        | ty::Placeholder(_)
        | ty::CoroutineWitness(..)
        | ty::Error(_) => {
            bug!("debuginfo: unexpected type in type_di_node(): {:?}", t)
        }
    };

    {
        if already_stored_in_typemap {
            // Make sure that we really do have a `TypeMap` entry for the unique type ID.
            let di_node_for_uid =
                match debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) {
                    Some(di_node) => di_node,
                    None => {
                        bug!(
                            "expected type debuginfo node for unique \
                               type ID '{:?}' to already be in \
                               the `debuginfo::TypeMap` but it \
                               was not.",
                            unique_type_id,
                        );
                    }
                };

            assert_eq!(di_node_for_uid as *const _, di_node as *const _);
        } else {
            debug_context(cx).type_map.insert(unique_type_id, di_node);
        }
    }

    di_node
}

// FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context.
fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType {
    *debug_context(cx).recursion_marker_type.get_or_init(move || {
        // The choice of type here is pretty arbitrary -
        // anything reading the debuginfo for a recursive
        // type is going to see *something* weird - the only
        // question is what exactly it will see.
        //
        // FIXME: the name `<recur_type>` does not fit the naming scheme
        //        of other types.
        //
        // FIXME: it might make sense to use an actual pointer type here
        //        so that debuggers can show the address.
        create_basic_type(
            cx,
            "<recur_type>",
            cx.tcx.data_layout.pointer_size(),
            dwarf_const::DW_ATE_unsigned,
        )
    })
}

fn hex_encode(data: &[u8]) -> String {
    let mut hex_string = String::with_capacity(data.len() * 2);
    for byte in data.iter() {
        write!(&mut hex_string, "{byte:02x}").unwrap();
    }
    hex_string
}

pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile {
    let cache_key = Some((source_file.stable_id, source_file.src_hash));
    return debug_context(cx)
        .created_files
        .borrow_mut()
        .entry(cache_key)
        .or_insert_with(|| alloc_new_file_metadata(cx, source_file));

    #[instrument(skip(cx, source_file), level = "debug")]
    fn alloc_new_file_metadata<'ll>(
        cx: &CodegenCx<'ll, '_>,
        source_file: &SourceFile,
    ) -> &'ll DIFile {
        debug!(?source_file.name);

        let (directory, file_name) = match &source_file.name {
            FileName::Real(filename) => {
                let (working_directory, embeddable_name) =
                    filename.embeddable_name(RemapPathScopeComponents::DEBUGINFO);

                debug!(?working_directory, ?embeddable_name);

                if let Ok(rel_path) = embeddable_name.strip_prefix(working_directory) {
                    // If the compiler's working directory (which also is the DW_AT_comp_dir of
                    // the compilation unit) is a prefix of the path we are about to emit, then
                    // only emit the part relative to the working directory. Because of path
                    // remapping we sometimes see strange things here: `abs_path` might
                    // actually look like a relative path (e.g.
                    // `<crate-name-and-version>/src/lib.rs`), so if we emit it without taking
                    // the working directory into account, downstream tooling will interpret it
                    // as `<working-directory>/<crate-name-and-version>/src/lib.rs`, which
                    // makes no sense. Usually in such cases the working directory will also be
                    // remapped to `<crate-name-and-version>` or some other prefix of the path
                    // we are remapping, so we end up with
                    // `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
                    //
                    // By moving the working directory portion into the `directory` part of the
                    // DIFile, we allow LLVM to emit just the relative path for DWARF, while
                    // still emitting the correct absolute path for CodeView.
                    (working_directory.to_string_lossy(), rel_path.to_string_lossy().into_owned())
                } else {
                    ("".into(), embeddable_name.to_string_lossy().into_owned())
                }
            }
            other => {
                debug!(?other);
                ("".into(), other.display(RemapPathScopeComponents::DEBUGINFO).to_string())
            }
        };

        let hash_kind = match source_file.src_hash.kind {
            rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5,
            rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1,
            rustc_span::SourceFileHashAlgorithm::Sha256 => llvm::ChecksumKind::SHA256,
            rustc_span::SourceFileHashAlgorithm::Blake3 => llvm::ChecksumKind::None,
        };
        let hash_value = hex_encode(source_file.src_hash.hash_bytes());

        let mut source = None;
        let external_src;
        if cx.sess().opts.unstable_opts.embed_source {
            source = source_file.src.as_deref().map(String::as_str);
            if source.is_none() {
                cx.tcx.sess.source_map().ensure_source_file_source_present(source_file);
                external_src = source_file.external_src.read();
                source = external_src.get_source();
            }
        }

        create_file(DIB(cx), &file_name, &directory, &hash_value, hash_kind, source)
    }
}

fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
    debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| {
        create_file(DIB(cx), "<unknown>", "", "", llvm::ChecksumKind::None, None)
    })
}

fn create_file<'ll>(
    builder: &DIBuilder<'ll>,
    file_name: &str,
    directory: &str,
    hash_value: &str,
    hash_kind: llvm::ChecksumKind,
    source: Option<&str>,
) -> &'ll DIFile {
    unsafe {
        llvm::LLVMRustDIBuilderCreateFile(
            builder,
            file_name.as_c_char_ptr(),
            file_name.len(),
            directory.as_c_char_ptr(),
            directory.len(),
            hash_kind,
            hash_value.as_c_char_ptr(),
            hash_value.len(),
            source.map_or(ptr::null(), |x| x.as_c_char_ptr()),
            source.map_or(0, |x| x.len()),
        )
    }
}

trait MsvcBasicName {
    fn msvc_basic_name(self) -> &'static str;
}

impl MsvcBasicName for ty::IntTy {
    fn msvc_basic_name(self) -> &'static str {
        match self {
            ty::IntTy::Isize => "ptrdiff_t",
            ty::IntTy::I8 => "__int8",
            ty::IntTy::I16 => "__int16",
            ty::IntTy::I32 => "__int32",
            ty::IntTy::I64 => "__int64",
            ty::IntTy::I128 => "__int128",
        }
    }
}

impl MsvcBasicName for ty::UintTy {
    fn msvc_basic_name(self) -> &'static str {
        match self {
            ty::UintTy::Usize => "size_t",
            ty::UintTy::U8 => "unsigned __int8",
            ty::UintTy::U16 => "unsigned __int16",
            ty::UintTy::U32 => "unsigned __int32",
            ty::UintTy::U64 => "unsigned __int64",
            ty::UintTy::U128 => "unsigned __int128",
        }
    }
}

impl MsvcBasicName for ty::FloatTy {
    fn msvc_basic_name(self) -> &'static str {
        // FIXME(f128): `f128` has no MSVC representation. We could improve the debuginfo.
        // See: <https://github.com/rust-lang/rust/issues/121837>
        match self {
            ty::FloatTy::F16 => {
                bug!("`f16` should have been handled in `build_basic_type_di_node`")
            }
            ty::FloatTy::F32 => "float",
            ty::FloatTy::F64 => "double",
            ty::FloatTy::F128 => "fp128",
        }
    }
}

fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreationResult<'ll> {
    // MSVC has no native support for `f16`. Instead, emit `struct f16 { bits: u16 }` to allow the
    // `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`.
    let float_ty = cx.tcx.types.f16;
    let bits_ty = cx.tcx.types.u16;
    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
        match float_ty.kind() {
            ty::Adt(def, _) => Some(file_metadata_from_def_id(cx, Some(def.did()))),
            _ => None,
        }
    } else {
        None
    };
    type_map::build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Struct,
            UniqueTypeId::for_ty(cx.tcx, float_ty),
            "f16",
            def_location,
            cx.size_and_align_of(float_ty),
            NO_SCOPE_METADATA,
            DIFlags::FlagZero,
        ),
        // Fields:
        |cx, float_di_node| {
            let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
                match bits_ty.kind() {
                    ty::Adt(def, _) => Some(def.did()),
                    _ => None,
                }
            } else {
                None
            };
            smallvec![build_field_di_node(
                cx,
                float_di_node,
                "bits",
                cx.layout_of(bits_ty),
                Size::ZERO,
                DIFlags::FlagZero,
                type_di_node(cx, bits_ty),
                def_id,
            )]
        },
        NO_GENERICS,
    )
}

fn build_basic_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    t: Ty<'tcx>,
) -> DINodeCreationResult<'ll> {
    debug!("build_basic_type_di_node: {:?}", t);

    // When targeting MSVC, emit MSVC style type names for compatibility with
    // .natvis visualizers (and perhaps other existing native debuggers?)
    let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx);

    use dwarf_const::{DW_ATE_UTF, DW_ATE_boolean, DW_ATE_float, DW_ATE_signed, DW_ATE_unsigned};

    let (name, encoding) = match t.kind() {
        ty::Never => ("!", DW_ATE_unsigned),
        ty::Tuple(elements) if elements.is_empty() => {
            if cpp_like_debuginfo {
                return build_tuple_type_di_node(cx, UniqueTypeId::for_ty(cx.tcx, t));
            } else {
                ("()", DW_ATE_unsigned)
            }
        }
        ty::Bool => ("bool", DW_ATE_boolean),
        ty::Char => ("char", DW_ATE_UTF),
        ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
        ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
        ty::Float(ty::FloatTy::F16) if cpp_like_debuginfo => {
            return build_cpp_f16_di_node(cx);
        }
        ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float),
        ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
        ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),
        ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float),
        _ => bug!("debuginfo::build_basic_type_di_node - `t` is invalid type"),
    };

    let ty_di_node = create_basic_type(cx, name, cx.size_of(t), encoding);

    if !cpp_like_debuginfo {
        return DINodeCreationResult::new(ty_di_node, false);
    }

    let typedef_name = match t.kind() {
        ty::Int(int_ty) => int_ty.name_str(),
        ty::Uint(uint_ty) => uint_ty.name_str(),
        ty::Float(float_ty) => float_ty.name_str(),
        _ => return DINodeCreationResult::new(ty_di_node, false),
    };

    let typedef_di_node = unsafe {
        llvm::LLVMDIBuilderCreateTypedef(
            DIB(cx),
            ty_di_node,
            typedef_name.as_ptr(),
            typedef_name.len(),
            unknown_file_metadata(cx),
            0,    // (no line number)
            None, // (no scope)
            0u32, // (no alignment specified)
        )
    };

    DINodeCreationResult::new(typedef_di_node, false)
}

fn create_basic_type<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    name: &str,
    size: Size,
    encoding: u32,
) -> &'ll DIBasicType {
    unsafe {
        llvm::LLVMDIBuilderCreateBasicType(
            DIB(cx),
            name.as_ptr(),
            name.len(),
            size.bits(),
            encoding,
            DIFlags::FlagZero,
        )
    }
}

fn build_foreign_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    t: Ty<'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
) -> DINodeCreationResult<'ll> {
    debug!("build_foreign_type_di_node: {:?}", t);

    let &ty::Foreign(def_id) = unique_type_id.expect_ty().kind() else {
        bug!(
            "build_foreign_type_di_node() called with unexpected type: {:?}",
            unique_type_id.expect_ty()
        );
    };

    build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Struct,
            unique_type_id,
            &compute_debuginfo_type_name(cx.tcx, t, false),
            None,
            cx.size_and_align_of(t),
            Some(get_namespace_for_item(cx, def_id)),
            DIFlags::FlagZero,
        ),
        |_, _| smallvec![],
        NO_GENERICS,
    )
}

pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
    tcx: TyCtxt<'tcx>,
    codegen_unit_name: &str,
    debug_context: &CodegenUnitDebugContext<'ll, 'tcx>,
) -> &'ll DIDescriptor {
    let mut name_in_debuginfo = tcx
        .sess
        .local_crate_source_file()
        .map(|src| src.path(RemapPathScopeComponents::DEBUGINFO).to_path_buf())
        .unwrap_or_else(|| PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()));

    // To avoid breaking split DWARF, we need to ensure that each codegen unit
    // has a unique `DW_AT_name`. This is because there's a remote chance that
    // different codegen units for the same module will have entirely
    // identical DWARF entries for the purpose of the DWO ID, which would
    // violate Appendix F ("Split Dwarf Object Files") of the DWARF 5
    // specification. LLVM uses the algorithm specified in section 7.32 "Type
    // Signature Computation" to compute the DWO ID, which does not include
    // any fields that would distinguish compilation units. So we must embed
    // the codegen unit name into the `DW_AT_name`. (Issue #88521.)
    //
    // Additionally, the OSX linker has an idiosyncrasy where it will ignore
    // some debuginfo if multiple object files with the same `DW_AT_name` are
    // linked together.
    //
    // As a workaround for these two issues, we generate unique names for each
    // object file. Those do not correspond to an actual source file but that
    // is harmless.
    name_in_debuginfo.push("@");
    name_in_debuginfo.push(codegen_unit_name);

    debug!("build_compile_unit_di_node: {:?}", name_in_debuginfo);
    let rustc_producer = format!("rustc version {}", tcx.sess.cfg_version);
    // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
    let producer = format!("clang LLVM ({rustc_producer})");

    let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
    let work_dir = tcx.sess.psess.source_map().working_dir();
    let output_filenames = tcx.output_filenames(());
    let split_name = if tcx.sess.target_can_use_split_dwarf()
        && let Some(f) = output_filenames.split_dwarf_path(
            tcx.sess.split_debuginfo(),
            tcx.sess.opts.unstable_opts.split_dwarf_kind,
            codegen_unit_name,
        ) {
        // We get a path relative to the working directory from split_dwarf_path
        Some(tcx.sess.source_map().path_mapping().to_real_filename(work_dir, f))
    } else {
        None
    };
    let split_name = split_name
        .as_ref()
        .map(|f| f.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy())
        .unwrap_or_default();
    let work_dir = work_dir.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy();
    let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);

    let dwarf_version = tcx.sess.dwarf_version();
    let is_dwarf_kind =
        matches!(tcx.sess.target.debuginfo_kind, DebuginfoKind::Dwarf | DebuginfoKind::DwarfDsym);
    // Don't emit `.debug_pubnames` and `.debug_pubtypes` on DWARFv4 or lower.
    let debug_name_table_kind = if is_dwarf_kind && dwarf_version <= 4 {
        DebugNameTableKind::None
    } else {
        DebugNameTableKind::Default
    };

    unsafe {
        let compile_unit_file = create_file(
            debug_context.builder.as_ref(),
            &name_in_debuginfo,
            &work_dir,
            "",
            llvm::ChecksumKind::None,
            None,
        );

        let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
            debug_context.builder.as_ref(),
            dwarf_const::DW_LANG_Rust,
            compile_unit_file,
            producer.as_c_char_ptr(),
            producer.len(),
            tcx.sess.opts.optimize != config::OptLevel::No,
            c"".as_ptr(),
            0,
            // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead
            // put the path supplied to `MCSplitDwarfFile` into the debug info of the final
            // output(s).
            split_name.as_c_char_ptr(),
            split_name.len(),
            kind,
            0,
            tcx.sess.opts.unstable_opts.split_dwarf_inlining,
            debug_name_table_kind,
        );

        return unit_metadata;
    };
}

/// Creates a `DW_TAG_member` entry inside the DIE represented by the given `type_di_node`.
fn build_field_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    owner: &'ll DIScope,
    name: &str,
    layout: TyAndLayout<'tcx>,
    offset: Size,
    flags: DIFlags,
    type_di_node: &'ll DIType,
    def_id: Option<DefId>,
) -> &'ll DIType {
    let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers
    {
        file_metadata_from_def_id(cx, def_id)
    } else {
        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
    };
    create_member_type(
        cx,
        owner,
        name,
        file_metadata,
        line_number,
        layout,
        offset,
        flags,
        type_di_node,
    )
}

fn create_member_type<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    owner: &'ll DIScope,
    name: &str,
    file_metadata: &'ll DIType,
    line_number: u32,
    layout: TyAndLayout<'tcx>,
    offset: Size,
    flags: DIFlags,
    type_di_node: &'ll DIType,
) -> &'ll DIType {
    unsafe {
        llvm::LLVMDIBuilderCreateMemberType(
            DIB(cx),
            owner,
            name.as_ptr(),
            name.len(),
            file_metadata,
            line_number,
            layout.size.bits(),
            layout.align.bits() as u32,
            offset.bits(),
            flags,
            type_di_node,
        )
    }
}

/// Returns the `DIFlags` corresponding to the visibility of the item identified by `did`.
///
/// `DIFlags::Flag{Public,Protected,Private}` correspond to `DW_AT_accessibility`
/// (public/protected/private) aren't exactly right for Rust, but neither is `DW_AT_visibility`
/// (local/exported/qualified), and there's no way to set `DW_AT_visibility` in LLVM's API.
fn visibility_di_flags<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    did: DefId,
    type_did: DefId,
) -> DIFlags {
    let parent_did = cx.tcx.parent(type_did);
    let visibility = cx.tcx.visibility(did);
    match visibility {
        Visibility::Public => DIFlags::FlagPublic,
        // Private fields have a restricted visibility of the module containing the type.
        Visibility::Restricted(did) if did.to_def_id() == parent_did => DIFlags::FlagPrivate,
        // `pub(crate)`/`pub(super)` visibilities are any other restricted visibility.
        Visibility::Restricted(..) => DIFlags::FlagProtected,
    }
}

/// Creates the debuginfo node for a Rust struct type. Maybe be a regular struct or a tuple-struct.
fn build_struct_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
    span: Span,
) -> DINodeCreationResult<'ll> {
    let struct_type = unique_type_id.expect_ty();

    let ty::Adt(adt_def, _) = struct_type.kind() else {
        bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
    };
    assert!(adt_def.is_struct());
    let containing_scope = get_namespace_for_item(cx, adt_def.did());
    let struct_type_and_layout = cx.spanned_layout_of(struct_type, span);
    let variant_def = adt_def.non_enum_variant();
    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
        Some(file_metadata_from_def_id(cx, Some(adt_def.did())))
    } else {
        None
    };
    let name = compute_debuginfo_type_name(cx.tcx, struct_type, false);

    if struct_type.is_scalable_vector() {
        let parts = struct_type.scalable_vector_parts(cx.tcx).unwrap();
        return build_scalable_vector_di_node(
            cx,
            unique_type_id,
            name,
            *adt_def,
            parts,
            struct_type_and_layout.layout,
            def_location,
            containing_scope,
        );
    }

    type_map::build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Struct,
            unique_type_id,
            &name,
            def_location,
            size_and_align_of(struct_type_and_layout),
            Some(containing_scope),
            visibility_di_flags(cx, adt_def.did(), adt_def.did()),
        ),
        // Fields:
        |cx, owner| {
            variant_def
                .fields
                .iter()
                .enumerate()
                .map(|(i, f)| {
                    let field_name = if variant_def.ctor_kind() == Some(CtorKind::Fn) {
                        // This is a tuple struct
                        tuple_field_name(i)
                    } else {
                        // This is struct with named fields
                        Cow::Borrowed(f.name.as_str())
                    };
                    let field_layout = struct_type_and_layout.field(cx, i);
                    let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
                        Some(f.did)
                    } else {
                        None
                    };
                    build_field_di_node(
                        cx,
                        owner,
                        &field_name[..],
                        field_layout,
                        struct_type_and_layout.fields.offset(i),
                        visibility_di_flags(cx, f.did, adt_def.did()),
                        type_di_node(cx, field_layout.ty),
                        def_id,
                    )
                })
                .collect()
        },
        |cx| build_generic_type_param_di_nodes(cx, struct_type),
    )
}

/// Generate debuginfo for a `#[rustc_scalable_vector]` type.
///
/// Debuginfo for a scalable vector uses a derived type based on a composite type. The composite
/// type has the  `DIFlagVector` flag set and is based on the element type of the scalable vector.
/// The composite type has a subrange from 0 to an expression that calculates the number of
/// elements in the vector.
///
/// ```text,ignore
/// !1 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint16_t", ..., baseType: !2, ...)
/// !2 = !DICompositeType(tag: DW_TAG_array_type, baseType: !3, ..., flags: DIFlagVector, elements: !4)
/// !3 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed)
/// !4 = !{!5}
/// !5 = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
/// ```
///
/// See the `CodegenType::CreateType(const BuiltinType *BT)` implementation in Clang for how this
/// is generated for C and C++.
fn build_scalable_vector_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
    name: String,
    adt_def: AdtDef<'tcx>,
    (element_count, element_ty, number_of_vectors): (u16, Ty<'tcx>, NumScalableVectors),
    layout: Layout<'tcx>,
    def_location: Option<DefinitionLocation<'ll>>,
    containing_scope: &'ll DIScope,
) -> DINodeCreationResult<'ll> {
    use dwarf_const::{DW_OP_bregx, DW_OP_constu, DW_OP_minus, DW_OP_mul};
    assert!(adt_def.repr().scalable());
    // This logic is specific to AArch64 for the moment, but can be extended for other architectures
    // later.
    assert_matches!(cx.tcx.sess.target.arch, Arch::AArch64);

    let (file_metadata, line_number) = if let Some(def_location) = def_location {
        (def_location.0, def_location.1)
    } else {
        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
    };

    let (bitstride, element_di_node) = if element_ty.is_bool() {
        (Some(llvm::LLVMValueAsMetadata(cx.const_i64(1))), type_di_node(cx, cx.tcx.types.u8))
    } else {
        (None, type_di_node(cx, element_ty))
    };

    let number_of_elements: u64 = (element_count as u64) * (number_of_vectors.0 as u64);
    let number_of_elements_per_vg = number_of_elements / 2;
    let mut expr = smallvec::SmallVec::<[u64; 9]>::new();
    // `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1`
    expr.push(DW_OP_constu); // Push a constant onto the stack
    expr.push(number_of_elements_per_vg);
    expr.push(DW_OP_bregx); // Push the value of a register + offset on to the stack
    expr.push(/* AArch64::VG */ 46u64);
    expr.push(0u64);
    expr.push(DW_OP_mul); // Multiply top two values on stack
    expr.push(DW_OP_constu); // Push a constant onto the stack
    expr.push(1u64);
    expr.push(DW_OP_minus); // Subtract top two values on stack

    let di_builder = DIB(cx);
    let metadata = unsafe {
        let upper = llvm::LLVMDIBuilderCreateExpression(di_builder, expr.as_ptr(), expr.len());
        let subrange = llvm::LLVMRustDIGetOrCreateSubrange(
            di_builder,
            /* CountNode */ None,
            llvm::LLVMValueAsMetadata(cx.const_i64(0)),
            upper,
            /* Stride */ None,
        );
        let subscripts = create_DIArray(di_builder, &[Some(subrange)]);
        let vector_ty = llvm::LLVMRustDICreateVectorType(
            di_builder,
            /* Size */ 0,
            layout.align.bits() as u32,
            element_di_node,
            subscripts,
            bitstride,
        );
        llvm::LLVMDIBuilderCreateTypedef(
            di_builder,
            vector_ty,
            name.as_ptr(),
            name.len(),
            file_metadata,
            line_number,
            Some(containing_scope),
            layout.align.bits() as u32,
        )
    };

    debug_context(cx).type_map.insert(unique_type_id, metadata);
    DINodeCreationResult { di_node: metadata, already_stored_in_typemap: true }
}

//=-----------------------------------------------------------------------------
// Tuples
//=-----------------------------------------------------------------------------

/// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or coroutine.
/// For a coroutine, this will handle upvars shared by all states.
fn build_upvar_field_di_nodes<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    closure_or_coroutine_ty: Ty<'tcx>,
    closure_or_coroutine_di_node: &'ll DIType,
) -> SmallVec<&'ll DIType> {
    let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() {
        ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().upvar_tys()),
        ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()),
        ty::CoroutineClosure(def_id, args) => (def_id, args.as_coroutine_closure().upvar_tys()),
        _ => {
            bug!(
                "build_upvar_field_di_nodes() called with non-closure-or-coroutine-type: {:?}",
                closure_or_coroutine_ty
            )
        }
    };

    for ty in up_var_tys.iter() {
        cx.tcx.assert_fully_normalized(cx.typing_env(), ty);
    }

    let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
    let layout = cx.layout_of(closure_or_coroutine_ty);

    up_var_tys
        .into_iter()
        .zip(capture_names.iter())
        .enumerate()
        .map(|(index, (up_var_ty, capture_name))| {
            build_field_di_node(
                cx,
                closure_or_coroutine_di_node,
                capture_name.as_str(),
                cx.layout_of(up_var_ty),
                layout.fields.offset(index),
                DIFlags::FlagZero,
                type_di_node(cx, up_var_ty),
                None,
            )
        })
        .collect()
}

/// Builds the DW_TAG_structure_type debuginfo node for a Rust tuple type.
fn build_tuple_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
) -> DINodeCreationResult<'ll> {
    let tuple_type = unique_type_id.expect_ty();
    let &ty::Tuple(component_types) = tuple_type.kind() else {
        bug!("build_tuple_type_di_node() called with non-tuple-type: {:?}", tuple_type)
    };

    let tuple_type_and_layout = cx.layout_of(tuple_type);
    let type_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);

    type_map::build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Struct,
            unique_type_id,
            &type_name,
            None,
            size_and_align_of(tuple_type_and_layout),
            NO_SCOPE_METADATA,
            DIFlags::FlagZero,
        ),
        // Fields:
        |cx, tuple_di_node| {
            component_types
                .into_iter()
                .enumerate()
                .map(|(index, component_type)| {
                    build_field_di_node(
                        cx,
                        tuple_di_node,
                        &tuple_field_name(index),
                        cx.layout_of(component_type),
                        tuple_type_and_layout.fields.offset(index),
                        DIFlags::FlagZero,
                        type_di_node(cx, component_type),
                        None,
                    )
                })
                .collect()
        },
        NO_GENERICS,
    )
}

/// Builds the debuginfo node for a closure environment.
fn build_closure_env_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
) -> DINodeCreationResult<'ll> {
    let closure_env_type = unique_type_id.expect_ty();
    let &(ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _)) = closure_env_type.kind()
    else {
        bug!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type)
    };
    let containing_scope = get_namespace_for_item(cx, def_id);
    let type_name = compute_debuginfo_type_name(cx.tcx, closure_env_type, false);

    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
        Some(file_metadata_from_def_id(cx, Some(def_id)))
    } else {
        None
    };

    type_map::build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Struct,
            unique_type_id,
            &type_name,
            def_location,
            cx.size_and_align_of(closure_env_type),
            Some(containing_scope),
            DIFlags::FlagZero,
        ),
        // Fields:
        |cx, owner| build_upvar_field_di_nodes(cx, closure_env_type, owner),
        NO_GENERICS,
    )
}

/// Build the debuginfo node for a Rust `union` type.
fn build_union_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
    span: Span,
) -> DINodeCreationResult<'ll> {
    let union_type = unique_type_id.expect_ty();
    let (union_def_id, variant_def) = match union_type.kind() {
        ty::Adt(def, _) => (def.did(), def.non_enum_variant()),
        _ => bug!("build_union_type_di_node on a non-ADT"),
    };
    let containing_scope = get_namespace_for_item(cx, union_def_id);
    let union_ty_and_layout = cx.spanned_layout_of(union_type, span);
    let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
        Some(file_metadata_from_def_id(cx, Some(union_def_id)))
    } else {
        None
    };

    type_map::build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Union,
            unique_type_id,
            &type_name,
            def_location,
            size_and_align_of(union_ty_and_layout),
            Some(containing_scope),
            DIFlags::FlagZero,
        ),
        // Fields:
        |cx, owner| {
            variant_def
                .fields
                .iter()
                .enumerate()
                .map(|(i, f)| {
                    let field_layout = union_ty_and_layout.field(cx, i);
                    let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
                        Some(f.did)
                    } else {
                        None
                    };
                    build_field_di_node(
                        cx,
                        owner,
                        f.name.as_str(),
                        field_layout,
                        Size::ZERO,
                        DIFlags::FlagZero,
                        type_di_node(cx, field_layout.ty),
                        def_id,
                    )
                })
                .collect()
        },
        // Generics:
        |cx| build_generic_type_param_di_nodes(cx, union_type),
    )
}

/// Computes the type parameters for a type, if any, for the given metadata.
fn build_generic_type_param_di_nodes<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    ty: Ty<'tcx>,
) -> SmallVec<Option<&'ll DIType>> {
    if let ty::Adt(def, args) = *ty.kind() {
        if args.types().next().is_some() {
            let generics = cx.tcx.generics_of(def.did());
            let names = get_parameter_names(cx, generics);
            let template_params: SmallVec<_> = iter::zip(args, names)
                .filter_map(|(kind, name)| {
                    kind.as_type().map(|ty| {
                        let actual_type = cx
                            .tcx
                            .normalize_erasing_regions(cx.typing_env(), Unnormalized::new_wip(ty));
                        let actual_type_di_node = type_di_node(cx, actual_type);
                        Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node))
                    })
                })
                .collect();

            return template_params;
        }
    }

    return smallvec![];

    fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
        let mut names = generics
            .parent
            .map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
        names.extend(generics.own_params.iter().map(|param| param.name));
        names
    }
}

/// Creates debug information for the given global variable.
///
/// Adds the created debuginfo nodes directly to the crate's IR.
pub(crate) fn build_global_var_di_node<'ll>(
    cx: &CodegenCx<'ll, '_>,
    def_id: DefId,
    global: &'ll Value,
) {
    if cx.dbg_cx.is_none() {
        return;
    }

    // Only create type information if full debuginfo is enabled
    if cx.sess().opts.debuginfo != DebugInfo::Full {
        return;
    }

    let tcx = cx.tcx;

    // We may want to remove the namespace scope if we're in an extern block (see
    // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
    let var_scope = get_namespace_for_item(cx, def_id);
    let (file_metadata, line_number) = file_metadata_from_def_id(cx, Some(def_id));

    let is_local_to_unit = is_node_local_to_unit(cx, def_id);

    let DefKind::Static { nested, .. } = cx.tcx.def_kind(def_id) else { bug!() };
    if nested {
        return;
    }
    let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, cx.typing_env());
    let type_di_node = type_di_node(cx, variable_type);
    let var_name = tcx.item_name(def_id);
    let var_name = var_name.as_str();
    let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name;
    // When empty, linkage_name field is omitted,
    // which is what we want for no_mangle statics
    let linkage_name = if var_name == linkage_name { "" } else { linkage_name };

    let global_align = cx.align_of(variable_type);

    DIB(cx).create_static_variable(
        Some(var_scope),
        var_name,
        linkage_name,
        file_metadata,
        line_number,
        type_di_node,
        is_local_to_unit,
        global, // (value)
        None,   // (decl)
        Some(global_align),
    );
}

/// Generates LLVM debuginfo for a vtable.
///
/// The vtable type looks like a struct with a field for each function pointer and super-trait
/// pointer it contains (plus the `size` and `align` fields).
///
/// Except for `size`, `align`, and `drop_in_place`, the field names don't try to mirror
/// the name of the method they implement. This can be implemented in the future once there
/// is a proper disambiguation scheme for dealing with methods from different traits that have
/// the same name.
fn build_vtable_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    ty: Ty<'tcx>,
    poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
) -> &'ll DIType {
    let tcx = cx.tcx;

    let vtable_entries = if let Some(poly_trait_ref) = poly_trait_ref {
        let trait_ref = poly_trait_ref.with_self_ty(tcx, ty);
        let trait_ref = tcx.erase_and_anonymize_regions(trait_ref);

        tcx.vtable_entries(trait_ref)
    } else {
        TyCtxt::COMMON_VTABLE_ENTRIES
    };

    // All function pointers are described as opaque pointers. This could be improved in the future
    // by describing them as actual function pointers.
    let void_pointer_ty = Ty::new_imm_ptr(tcx, tcx.types.unit);
    let void_pointer_type_di_node = type_di_node(cx, void_pointer_ty);
    let usize_di_node = type_di_node(cx, tcx.types.usize);
    let pointer_layout = cx.layout_of(void_pointer_ty);
    let pointer_size = pointer_layout.size;
    let pointer_align = pointer_layout.align.abi;
    // If `usize` is not pointer-sized and -aligned then the size and alignment computations
    // for the vtable as a whole would be wrong. Let's make sure this holds even on weird
    // platforms.
    assert_eq!(cx.size_and_align_of(tcx.types.usize), (pointer_size, pointer_align));

    let vtable_type_name =
        compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::Type);
    let unique_type_id = UniqueTypeId::for_vtable_ty(tcx, ty, poly_trait_ref);
    let size = pointer_size * vtable_entries.len() as u64;

    // This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate
    // the vtable to the type it is for.
    let vtable_holder = type_di_node(cx, ty);

    build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::VTableTy { vtable_holder },
            unique_type_id,
            &vtable_type_name,
            None,
            (size, pointer_align),
            NO_SCOPE_METADATA,
            DIFlags::FlagArtificial,
        ),
        |cx, vtable_type_di_node| {
            vtable_entries
                .iter()
                .enumerate()
                .filter_map(|(index, vtable_entry)| {
                    let (field_name, field_type_di_node) = match vtable_entry {
                        ty::VtblEntry::MetadataDropInPlace => {
                            ("drop_in_place".to_string(), void_pointer_type_di_node)
                        }
                        ty::VtblEntry::Method(_) => {
                            // Note: This code does not try to give a proper name to each method
                            //       because their might be multiple methods with the same name
                            //       (coming from different traits).
                            (format!("__method{index}"), void_pointer_type_di_node)
                        }
                        ty::VtblEntry::TraitVPtr(_) => {
                            (format!("__super_trait_ptr{index}"), void_pointer_type_di_node)
                        }
                        ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_di_node),
                        ty::VtblEntry::MetadataSize => ("size".to_string(), usize_di_node),
                        ty::VtblEntry::Vacant => return None,
                    };

                    let field_offset = pointer_size * index as u64;

                    Some(build_field_di_node(
                        cx,
                        vtable_type_di_node,
                        &field_name,
                        pointer_layout,
                        field_offset,
                        DIFlags::FlagZero,
                        field_type_di_node,
                        None,
                    ))
                })
                .collect()
        },
        NO_GENERICS,
    )
    .di_node
}

/// Creates the debuginfo node for `unsafe<'a> T` binder types.
///
/// We treat an unsafe binder like a struct with a single field named `inner`
/// rather than delegating to the inner type's DI node directly. This way the
/// debugger shows the binder's own type name, and the wrapped value is still
/// accessible through the `inner` field.
fn build_unsafe_binder_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    binder_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId<'tcx>,
) -> DINodeCreationResult<'ll> {
    let ty::UnsafeBinder(inner) = binder_type.kind() else {
        bug!(
            "Only ty::UnsafeBinder is valid for build_unsafe_binder_type_di_node. Found {:?} instead.",
            binder_type
        )
    };
    let inner_type = cx.tcx.instantiate_bound_regions_with_erased((*inner).into());
    let inner_type_di_node = type_di_node(cx, inner_type);

    let type_name = compute_debuginfo_type_name(cx.tcx, binder_type, true);
    type_map::build_type_with_children(
        cx,
        type_map::stub(
            cx,
            Stub::Struct,
            unique_type_id,
            &type_name,
            None,
            cx.size_and_align_of(binder_type),
            NO_SCOPE_METADATA,
            DIFlags::FlagZero,
        ),
        |cx, unsafe_binder_type_di_node| {
            let inner_layout = cx.layout_of(inner_type);
            smallvec![build_field_di_node(
                cx,
                unsafe_binder_type_di_node,
                "inner",
                inner_layout,
                Size::ZERO,
                DIFlags::FlagZero,
                inner_type_di_node,
                None,
            )]
        },
        NO_GENERICS,
    )
}

/// Get the global variable for the vtable.
///
/// When using global variables, we may have created an addrspacecast to get a pointer to the
/// default address space if global variables are created in a different address space.
/// For modifying the vtable, we need the real global variable. This function accepts either a
/// global variable (which is simply returned), or an addrspacecast constant expression.
/// If the given value is an addrspacecast, the cast is removed and the global variable behind
/// the cast is returned.
fn find_vtable_behind_cast<'ll>(vtable: &'ll Value) -> &'ll Value {
    // The vtable is a global variable, which may be behind an addrspacecast.
    unsafe {
        if let Some(c) = llvm::LLVMIsAConstantExpr(vtable) {
            if llvm::LLVMGetConstOpcode(c) == llvm::Opcode::AddrSpaceCast {
                return llvm::LLVMGetOperand(c, 0).unwrap();
            }
        }
    }
    vtable
}

pub(crate) fn apply_vcall_visibility_metadata<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    ty: Ty<'tcx>,
    trait_ref: Option<ExistentialTraitRef<'tcx>>,
    vtable: &'ll Value,
) {
    // FIXME(flip1995): The virtual function elimination optimization only works with full LTO in
    // LLVM at the moment.
    if !cx.sess().opts.unstable_opts.virtual_function_elimination || cx.sess().lto() != Lto::Fat {
        return;
    }

    enum VCallVisibility {
        Public = 0,
        LinkageUnit = 1,
        TranslationUnit = 2,
    }

    let Some(trait_ref) = trait_ref else { return };

    // Unwrap potential addrspacecast
    let vtable = find_vtable_behind_cast(vtable);
    let trait_ref_self = trait_ref.with_self_ty(cx.tcx, ty);
    let trait_def_id = trait_ref_self.def_id;
    let trait_vis = cx.tcx.visibility(trait_def_id);

    let cgus = cx.sess().codegen_units().as_usize();
    let single_cgu = cgus == 1;

    let lto = cx.sess().lto();

    // Since LLVM requires full LTO for the virtual function elimination optimization to apply,
    // only the `Lto::Fat` cases are relevant currently.
    let vcall_visibility = match (lto, trait_vis, single_cgu) {
        // If there is not LTO and the visibility in public, we have to assume that the vtable can
        // be seen from anywhere. With multiple CGUs, the vtable is quasi-public.
        (Lto::No | Lto::ThinLocal, Visibility::Public, _)
        | (Lto::No, Visibility::Restricted(_), false) => VCallVisibility::Public,
        // With LTO and a quasi-public visibility, the usages of the functions of the vtable are
        // all known by the `LinkageUnit`.
        // FIXME: LLVM only supports this optimization for `Lto::Fat` currently. Once it also
        // supports `Lto::Thin` the `VCallVisibility` may have to be adjusted for those.
        (Lto::Fat | Lto::Thin, Visibility::Public, _)
        | (Lto::ThinLocal | Lto::Thin | Lto::Fat, Visibility::Restricted(_), false) => {
            VCallVisibility::LinkageUnit
        }
        // If there is only one CGU, private vtables can only be seen by that CGU/translation unit
        // and therefore we know of all usages of functions in the vtable.
        (_, Visibility::Restricted(_), true) => VCallVisibility::TranslationUnit,
    };

    let trait_ref_typeid = typeid_for_trait_ref(cx.tcx, trait_ref);
    let typeid = cx.create_metadata(trait_ref_typeid.as_bytes());

    let type_ = [llvm::LLVMValueAsMetadata(cx.const_usize(0)), typeid];
    cx.global_add_metadata_node(vtable, llvm::MD_type, &type_);

    let vcall_visibility = [llvm::LLVMValueAsMetadata(cx.const_u64(vcall_visibility as u64))];
    cx.global_set_metadata_node(vtable, llvm::MD_vcall_visibility, &vcall_visibility);
}

/// Creates debug information for the given vtable, which is for the
/// given type.
///
/// Adds the created metadata nodes directly to the crate's IR.
pub(crate) fn create_vtable_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    ty: Ty<'tcx>,
    poly_trait_ref: Option<ty::ExistentialTraitRef<'tcx>>,
    vtable: &'ll Value,
) {
    if cx.dbg_cx.is_none() {
        return;
    }

    // Only create type information if full debuginfo is enabled
    if cx.sess().opts.debuginfo != DebugInfo::Full {
        return;
    }

    // Unwrap potential addrspacecast
    let vtable = find_vtable_behind_cast(vtable);

    // When full debuginfo is enabled, we want to try and prevent vtables from being
    // merged. Otherwise debuggers will have a hard time mapping from dyn pointer
    // to concrete type.
    llvm::set_unnamed_address(vtable, llvm::UnnamedAddr::No);

    let vtable_name =
        compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable);
    let vtable_type_di_node = build_vtable_type_di_node(cx, ty, poly_trait_ref);

    DIB(cx).create_static_variable(
        NO_SCOPE_METADATA,
        &vtable_name,
        "", // (linkage_name)
        unknown_file_metadata(cx),
        UNKNOWN_LINE_NUMBER,
        vtable_type_di_node,
        true,   // (is_local_to_unit)
        vtable, // (value)
        None,   // (decl)
        None::<Align>,
    );
}

/// Creates an "extension" of an existing `DIScope` into another file.
pub(crate) fn extend_scope_to_file<'ll>(
    cx: &CodegenCx<'ll, '_>,
    scope_metadata: &'ll DIScope,
    file: &SourceFile,
) -> &'ll DILexicalBlock {
    let file_metadata = file_metadata(cx, file);
    unsafe {
        llvm::LLVMDIBuilderCreateLexicalBlockFile(
            DIB(cx),
            scope_metadata,
            file_metadata,
            /* Discriminator (default) */ 0u32,
        )
    }
}

fn tuple_field_name(field_index: usize) -> Cow<'static, str> {
    const TUPLE_FIELD_NAMES: [&'static str; 16] = [
        "__0", "__1", "__2", "__3", "__4", "__5", "__6", "__7", "__8", "__9", "__10", "__11",
        "__12", "__13", "__14", "__15",
    ];
    TUPLE_FIELD_NAMES
        .get(field_index)
        .map(|s| Cow::from(*s))
        .unwrap_or_else(|| Cow::from(format!("__{field_index}")))
}

pub(crate) type DefinitionLocation<'ll> = (&'ll DIFile, c_uint);

pub(crate) fn file_metadata_from_def_id<'ll>(
    cx: &CodegenCx<'ll, '_>,
    def_id: Option<DefId>,
) -> DefinitionLocation<'ll> {
    if let Some(def_id) = def_id
        && let span = hygiene::walk_chain_collapsed(cx.tcx.def_span(def_id), DUMMY_SP)
        && !span.is_dummy()
    {
        let loc = cx.lookup_debug_loc(span.lo());
        (file_metadata(cx, &loc.file), loc.line)
    } else {
        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
    }
}
