Skip to main content

rustc_codegen_llvm/debuginfo/metadata/enums/
cpp_like.rs

1use std::borrow::Cow;
2
3use libc::c_uint;
4use rustc_abi::{Align, Endian, FieldIdx, Size, TagEncoding, VariantIdx, Variants};
5use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
6use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
7use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods};
8use rustc_index::IndexVec;
9use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
10use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
11use rustc_span::bug;
12use smallvec::smallvec;
13
14use crate::common::CodegenCx;
15use crate::debuginfo::dwarf_const::DW_TAG_const_type;
16use crate::debuginfo::metadata::enums::DiscrResult;
17use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
18use crate::debuginfo::metadata::{
19    DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER,
20    build_field_di_node, create_member_type, file_metadata, file_metadata_from_def_id,
21    size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags,
22};
23use crate::debuginfo::utils::DIB;
24use crate::llvm;
25use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
26
27// The names of the associated constants in each variant wrapper struct.
28// These have to match up with the names being used in `intrinsic.natvis`.
29const ASSOC_CONST_DISCR_NAME: &str = "NAME";
30const ASSOC_CONST_DISCR_EXACT: &str = "DISCR_EXACT";
31const ASSOC_CONST_DISCR_BEGIN: &str = "DISCR_BEGIN";
32const ASSOC_CONST_DISCR_END: &str = "DISCR_END";
33
34const ASSOC_CONST_DISCR128_EXACT_LO: &str = "DISCR128_EXACT_LO";
35const ASSOC_CONST_DISCR128_EXACT_HI: &str = "DISCR128_EXACT_HI";
36const ASSOC_CONST_DISCR128_BEGIN_LO: &str = "DISCR128_BEGIN_LO";
37const ASSOC_CONST_DISCR128_BEGIN_HI: &str = "DISCR128_BEGIN_HI";
38const ASSOC_CONST_DISCR128_END_LO: &str = "DISCR128_END_LO";
39const ASSOC_CONST_DISCR128_END_HI: &str = "DISCR128_END_HI";
40
41// The name of the tag field in the top-level union
42const TAG_FIELD_NAME: &str = "tag";
43const TAG_FIELD_NAME_128_LO: &str = "tag128_lo";
44const TAG_FIELD_NAME_128_HI: &str = "tag128_hi";
45
46// We assign a "virtual" discriminant value to the sole variant of
47// a single-variant enum.
48const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
49
50/// In CPP-like mode, we generate a union with a field for each variant and an
51/// explicit tag field. The field of each variant has a struct type
52/// that encodes the discriminant of the variant and it's data layout.
53/// The union also has a nested enumeration type that is only used for encoding
54/// variant names in an efficient way. Its enumerator values do _not_ correspond
55/// to the enum's discriminant values.
56/// It's roughly equivalent to the following C/C++ code:
57///
58/// ```c
59/// union enum2$<{fully-qualified-name}> {
60///   struct Variant0 {
61///     struct {name-of-variant-0} {
62///        <variant 0 fields>
63///     } value;
64///
65///     static VariantNames NAME = {name-of-variant-0};
66///     static int_type DISCR_EXACT = {discriminant-of-variant-0};
67///   } variant0;
68///
69///   <other variant structs>
70///
71///   int_type tag;
72///
73///   enum VariantNames {
74///      <name-of-variant-0> = 0, // The numeric values are variant index,
75///      <name-of-variant-1> = 1, // not discriminant values.
76///      <name-of-variant-2> = 2,
77///      ...
78///   }
79/// }
80/// ```
81///
82/// As you can see, the type name is wrapped in `enum2$<_>`. This way we can
83/// have a single NatVis rule for handling all enums. The `2` in `enum2$<_>`
84/// is an encoding version tag, so that debuggers can decide to decode this
85/// differently than the previous `enum$<_>` encoding emitted by earlier
86/// compiler versions.
87///
88/// Niche-tag enums have one special variant, usually called the
89/// "untagged variant". This variant has a field that
90/// doubles as the tag of the enum. The variant is active when the value of
91/// that field is within a pre-defined range. Therefore the variant struct
92/// has a `DISCR_BEGIN` and `DISCR_END` field instead of `DISCR_EXACT` in
93/// that case. Both `DISCR_BEGIN` and `DISCR_END` are inclusive bounds.
94/// Note that these ranges can wrap around, so that `DISCR_END < DISCR_BEGIN`.
95///
96/// Single-variant enums don't actually have a tag field. In this case we
97/// emit a static tag field (that always has the value 0) so we can use the
98/// same representation (and NatVis).
99///
100/// For niche-layout enums it's possible to have a 128-bit tag. NatVis, VS, and
101/// WinDbg (the main targets for CPP-like debuginfo at the moment) don't support
102/// 128-bit integers, so all values involved get split into two 64-bit fields.
103/// Instead of the `tag` field, we generate two fields `tag128_lo` and `tag128_hi`,
104/// Instead of `DISCR_EXACT`, we generate `DISCR128_EXACT_LO` and `DISCR128_EXACT_HI`,
105/// and so on.
106///
107///
108/// The following pseudocode shows how to decode an enum value in a debugger:
109///
110/// ```text
111///
112/// fn find_active_variant(enum_value) -> (VariantName, VariantValue) {
113///     let is_128_bit = enum_value.has_field("tag128_lo");
114///
115///     if !is_128_bit {
116///         // Note: `tag` can be a static field for enums with only one
117///         //       inhabited variant.
118///         let tag = enum_value.field("tag").value;
119///
120///         // For each variant, check if it is a match. Only one of them will match,
121///         // so if we find it we can return it immediately.
122///         for variant_field in enum_value.fields().filter(|f| f.name.starts_with("variant")) {
123///             if variant_field.has_field("DISCR_EXACT") {
124///                 // This variant corresponds to a single tag value
125///                 if variant_field.field("DISCR_EXACT").value == tag {
126///                     return (variant_field.field("NAME"), variant_field.value);
127///                 }
128///             } else {
129///                 // This is a range variant
130///                 let begin = variant_field.field("DISCR_BEGIN");
131///                 let end = variant_field.field("DISCR_END");
132///
133///                 if is_in_range(tag, begin, end) {
134///                     return (variant_field.field("NAME"), variant_field.value);
135///                 }
136///             }
137///         }
138///     } else {
139///         // Basically the same as with smaller tags, we just have to
140///         // stitch the values together.
141///         let tag: u128 = (enum_value.field("tag128_lo").value as u128) |
142///                         (enum_value.field("tag128_hi").value as u128 << 64);
143///
144///         for variant_field in enum_value.fields().filter(|f| f.name.starts_with("variant")) {
145///             if variant_field.has_field("DISCR128_EXACT_LO") {
146///                 let discr_exact = (variant_field.field("DISCR128_EXACT_LO" as u128) |
147///                                   (variant_field.field("DISCR128_EXACT_HI") as u128 << 64);
148///
149///                 // This variant corresponds to a single tag value
150///                 if discr_exact.value == tag {
151///                     return (variant_field.field("NAME"), variant_field.value);
152///                 }
153///             } else {
154///                 // This is a range variant
155///                 let begin = (variant_field.field("DISCR128_BEGIN_LO").value as u128) |
156///                             (variant_field.field("DISCR128_BEGIN_HI").value as u128 << 64);
157///                 let end = (variant_field.field("DISCR128_END_LO").value as u128) |
158///                           (variant_field.field("DISCR128_END_HI").value as u128 << 64);
159///
160///                 if is_in_range(tag, begin, end) {
161///                     return (variant_field.field("NAME"), variant_field.value);
162///                 }
163///             }
164///         }
165///     }
166///
167///     // We should have found an active variant at this point.
168///     unreachable!();
169/// }
170///
171/// // Check if a value is within the given range
172/// // (where the range might wrap around the value space)
173/// fn is_in_range(value, start, end) -> bool {
174///     if start < end {
175///         value >= start && value <= end
176///     } else {
177///         value >= start || value <= end
178///     }
179/// }
180///
181/// ```
182pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
183    cx: &CodegenCx<'ll, 'tcx>,
184    unique_type_id: UniqueTypeId<'tcx>,
185) -> DINodeCreationResult<'ll> {
186    let enum_type = unique_type_id.expect_ty();
187    let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
188        ::rustc_span::macros::bug_impl(None,
    format_args!("build_enum_type_di_node() called with non-enum type: `{0:?}`",
        enum_type), Location::caller())bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
189    };
190
191    let enum_type_and_layout = cx.layout_of(enum_type);
192    let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
193
194    if !!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) {
    ::core::panicking::panic("assertion failed: !wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)")
};assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout));
195
196    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
197        Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did())))
198    } else {
199        None
200    };
201
202    type_map::build_type_with_children(
203        cx,
204        type_map::stub(
205            cx,
206            type_map::Stub::Union,
207            unique_type_id,
208            &enum_type_name,
209            def_location,
210            cx.size_and_align_of(enum_type),
211            NO_SCOPE_METADATA,
212            visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did()),
213        ),
214        |cx, enum_type_di_node| {
215            match enum_type_and_layout.variants {
216                // We don't generate any members for uninhabited types.
217                Variants::Empty => ::smallvec::SmallVec::new()smallvec![],
218                Variants::Single { index: variant_index } => build_single_variant_union_fields(
219                    cx,
220                    enum_adt_def,
221                    enum_type_and_layout,
222                    enum_type_di_node,
223                    variant_index,
224                ),
225                Variants::Multiple {
226                    tag_encoding: TagEncoding::Direct,
227                    ref variants,
228                    tag_field,
229                    ..
230                } => build_union_fields_for_enum(
231                    cx,
232                    enum_adt_def,
233                    enum_type_and_layout,
234                    enum_type_di_node,
235                    variants.indices(),
236                    tag_field,
237                    None,
238                ),
239                Variants::Multiple {
240                    tag_encoding: TagEncoding::Niche { untagged_variant, .. },
241                    ref variants,
242                    tag_field,
243                    ..
244                } => build_union_fields_for_enum(
245                    cx,
246                    enum_adt_def,
247                    enum_type_and_layout,
248                    enum_type_di_node,
249                    variants.indices(),
250                    tag_field,
251                    Some(untagged_variant),
252                ),
253            }
254        },
255        NO_GENERICS,
256    )
257}
258
259/// A coroutine debuginfo node looks the same as a that of an enum type.
260///
261/// See [build_enum_type_di_node] for more information.
262pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
263    cx: &CodegenCx<'ll, 'tcx>,
264    unique_type_id: UniqueTypeId<'tcx>,
265) -> DINodeCreationResult<'ll> {
266    let coroutine_type = unique_type_id.expect_ty();
267    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
268        let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else {
269            ::rustc_span::macros::bug_impl(None,
    format_args!("build_coroutine_di_node() called with non-coroutine type: `{0:?}`",
        coroutine_type), Location::caller())bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
270        };
271        Some(file_metadata_from_def_id(cx, Some(coroutine_def_id)))
272    } else {
273        None
274    };
275    let coroutine_type_and_layout = cx.layout_of(coroutine_type);
276    let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
277
278    if !!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout) {
    ::core::panicking::panic("assertion failed: !wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout)")
};assert!(!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout));
279
280    type_map::build_type_with_children(
281        cx,
282        type_map::stub(
283            cx,
284            type_map::Stub::Union,
285            unique_type_id,
286            &coroutine_type_name,
287            def_location,
288            size_and_align_of(coroutine_type_and_layout),
289            NO_SCOPE_METADATA,
290            DIFlags::FlagZero,
291        ),
292        |cx, coroutine_type_di_node| match coroutine_type_and_layout.variants {
293            Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => {
294                build_union_fields_for_direct_tag_coroutine(
295                    cx,
296                    coroutine_type_and_layout,
297                    coroutine_type_di_node,
298                )
299            }
300            Variants::Single { .. }
301            | Variants::Empty
302            | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
303                ::rustc_span::macros::bug_impl(None,
    format_args!("Encountered coroutine with non-direct-tag layout: {0:?}",
        coroutine_type_and_layout), Location::caller())bug!(
304                    "Encountered coroutine with non-direct-tag layout: {:?}",
305                    coroutine_type_and_layout
306                )
307            }
308        },
309        NO_GENERICS,
310    )
311}
312
313fn build_single_variant_union_fields<'ll, 'tcx>(
314    cx: &CodegenCx<'ll, 'tcx>,
315    enum_adt_def: AdtDef<'tcx>,
316    enum_type_and_layout: TyAndLayout<'tcx>,
317    enum_type_di_node: &'ll DIType,
318    variant_index: VariantIdx,
319) -> SmallVec<&'ll DIType> {
320    let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
321    let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
322    let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
323        cx,
324        enum_type_and_layout,
325        enum_type_di_node,
326        variant_index,
327        enum_adt_def.variant(variant_index),
328        variant_layout,
329        visibility_flags,
330    );
331
332    let tag_base_type = cx.tcx.types.u32;
333    let tag_base_type_di_node = type_di_node(cx, tag_base_type);
334    let tag_base_type_align = cx.align_of(tag_base_type);
335
336    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
337        Some(enum_adt_def.did())
338    } else {
339        None
340    };
341
342    let variant_names_type_di_node = build_variant_names_type_di_node(
343        cx,
344        enum_type_di_node,
345        std::iter::once((
346            variant_index,
347            Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
348        )),
349        enum_adt_def_id,
350    );
351
352    let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node(
353        cx,
354        enum_type_and_layout,
355        enum_type_di_node,
356        variant_index,
357        None,
358        variant_struct_type_di_node,
359        variant_names_type_di_node,
360        tag_base_type_di_node,
361        tag_base_type,
362        DiscrResult::NoDiscriminant,
363        None,
364    );
365
366    {
    let count = 0usize + 1usize + 1usize;
    let mut vec = ::smallvec::SmallVec::new();
    if count <= vec.inline_size() {
        vec.push(build_field_di_node(cx, enum_type_di_node,
                &variant_union_field_name(variant_index),
                enum_type_and_layout, Size::ZERO, visibility_flags,
                variant_struct_type_wrapper_di_node, None));
        vec.push(create_static_member_type(cx, enum_type_di_node,
                TAG_FIELD_NAME, unknown_file_metadata(cx),
                UNKNOWN_LINE_NUMBER, variant_names_type_di_node,
                visibility_flags,
                Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
                tag_base_type_align));
        vec
    } else {
        ::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                    [build_field_di_node(cx, enum_type_di_node,
                                &variant_union_field_name(variant_index),
                                enum_type_and_layout, Size::ZERO, visibility_flags,
                                variant_struct_type_wrapper_di_node, None),
                            create_static_member_type(cx, enum_type_di_node,
                                TAG_FIELD_NAME, unknown_file_metadata(cx),
                                UNKNOWN_LINE_NUMBER, variant_names_type_di_node,
                                visibility_flags,
                                Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
                                tag_base_type_align)])))
    }
}smallvec![
367        build_field_di_node(
368            cx,
369            enum_type_di_node,
370            &variant_union_field_name(variant_index),
371            // NOTE: We use the layout of the entire type, not from variant_layout
372            //       since the later is sometimes smaller (if it has fewer fields).
373            enum_type_and_layout,
374            Size::ZERO,
375            visibility_flags,
376            variant_struct_type_wrapper_di_node,
377            None,
378        ),
379        create_static_member_type(
380            cx,
381            enum_type_di_node,
382            TAG_FIELD_NAME,
383            unknown_file_metadata(cx),
384            UNKNOWN_LINE_NUMBER,
385            variant_names_type_di_node,
386            visibility_flags,
387            Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
388            tag_base_type_align,
389        ),
390    ]
391}
392
393fn build_union_fields_for_enum<'ll, 'tcx>(
394    cx: &CodegenCx<'ll, 'tcx>,
395    enum_adt_def: AdtDef<'tcx>,
396    enum_type_and_layout: TyAndLayout<'tcx>,
397    enum_type_di_node: &'ll DIType,
398    variant_indices: impl Iterator<Item = VariantIdx> + Clone,
399    tag_field: FieldIdx,
400    untagged_variant_index: Option<VariantIdx>,
401) -> SmallVec<&'ll DIType> {
402    let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
403
404    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
405        Some(enum_adt_def.did())
406    } else {
407        None
408    };
409
410    let variant_names_type_di_node = build_variant_names_type_di_node(
411        cx,
412        enum_type_di_node,
413        variant_indices.clone().map(|variant_index| {
414            let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
415            (variant_index, variant_name)
416        }),
417        enum_adt_def_id,
418    );
419    let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
420
421    let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices
422        .map(|variant_index| {
423            let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
424
425            let variant_def = enum_adt_def.variant(variant_index);
426
427            let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
428                cx,
429                enum_type_and_layout,
430                enum_type_di_node,
431                variant_index,
432                variant_def,
433                variant_layout,
434                visibility_flags,
435            );
436
437            VariantFieldInfo {
438                variant_index,
439                variant_struct_type_di_node,
440                source_info: None,
441                discr: super::compute_discriminant_value(cx, enum_type_and_layout, variant_index),
442            }
443        })
444        .collect();
445
446    build_union_fields_for_direct_tag_enum_or_coroutine(
447        cx,
448        enum_type_and_layout,
449        enum_type_di_node,
450        &variant_field_infos,
451        variant_names_type_di_node,
452        tag_base_type,
453        tag_field,
454        untagged_variant_index,
455        visibility_flags,
456    )
457}
458
459// The base type of the VariantNames DW_AT_enumeration_type is always the same.
460// It has nothing to do with the tag of the enum and just has to be big enough
461// to hold all variant names.
462fn variant_names_enum_base_type<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> Ty<'tcx> {
463    cx.tcx.types.u32
464}
465
466/// This function builds a DW_AT_enumeration_type that contains an entry for
467/// each variant. Note that this has nothing to do with the discriminant. The
468/// numeric value of each enumerator corresponds to the variant index. The
469/// type is only used for efficiently encoding the name of each variant in
470/// debuginfo.
471fn build_variant_names_type_di_node<'ll, 'tcx>(
472    cx: &CodegenCx<'ll, 'tcx>,
473    containing_scope: &'ll DIType,
474    variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>,
475    enum_def_id: Option<rustc_span::def_id::DefId>,
476) -> &'ll DIType {
477    // Create an enumerator for each variant.
478    super::build_enumeration_type_di_node(
479        cx,
480        "VariantNames",
481        variant_names_enum_base_type(cx),
482        variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())),
483        enum_def_id,
484        containing_scope,
485    )
486}
487
488fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
489    cx: &CodegenCx<'ll, 'tcx>,
490    enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
491    enum_or_coroutine_type_di_node: &'ll DIType,
492    variant_index: VariantIdx,
493    untagged_variant_index: Option<VariantIdx>,
494    variant_struct_type_di_node: &'ll DIType,
495    variant_names_type_di_node: &'ll DIType,
496    tag_base_type_di_node: &'ll DIType,
497    tag_base_type: Ty<'tcx>,
498    discr: DiscrResult,
499    source_info: Option<(&'ll DIFile, c_uint)>,
500) -> &'ll DIType {
501    type_map::build_type_with_children(
502        cx,
503        type_map::stub(
504            cx,
505            Stub::Struct,
506            UniqueTypeId::for_enum_variant_struct_type_wrapper(
507                cx.tcx,
508                enum_or_coroutine_type_and_layout.ty,
509                variant_index,
510            ),
511            &variant_struct_wrapper_type_name(variant_index),
512            source_info,
513            // NOTE: We use size and align of enum_type, not from variant_layout:
514            size_and_align_of(enum_or_coroutine_type_and_layout),
515            Some(enum_or_coroutine_type_di_node),
516            DIFlags::FlagZero,
517        ),
518        |cx, wrapper_struct_type_di_node| {
519            enum DiscrKind {
520                Exact(u64),
521                Exact128(u128),
522                Range(u64, u64),
523                Range128(u128, u128),
524            }
525
526            let (tag_base_type_size, tag_base_type_align) = cx.size_and_align_of(tag_base_type);
527            let is_128_bits = tag_base_type_size.bits() > 64;
528
529            let discr = match discr {
530                DiscrResult::NoDiscriminant => DiscrKind::Exact(SINGLE_VARIANT_VIRTUAL_DISR),
531                DiscrResult::Value(discr_val) => {
532                    if is_128_bits {
533                        DiscrKind::Exact128(discr_val)
534                    } else {
535                        {
    match (&discr_val, &(discr_val as u64 as u128)) {
        (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!(discr_val, discr_val as u64 as u128);
536                        DiscrKind::Exact(discr_val as u64)
537                    }
538                }
539                DiscrResult::Range(min, max) => {
540                    {
    match (&Some(variant_index), &untagged_variant_index) {
        (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!(Some(variant_index), untagged_variant_index);
541                    if is_128_bits {
542                        DiscrKind::Range128(min, max)
543                    } else {
544                        {
    match (&min, &(min as u64 as u128)) {
        (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!(min, min as u64 as u128);
545                        {
    match (&max, &(max as u64 as u128)) {
        (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!(max, max as u64 as u128);
546                        DiscrKind::Range(min as u64, max as u64)
547                    }
548                }
549            };
550
551            let mut fields = SmallVec::new();
552
553            // We always have a field for the value
554            fields.push(build_field_di_node(
555                cx,
556                wrapper_struct_type_di_node,
557                "value",
558                enum_or_coroutine_type_and_layout,
559                Size::ZERO,
560                DIFlags::FlagZero,
561                variant_struct_type_di_node,
562                None,
563            ));
564
565            let build_assoc_const = |name: &str,
566                                     type_di_node_: &'ll DIType,
567                                     value: u64,
568                                     align: Align|
569             -> &'ll llvm::Metadata {
570                // FIXME: Currently we force all DISCR_* values to be u64's as LLDB seems to have
571                // problems inspecting other value types. Since DISCR_* is typically only going to be
572                // directly inspected via the debugger visualizer - which compares it to the `tag` value
573                // (whose type is not modified at all) it shouldn't cause any real problems.
574                let (t_di, align) = if name == ASSOC_CONST_DISCR_NAME {
575                    (type_di_node_, align)
576                } else {
577                    let ty_u64 = Ty::new_uint(cx.tcx, ty::UintTy::U64);
578                    (type_di_node(cx, ty_u64), Align::EIGHT)
579                };
580
581                // must wrap type in a `const` modifier for LLDB to be able to inspect the value of the member
582                let field_type = unsafe {
583                    llvm::LLVMDIBuilderCreateQualifiedType(DIB(cx), DW_TAG_const_type, t_di)
584                };
585
586                create_static_member_type(
587                    cx,
588                    wrapper_struct_type_di_node,
589                    name,
590                    unknown_file_metadata(cx),
591                    UNKNOWN_LINE_NUMBER,
592                    field_type,
593                    DIFlags::FlagZero,
594                    Some(cx.const_u64(value)),
595                    align,
596                )
597            };
598
599            // We also always have an associated constant for the discriminant value
600            // of the variant.
601            fields.push(build_assoc_const(
602                ASSOC_CONST_DISCR_NAME,
603                variant_names_type_di_node,
604                variant_index.as_u32() as u64,
605                cx.align_of(variant_names_enum_base_type(cx)),
606            ));
607
608            // Emit the discriminant value (or range) corresponding to the variant.
609            match discr {
610                DiscrKind::Exact(discr_val) => {
611                    fields.push(build_assoc_const(
612                        ASSOC_CONST_DISCR_EXACT,
613                        tag_base_type_di_node,
614                        discr_val,
615                        tag_base_type_align,
616                    ));
617                }
618                DiscrKind::Exact128(discr_val) => {
619                    let align = cx.align_of(cx.tcx.types.u64);
620                    let type_di_node = type_di_node(cx, cx.tcx.types.u64);
621                    let Split128 { hi, lo } = split_128(discr_val);
622
623                    fields.push(build_assoc_const(
624                        ASSOC_CONST_DISCR128_EXACT_LO,
625                        type_di_node,
626                        lo,
627                        align,
628                    ));
629
630                    fields.push(build_assoc_const(
631                        ASSOC_CONST_DISCR128_EXACT_HI,
632                        type_di_node,
633                        hi,
634                        align,
635                    ));
636                }
637                DiscrKind::Range(begin, end) => {
638                    fields.push(build_assoc_const(
639                        ASSOC_CONST_DISCR_BEGIN,
640                        tag_base_type_di_node,
641                        begin,
642                        tag_base_type_align,
643                    ));
644
645                    fields.push(build_assoc_const(
646                        ASSOC_CONST_DISCR_END,
647                        tag_base_type_di_node,
648                        end,
649                        tag_base_type_align,
650                    ));
651                }
652                DiscrKind::Range128(begin, end) => {
653                    let align = cx.align_of(cx.tcx.types.u64);
654                    let type_di_node = type_di_node(cx, cx.tcx.types.u64);
655                    let Split128 { hi: begin_hi, lo: begin_lo } = split_128(begin);
656                    let Split128 { hi: end_hi, lo: end_lo } = split_128(end);
657
658                    fields.push(build_assoc_const(
659                        ASSOC_CONST_DISCR128_BEGIN_HI,
660                        type_di_node,
661                        begin_hi,
662                        align,
663                    ));
664
665                    fields.push(build_assoc_const(
666                        ASSOC_CONST_DISCR128_BEGIN_LO,
667                        type_di_node,
668                        begin_lo,
669                        align,
670                    ));
671
672                    fields.push(build_assoc_const(
673                        ASSOC_CONST_DISCR128_END_HI,
674                        type_di_node,
675                        end_hi,
676                        align,
677                    ));
678
679                    fields.push(build_assoc_const(
680                        ASSOC_CONST_DISCR128_END_LO,
681                        type_di_node,
682                        end_lo,
683                        align,
684                    ));
685                }
686            }
687
688            fields
689        },
690        NO_GENERICS,
691    )
692    .di_node
693}
694
695struct Split128 {
696    hi: u64,
697    lo: u64,
698}
699
700fn split_128(value: u128) -> Split128 {
701    Split128 { hi: (value >> 64) as u64, lo: value as u64 }
702}
703
704fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
705    cx: &CodegenCx<'ll, 'tcx>,
706    coroutine_type_and_layout: TyAndLayout<'tcx>,
707    coroutine_type_di_node: &'ll DIType,
708) -> SmallVec<&'ll DIType> {
709    let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } =
710        coroutine_type_and_layout.variants
711    else {
712        ::rustc_span::macros::bug_impl(None,
    format_args!("This function only supports layouts with directly encoded tags."),
    Location::caller())bug!("This function only supports layouts with directly encoded tags.")
713    };
714
715    let (coroutine_def_id, coroutine_args) = match coroutine_type_and_layout.ty.kind() {
716        &ty::Coroutine(def_id, args) => (def_id, args.as_coroutine()),
717        _ => ::core::panicking::unreachable_default_msg()unreachable!(),
718    };
719
720    let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();
721
722    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
723    let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
724    let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
725
726    let tag_base_type = tag_base_type(cx.tcx, coroutine_type_and_layout);
727
728    let variant_names_type_di_node = build_variant_names_type_di_node(
729        cx,
730        coroutine_type_di_node,
731        variant_range
732            .clone()
733            .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
734        if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
735            Some(coroutine_def_id)
736        } else {
737            None
738        },
739    );
740
741    let discriminants: IndexVec<VariantIdx, DiscrResult> = {
742        let discriminants_iter = coroutine_args.discriminants(coroutine_def_id, cx.tcx);
743        let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
744            IndexVec::with_capacity(variant_count);
745        for (variant_index, discr) in discriminants_iter {
746            // Assert that the index in the IndexMap matches up with the given VariantIdx.
747            {
    match (&variant_index, &discriminants.next_index()) {
        (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!(variant_index, discriminants.next_index());
748            discriminants.push(DiscrResult::Value(discr.val));
749        }
750        discriminants
751    };
752
753    // Build the type node for each field.
754    let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
755        .map(|variant_index| {
756            let variant_struct_type_di_node = super::build_coroutine_variant_struct_type_di_node(
757                cx,
758                variant_index,
759                coroutine_type_and_layout,
760                coroutine_type_di_node,
761                coroutine_layout,
762                common_upvar_names,
763            );
764
765            let span = coroutine_layout.variant_source_info[variant_index].span;
766            let source_info = if !span.is_dummy() {
767                let loc = cx.lookup_debug_loc(span.lo());
768                Some((file_metadata(cx, &loc.file), loc.line as c_uint))
769            } else {
770                None
771            };
772
773            VariantFieldInfo {
774                variant_index,
775                variant_struct_type_di_node,
776                source_info,
777                discr: discriminants[variant_index],
778            }
779        })
780        .collect();
781
782    build_union_fields_for_direct_tag_enum_or_coroutine(
783        cx,
784        coroutine_type_and_layout,
785        coroutine_type_di_node,
786        &variant_field_infos[..],
787        variant_names_type_di_node,
788        tag_base_type,
789        tag_field,
790        None,
791        DIFlags::FlagZero,
792    )
793}
794
795/// This is a helper function shared between enums and coroutines that makes sure fields have the
796/// expect names.
797fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
798    cx: &CodegenCx<'ll, 'tcx>,
799    enum_type_and_layout: TyAndLayout<'tcx>,
800    enum_type_di_node: &'ll DIType,
801    variant_field_infos: &[VariantFieldInfo<'ll>],
802    discr_type_di_node: &'ll DIType,
803    tag_base_type: Ty<'tcx>,
804    tag_field: FieldIdx,
805    untagged_variant_index: Option<VariantIdx>,
806    di_flags: DIFlags,
807) -> SmallVec<&'ll DIType> {
808    let tag_base_type_di_node = type_di_node(cx, tag_base_type);
809    let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
810
811    // We create a field in the union for each variant ...
812    unions_fields.extend(variant_field_infos.iter().map(|variant_member_info| {
813        let (file_di_node, line_number) = variant_member_info
814            .source_info
815            .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
816
817        let field_name = variant_union_field_name(variant_member_info.variant_index);
818
819        let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node(
820            cx,
821            enum_type_and_layout,
822            enum_type_di_node,
823            variant_member_info.variant_index,
824            untagged_variant_index,
825            variant_member_info.variant_struct_type_di_node,
826            discr_type_di_node,
827            tag_base_type_di_node,
828            tag_base_type,
829            variant_member_info.discr,
830            if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
831                variant_member_info.source_info
832            } else {
833                None
834            },
835        );
836
837        // We use create_member_type() member type directly because
838        // the build_field_di_node() function does not support specifying a source location,
839        // which is something that we don't do anywhere else.
840        create_member_type(
841            cx,
842            enum_type_di_node,
843            &field_name,
844            file_di_node,
845            line_number,
846            // NOTE: We use the layout of the entire type, not from variant_layout
847            //       since the later is sometimes smaller (if it has fewer fields).
848            enum_type_and_layout,
849            // Union fields are always at offset zero
850            Size::ZERO,
851            di_flags,
852            variant_struct_type_wrapper,
853        )
854    }));
855
856    {
    match (&cx.size_and_align_of(enum_type_and_layout.field(cx,
                            tag_field.as_usize()).ty),
            &cx.size_and_align_of(self::tag_base_type(cx.tcx,
                        enum_type_and_layout))) {
        (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!(
857        cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field.as_usize()).ty),
858        cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout))
859    );
860
861    // ... and a field for the tag. If the tag is 128 bits wide, this will actually
862    // be two 64-bit fields.
863    let is_128_bits = cx.size_of(tag_base_type).bits() > 64;
864
865    if is_128_bits {
866        let type_di_node = type_di_node(cx, cx.tcx.types.u64);
867        let u64_layout = cx.layout_of(cx.tcx.types.u64);
868
869        let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian {
870            Endian::Little => (0, 8),
871            Endian::Big => (8, 0),
872        };
873
874        let tag_field_offset = enum_type_and_layout.fields.offset(tag_field.as_usize()).bytes();
875        let lo_offset = Size::from_bytes(tag_field_offset + lo_offset);
876        let hi_offset = Size::from_bytes(tag_field_offset + hi_offset);
877
878        unions_fields.push(build_field_di_node(
879            cx,
880            enum_type_di_node,
881            TAG_FIELD_NAME_128_LO,
882            u64_layout,
883            lo_offset,
884            di_flags,
885            type_di_node,
886            None,
887        ));
888
889        unions_fields.push(build_field_di_node(
890            cx,
891            enum_type_di_node,
892            TAG_FIELD_NAME_128_HI,
893            u64_layout,
894            hi_offset,
895            DIFlags::FlagZero,
896            type_di_node,
897            None,
898        ));
899    } else {
900        unions_fields.push(build_field_di_node(
901            cx,
902            enum_type_di_node,
903            TAG_FIELD_NAME,
904            enum_type_and_layout.field(cx, tag_field.as_usize()),
905            enum_type_and_layout.fields.offset(tag_field.as_usize()),
906            di_flags,
907            tag_base_type_di_node,
908            None,
909        ));
910    }
911
912    unions_fields
913}
914
915/// Information about a single field of the top-level DW_TAG_union_type.
916struct VariantFieldInfo<'ll> {
917    variant_index: VariantIdx,
918    variant_struct_type_di_node: &'ll DIType,
919    source_info: Option<(&'ll DIFile, c_uint)>,
920    discr: DiscrResult,
921}
922
923fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> {
924    const PRE_ALLOCATED: [&str; 16] = [
925        "variant0",
926        "variant1",
927        "variant2",
928        "variant3",
929        "variant4",
930        "variant5",
931        "variant6",
932        "variant7",
933        "variant8",
934        "variant9",
935        "variant10",
936        "variant11",
937        "variant12",
938        "variant13",
939        "variant14",
940        "variant15",
941    ];
942
943    PRE_ALLOCATED
944        .get(variant_index.as_usize())
945        .map(|&s| Cow::from(s))
946        .unwrap_or_else(|| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("variant{0}",
                variant_index.as_usize()))
    })format!("variant{}", variant_index.as_usize()).into())
947}
948
949fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, str> {
950    const PRE_ALLOCATED: [&str; 16] = [
951        "Variant0",
952        "Variant1",
953        "Variant2",
954        "Variant3",
955        "Variant4",
956        "Variant5",
957        "Variant6",
958        "Variant7",
959        "Variant8",
960        "Variant9",
961        "Variant10",
962        "Variant11",
963        "Variant12",
964        "Variant13",
965        "Variant14",
966        "Variant15",
967    ];
968
969    PRE_ALLOCATED
970        .get(variant_index.as_usize())
971        .map(|&s| Cow::from(s))
972        .unwrap_or_else(|| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Variant{0}",
                variant_index.as_usize()))
    })format!("Variant{}", variant_index.as_usize()).into())
973}
974
975fn create_static_member_type<'ll>(
976    cx: &CodegenCx<'ll, '_>,
977    scope: &'ll llvm::Metadata,
978    name: &str,
979    file: &'ll llvm::Metadata,
980    line_number: c_uint,
981    ty: &'ll llvm::Metadata,
982    flags: DIFlags,
983    value: Option<llvm::Value<'ll>>,
984    align: Align,
985) -> &'ll llvm::Metadata {
986    unsafe {
987        llvm::LLVMDIBuilderCreateStaticMemberType(
988            DIB(cx),
989            scope,
990            name.as_ptr(),
991            name.len(),
992            file,
993            line_number,
994            ty,
995            flags,
996            value,
997            align.bits() as c_uint,
998        )
999    }
1000}