Skip to main content

rustc_codegen_llvm/debuginfo/metadata/
type_map.rs

1use std::cell::RefCell;
2
3use libc::c_uint;
4use rustc_abi::{Align, Size, VariantIdx};
5use rustc_data_structures::fingerprint::Fingerprint;
6use rustc_data_structures::fx::FxHashMap;
7use rustc_data_structures::stable_hasher::{StableHash, StableHasher};
8use rustc_macros::StableHash;
9use rustc_middle::bug;
10use rustc_middle::ty::{self, ExistentialTraitRef, Ty, TyCtxt, Unnormalized};
11
12use super::{DefinitionLocation, SmallVec, UNKNOWN_LINE_NUMBER, unknown_file_metadata};
13use crate::common::CodegenCx;
14use crate::debuginfo::utils::{DIB, create_DIArray, debug_context};
15use crate::llvm;
16use crate::llvm::debuginfo::{DIFlags, DIScope, DIType};
17
18mod private {
19    use rustc_macros::StableHash;
20
21    // This type cannot be constructed outside of this module because
22    // it has a private field. We make use of this in order to prevent
23    // `UniqueTypeId` from being constructed directly, without asserting
24    // the preconditions.
25    #[derive(#[automatically_derived]
impl ::core::fmt::Debug for HiddenZst {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "HiddenZst")
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for HiddenZst {
    #[inline]
    fn clone(&self) -> HiddenZst { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for HiddenZst { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for HiddenZst {
    #[inline]
    fn eq(&self, other: &HiddenZst) -> bool { true }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for HiddenZst {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::hash::Hash for HiddenZst {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash, const _: () =
    {
        impl ::rustc_data_structures::stable_hasher::StableHash for HiddenZst
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self { HiddenZst => {} }
            }
        }
    };StableHash)]
26    pub(crate) struct HiddenZst;
27}
28
29/// A unique identifier for anything that we create a debuginfo node for.
30/// The types it contains are expected to already be normalized (which
31/// is asserted in the constructors).
32///
33/// Note that there are some things that only show up in debuginfo, like
34/// the separate type descriptions for each enum variant. These get an ID
35/// too because they have their own debuginfo node in LLVM IR.
36#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for UniqueTypeId<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            UniqueTypeId::Ty(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f, "Ty",
                    __self_0, &__self_1),
            UniqueTypeId::VariantPart(__self_0, __self_1) =>
                ::core::fmt::Formatter::debug_tuple_field2_finish(f,
                    "VariantPart", __self_0, &__self_1),
            UniqueTypeId::VariantStructType(__self_0, __self_1, __self_2) =>
                ::core::fmt::Formatter::debug_tuple_field3_finish(f,
                    "VariantStructType", __self_0, __self_1, &__self_2),
            UniqueTypeId::VariantStructTypeCppLikeWrapper(__self_0, __self_1,
                __self_2) =>
                ::core::fmt::Formatter::debug_tuple_field3_finish(f,
                    "VariantStructTypeCppLikeWrapper", __self_0, __self_1,
                    &__self_2),
            UniqueTypeId::VTableTy(__self_0, __self_1, __self_2) =>
                ::core::fmt::Formatter::debug_tuple_field3_finish(f,
                    "VTableTy", __self_0, __self_1, &__self_2),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for UniqueTypeId<'tcx> {
    #[inline]
    fn clone(&self) -> UniqueTypeId<'tcx> {
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<VariantIdx>;
        let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _:
                ::core::clone::AssertParamIsClone<Option<ExistentialTraitRef<'tcx>>>;
        let _: ::core::clone::AssertParamIsClone<private::HiddenZst>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for UniqueTypeId<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for UniqueTypeId<'tcx> {
    #[inline]
    fn eq(&self, other: &UniqueTypeId<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (UniqueTypeId::Ty(__self_0, __self_1),
                    UniqueTypeId::Ty(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (UniqueTypeId::VariantPart(__self_0, __self_1),
                    UniqueTypeId::VariantPart(__arg1_0, __arg1_1)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (UniqueTypeId::VariantStructType(__self_0, __self_1,
                    __self_2),
                    UniqueTypeId::VariantStructType(__arg1_0, __arg1_1,
                    __arg1_2)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                        __self_2 == __arg1_2,
                (UniqueTypeId::VariantStructTypeCppLikeWrapper(__self_0,
                    __self_1, __self_2),
                    UniqueTypeId::VariantStructTypeCppLikeWrapper(__arg1_0,
                    __arg1_1, __arg1_2)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                        __self_2 == __arg1_2,
                (UniqueTypeId::VTableTy(__self_0, __self_1, __self_2),
                    UniqueTypeId::VTableTy(__arg1_0, __arg1_1, __arg1_2)) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                        __self_2 == __arg1_2,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for UniqueTypeId<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<VariantIdx>;
        let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
        let _: ::core::cmp::AssertParamIsEq<Ty<'tcx>>;
        let _:
                ::core::cmp::AssertParamIsEq<Option<ExistentialTraitRef<'tcx>>>;
        let _: ::core::cmp::AssertParamIsEq<private::HiddenZst>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for UniqueTypeId<'tcx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            UniqueTypeId::Ty(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            UniqueTypeId::VariantPart(__self_0, __self_1) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state)
            }
            UniqueTypeId::VariantStructType(__self_0, __self_1, __self_2) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state)
            }
            UniqueTypeId::VariantStructTypeCppLikeWrapper(__self_0, __self_1,
                __self_2) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state)
            }
            UniqueTypeId::VTableTy(__self_0, __self_1, __self_2) => {
                ::core::hash::Hash::hash(__self_0, state);
                ::core::hash::Hash::hash(__self_1, state);
                ::core::hash::Hash::hash(__self_2, state)
            }
        }
    }
}Hash, const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hasher::StableHash for
            UniqueTypeId<'tcx> {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    UniqueTypeId::Ty(ref __binding_0, ref __binding_1) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    UniqueTypeId::VariantPart(ref __binding_0, ref __binding_1)
                        => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                    UniqueTypeId::VariantStructType(ref __binding_0,
                        ref __binding_1, ref __binding_2) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                    UniqueTypeId::VariantStructTypeCppLikeWrapper(ref __binding_0,
                        ref __binding_1, ref __binding_2) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                    UniqueTypeId::VTableTy(ref __binding_0, ref __binding_1,
                        ref __binding_2) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
37pub(super) enum UniqueTypeId<'tcx> {
38    /// The ID of a regular type as it shows up at the language level.
39    Ty(Ty<'tcx>, private::HiddenZst),
40    /// The ID for the single DW_TAG_variant_part nested inside the top-level
41    /// DW_TAG_structure_type that describes enums and coroutines.
42    VariantPart(Ty<'tcx>, private::HiddenZst),
43    /// The ID for the artificial struct type describing a single enum variant.
44    VariantStructType(Ty<'tcx>, VariantIdx, private::HiddenZst),
45    /// The ID for the additional wrapper struct type describing an enum variant in CPP-like mode.
46    VariantStructTypeCppLikeWrapper(Ty<'tcx>, VariantIdx, private::HiddenZst),
47    /// The ID of the artificial type we create for VTables.
48    VTableTy(Ty<'tcx>, Option<ExistentialTraitRef<'tcx>>, private::HiddenZst),
49}
50
51impl<'tcx> UniqueTypeId<'tcx> {
52    pub(crate) fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
53        match (&t,
        &tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
                Unnormalized::new_wip(t))) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(
54            t,
55            tcx.normalize_erasing_regions(
56                ty::TypingEnv::fully_monomorphized(),
57                Unnormalized::new_wip(t)
58            )
59        );
60        UniqueTypeId::Ty(t, private::HiddenZst)
61    }
62
63    pub(crate) fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
64        match (&enum_ty,
        &tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
                Unnormalized::new_wip(enum_ty))) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(
65            enum_ty,
66            tcx.normalize_erasing_regions(
67                ty::TypingEnv::fully_monomorphized(),
68                Unnormalized::new_wip(enum_ty)
69            )
70        );
71        UniqueTypeId::VariantPart(enum_ty, private::HiddenZst)
72    }
73
74    pub(crate) fn for_enum_variant_struct_type(
75        tcx: TyCtxt<'tcx>,
76        enum_ty: Ty<'tcx>,
77        variant_idx: VariantIdx,
78    ) -> Self {
79        match (&enum_ty,
        &tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
                Unnormalized::new_wip(enum_ty))) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(
80            enum_ty,
81            tcx.normalize_erasing_regions(
82                ty::TypingEnv::fully_monomorphized(),
83                Unnormalized::new_wip(enum_ty)
84            )
85        );
86        UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
87    }
88
89    pub(crate) fn for_enum_variant_struct_type_wrapper(
90        tcx: TyCtxt<'tcx>,
91        enum_ty: Ty<'tcx>,
92        variant_idx: VariantIdx,
93    ) -> Self {
94        match (&enum_ty,
        &tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
                Unnormalized::new_wip(enum_ty))) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(
95            enum_ty,
96            tcx.normalize_erasing_regions(
97                ty::TypingEnv::fully_monomorphized(),
98                Unnormalized::new_wip(enum_ty)
99            )
100        );
101        UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst)
102    }
103
104    pub(crate) fn for_vtable_ty(
105        tcx: TyCtxt<'tcx>,
106        self_type: Ty<'tcx>,
107        implemented_trait: Option<ExistentialTraitRef<'tcx>>,
108    ) -> Self {
109        match (&self_type,
        &tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
                Unnormalized::new_wip(self_type))) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(
110            self_type,
111            tcx.normalize_erasing_regions(
112                ty::TypingEnv::fully_monomorphized(),
113                Unnormalized::new_wip(self_type)
114            )
115        );
116        match (&implemented_trait,
        &tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(),
                Unnormalized::new_wip(implemented_trait))) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(
117            implemented_trait,
118            tcx.normalize_erasing_regions(
119                ty::TypingEnv::fully_monomorphized(),
120                Unnormalized::new_wip(implemented_trait)
121            )
122        );
123        UniqueTypeId::VTableTy(self_type, implemented_trait, private::HiddenZst)
124    }
125
126    /// Generates a string version of this [UniqueTypeId], which can be used as the `UniqueId`
127    /// argument of the various `LLVMRustDIBuilderCreate*Type()` methods.
128    ///
129    /// Right now this takes the form of a hex-encoded opaque hash value.
130    fn generate_unique_id_string(self, tcx: TyCtxt<'tcx>) -> String {
131        let mut hasher = StableHasher::new();
132        tcx.with_stable_hashing_context(|mut hcx| {
133            hcx.while_hashing_spans(false, |hcx| self.stable_hash(hcx, &mut hasher))
134        });
135        hasher.finish::<Fingerprint>().to_hex()
136    }
137
138    pub(crate) fn expect_ty(self) -> Ty<'tcx> {
139        match self {
140            UniqueTypeId::Ty(ty, _) => ty,
141            _ => ::rustc_middle::util::bug::bug_fmt(format_args!("Expected `UniqueTypeId::Ty` but found `{0:?}`",
        self))bug!("Expected `UniqueTypeId::Ty` but found `{:?}`", self),
142        }
143    }
144}
145
146/// The `TypeMap` is where the debug context holds the type metadata nodes
147/// created so far. The debuginfo nodes are identified by `UniqueTypeId`.
148#[derive(#[automatically_derived]
impl<'ll, 'tcx> ::core::default::Default for TypeMap<'ll, 'tcx> {
    #[inline]
    fn default() -> TypeMap<'ll, 'tcx> {
        TypeMap { unique_id_to_di_node: ::core::default::Default::default() }
    }
}Default)]
149pub(crate) struct TypeMap<'ll, 'tcx> {
150    pub(super) unique_id_to_di_node: RefCell<FxHashMap<UniqueTypeId<'tcx>, &'ll DIType>>,
151}
152
153impl<'ll, 'tcx> TypeMap<'ll, 'tcx> {
154    /// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will
155    /// fail if the mapping already exists.
156    pub(super) fn insert(&self, unique_type_id: UniqueTypeId<'tcx>, metadata: &'ll DIType) {
157        if self.unique_id_to_di_node.borrow_mut().insert(unique_type_id, metadata).is_some() {
158            ::rustc_middle::util::bug::bug_fmt(format_args!("type metadata for unique ID \'{0:?}\' is already in the `TypeMap`!",
        unique_type_id));bug!("type metadata for unique ID '{:?}' is already in the `TypeMap`!", unique_type_id);
159        }
160    }
161
162    pub(super) fn di_node_for_unique_id(
163        &self,
164        unique_type_id: UniqueTypeId<'tcx>,
165    ) -> Option<&'ll DIType> {
166        self.unique_id_to_di_node.borrow().get(&unique_type_id).cloned()
167    }
168}
169
170pub(crate) struct DINodeCreationResult<'ll> {
171    pub di_node: &'ll DIType,
172    pub already_stored_in_typemap: bool,
173}
174
175impl<'ll> DINodeCreationResult<'ll> {
176    pub(crate) fn new(di_node: &'ll DIType, already_stored_in_typemap: bool) -> Self {
177        DINodeCreationResult { di_node, already_stored_in_typemap }
178    }
179}
180
181#[derive(#[automatically_derived]
impl<'ll> ::core::fmt::Debug for Stub<'ll> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Stub::Struct => ::core::fmt::Formatter::write_str(f, "Struct"),
            Stub::Union => ::core::fmt::Formatter::write_str(f, "Union"),
            Stub::VTableTy { vtable_holder: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "VTableTy", "vtable_holder", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'ll> ::core::marker::Copy for Stub<'ll> { }Copy, #[automatically_derived]
impl<'ll> ::core::clone::Clone for Stub<'ll> {
    #[inline]
    fn clone(&self) -> Stub<'ll> {
        let _: ::core::clone::AssertParamIsClone<&'ll DIType>;
        *self
    }
}Clone, #[automatically_derived]
impl<'ll> ::core::cmp::Eq for Stub<'ll> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<&'ll DIType>;
    }
}Eq, #[automatically_derived]
impl<'ll> ::core::cmp::PartialEq for Stub<'ll> {
    #[inline]
    fn eq(&self, other: &Stub<'ll>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Stub::VTableTy { vtable_holder: __self_0 }, Stub::VTableTy {
                    vtable_holder: __arg1_0 }) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq)]
182pub(crate) enum Stub<'ll> {
183    Struct,
184    Union,
185    VTableTy { vtable_holder: &'ll DIType },
186}
187
188pub(crate) struct StubInfo<'ll, 'tcx> {
189    metadata: &'ll DIType,
190    unique_type_id: UniqueTypeId<'tcx>,
191}
192
193impl<'ll, 'tcx> StubInfo<'ll, 'tcx> {
194    pub(super) fn new(
195        cx: &CodegenCx<'ll, 'tcx>,
196        unique_type_id: UniqueTypeId<'tcx>,
197        build: impl FnOnce(&CodegenCx<'ll, 'tcx>, /* unique_type_id_str: */ &str) -> &'ll DIType,
198    ) -> StubInfo<'ll, 'tcx> {
199        let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
200        let di_node = build(cx, &unique_type_id_str);
201        StubInfo { metadata: di_node, unique_type_id }
202    }
203}
204
205/// Create a stub debuginfo node onto which fields and nested types can be attached.
206pub(super) fn stub<'ll, 'tcx>(
207    cx: &CodegenCx<'ll, 'tcx>,
208    kind: Stub<'ll>,
209    unique_type_id: UniqueTypeId<'tcx>,
210    name: &str,
211    def_location: Option<DefinitionLocation<'ll>>,
212    (size, align): (Size, Align),
213    containing_scope: Option<&'ll DIScope>,
214    flags: DIFlags,
215) -> StubInfo<'ll, 'tcx> {
216    let no_elements: &[Option<&llvm::Metadata>] = &[];
217    let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx);
218
219    let (file_metadata, line_number) = if let Some(def_location) = def_location {
220        (def_location.0, def_location.1)
221    } else {
222        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
223    };
224
225    let metadata = match kind {
226        Stub::Struct | Stub::VTableTy { .. } => {
227            let vtable_holder = match kind {
228                Stub::VTableTy { vtable_holder } => Some(vtable_holder),
229                _ => None,
230            };
231            unsafe {
232                llvm::LLVMDIBuilderCreateStructType(
233                    DIB(cx),
234                    containing_scope,
235                    name.as_ptr(),
236                    name.len(),
237                    file_metadata,
238                    line_number,
239                    size.bits(),
240                    align.bits() as u32,
241                    flags,
242                    None,
243                    no_elements.as_ptr(),
244                    no_elements.len() as c_uint,
245                    0u32, // (Objective-C runtime version; default is 0)
246                    vtable_holder,
247                    unique_type_id_str.as_ptr(),
248                    unique_type_id_str.len(),
249                )
250            }
251        }
252        Stub::Union => unsafe {
253            llvm::LLVMDIBuilderCreateUnionType(
254                DIB(cx),
255                containing_scope,
256                name.as_ptr(),
257                name.len(),
258                file_metadata,
259                line_number,
260                size.bits(),
261                align.bits() as u32,
262                flags,
263                no_elements.as_ptr(),
264                no_elements.len() as c_uint,
265                0u32, // (Objective-C runtime version; default is 0)
266                unique_type_id_str.as_ptr(),
267                unique_type_id_str.len(),
268            )
269        },
270    };
271    StubInfo { metadata, unique_type_id }
272}
273
274struct AdtStackPopGuard<'ll, 'tcx, 'a> {
275    cx: &'a CodegenCx<'ll, 'tcx>,
276}
277
278impl<'ll, 'tcx, 'a> Drop for AdtStackPopGuard<'ll, 'tcx, 'a> {
279    fn drop(&mut self) {
280        debug_context(self.cx).adt_stack.borrow_mut().pop();
281    }
282}
283
284/// This function enables creating debuginfo nodes that can recursively refer to themselves.
285/// It will first insert the given stub into the type map and only then execute the `members`
286/// and `generics` closures passed in. These closures have access to the stub so they can
287/// directly attach fields to them. If the type of a field transitively refers back
288/// to the type currently being built, the stub will already be found in the type map,
289/// which effectively breaks the recursion cycle.
290pub(super) fn build_type_with_children<'ll, 'tcx>(
291    cx: &CodegenCx<'ll, 'tcx>,
292    stub_info: StubInfo<'ll, 'tcx>,
293    members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>,
294    generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<Option<&'ll DIType>>,
295) -> DINodeCreationResult<'ll> {
296    match (&debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id),
        &None) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
297
298    let mut _adt_stack_pop_guard = None;
299    if let UniqueTypeId::Ty(ty, ..) = stub_info.unique_type_id
300        && let ty::Adt(adt_def, args) = ty.kind()
301    {
302        let def_id = adt_def.did();
303        // If any child type references the original type definition and the child type has a type
304        // parameter that strictly contains the original parameter, the original type is a recursive
305        // type that can expanding indefinitely. Example,
306        // ```
307        // enum Recursive<T> {
308        //     Recurse(*const Recursive<Wrap<T>>),
309        //     Item(T),
310        // }
311        // ```
312        let is_expanding_recursive = {
313            let stack = debug_context(cx).adt_stack.borrow();
314            stack
315                .iter()
316                .enumerate()
317                .rev()
318                .skip(1)
319                .filter(|(_, (ancestor_def_id, _))| def_id == *ancestor_def_id)
320                .any(|(ancestor_index, (_, ancestor_args))| {
321                    args.iter()
322                        .zip(ancestor_args.iter())
323                        .filter_map(|(arg, ancestor_arg)| arg.as_type().zip(ancestor_arg.as_type()))
324                        .any(|(arg, ancestor_arg)|
325                            // Strictly contains.
326                            (arg != ancestor_arg && arg.contains(ancestor_arg))
327                            // Check all types between current and ancestor use the
328                            // ancestor_arg.
329                            // Otherwise, duplicate wrappers in normal recursive type may be
330                            // regarded as expanding.
331                            // ```
332                            // struct Recursive {
333                            //     a: Box<Box<Recursive>>,
334                            // }
335                            // ```
336                            // It can produce an ADT stack like this,
337                            // - Box<Recursive>
338                            // - Recursive
339                            // - Box<Box<Recursive>>
340                            && stack[ancestor_index + 1..stack.len()].iter().all(
341                                |(_, intermediate_args)|
342                                    intermediate_args
343                                        .iter()
344                                        .filter_map(|arg| arg.as_type())
345                                        .any(|mid_arg| mid_arg.contains(ancestor_arg))
346                            ))
347                })
348        };
349        if is_expanding_recursive {
350            // FIXME: indicate that this is an expanding recursive type in stub metadata?
351            return DINodeCreationResult::new(stub_info.metadata, false);
352        } else {
353            debug_context(cx).adt_stack.borrow_mut().push((def_id, args));
354            _adt_stack_pop_guard = Some(AdtStackPopGuard { cx });
355        }
356    }
357
358    debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata);
359
360    let members: SmallVec<_> =
361        members(cx, stub_info.metadata).into_iter().map(|node| Some(node)).collect();
362    let generics = generics(cx);
363
364    if !(members.is_empty() && generics.is_empty()) {
365        unsafe {
366            let members_array = create_DIArray(DIB(cx), &members[..]);
367            let generics_array = create_DIArray(DIB(cx), &generics[..]);
368            llvm::LLVMRustDICompositeTypeReplaceArrays(
369                DIB(cx),
370                stub_info.metadata,
371                Some(members_array),
372                Some(generics_array),
373            );
374        }
375    }
376
377    DINodeCreationResult { di_node: stub_info.metadata, already_stored_in_typemap: true }
378}