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::bug;
10use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
11use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
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::debuginfo::{DIFile, DIFlags, DIType};
25use crate::llvm::{self};
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        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    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                Variants::Empty => {
217                    // We don't generate any members for uninhabited types.
218                    return smallvec![];
219                }
220                Variants::Single { index: variant_index } => build_single_variant_union_fields(
221                    cx,
222                    enum_adt_def,
223                    enum_type_and_layout,
224                    enum_type_di_node,
225                    variant_index,
226                ),
227                Variants::Multiple {
228                    tag_encoding: TagEncoding::Direct,
229                    ref variants,
230                    tag_field,
231                    ..
232                } => build_union_fields_for_enum(
233                    cx,
234                    enum_adt_def,
235                    enum_type_and_layout,
236                    enum_type_di_node,
237                    variants.indices(),
238                    tag_field,
239                    None,
240                ),
241                Variants::Multiple {
242                    tag_encoding: TagEncoding::Niche { untagged_variant, .. },
243                    ref variants,
244                    tag_field,
245                    ..
246                } => build_union_fields_for_enum(
247                    cx,
248                    enum_adt_def,
249                    enum_type_and_layout,
250                    enum_type_di_node,
251                    variants.indices(),
252                    tag_field,
253                    Some(untagged_variant),
254                ),
255            }
256        },
257        NO_GENERICS,
258    )
259}
260
261/// A coroutine debuginfo node looks the same as a that of an enum type.
262///
263/// See [build_enum_type_di_node] for more information.
264pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
265    cx: &CodegenCx<'ll, 'tcx>,
266    unique_type_id: UniqueTypeId<'tcx>,
267) -> DINodeCreationResult<'ll> {
268    let coroutine_type = unique_type_id.expect_ty();
269    let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
270        let &ty::Coroutine(coroutine_def_id, _) = coroutine_type.kind() else {
271            bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
272        };
273        Some(file_metadata_from_def_id(cx, Some(coroutine_def_id)))
274    } else {
275        None
276    };
277    let coroutine_type_and_layout = cx.layout_of(coroutine_type);
278    let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
279
280    assert!(!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout));
281
282    type_map::build_type_with_children(
283        cx,
284        type_map::stub(
285            cx,
286            type_map::Stub::Union,
287            unique_type_id,
288            &coroutine_type_name,
289            def_location,
290            size_and_align_of(coroutine_type_and_layout),
291            NO_SCOPE_METADATA,
292            DIFlags::FlagZero,
293        ),
294        |cx, coroutine_type_di_node| match coroutine_type_and_layout.variants {
295            Variants::Multiple { tag_encoding: TagEncoding::Direct, .. } => {
296                build_union_fields_for_direct_tag_coroutine(
297                    cx,
298                    coroutine_type_and_layout,
299                    coroutine_type_di_node,
300                )
301            }
302            Variants::Single { .. }
303            | Variants::Empty
304            | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => {
305                bug!(
306                    "Encountered coroutine with non-direct-tag layout: {:?}",
307                    coroutine_type_and_layout
308                )
309            }
310        },
311        NO_GENERICS,
312    )
313}
314
315fn build_single_variant_union_fields<'ll, 'tcx>(
316    cx: &CodegenCx<'ll, 'tcx>,
317    enum_adt_def: AdtDef<'tcx>,
318    enum_type_and_layout: TyAndLayout<'tcx>,
319    enum_type_di_node: &'ll DIType,
320    variant_index: VariantIdx,
321) -> SmallVec<&'ll DIType> {
322    let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
323    let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
324    let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
325        cx,
326        enum_type_and_layout,
327        enum_type_di_node,
328        variant_index,
329        enum_adt_def.variant(variant_index),
330        variant_layout,
331        visibility_flags,
332    );
333
334    let tag_base_type = cx.tcx.types.u32;
335    let tag_base_type_di_node = type_di_node(cx, tag_base_type);
336    let tag_base_type_align = cx.align_of(tag_base_type);
337
338    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
339        Some(enum_adt_def.did())
340    } else {
341        None
342    };
343
344    let variant_names_type_di_node = build_variant_names_type_di_node(
345        cx,
346        enum_type_di_node,
347        std::iter::once((
348            variant_index,
349            Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
350        )),
351        enum_adt_def_id,
352    );
353
354    let variant_struct_type_wrapper_di_node = build_variant_struct_wrapper_type_di_node(
355        cx,
356        enum_type_and_layout,
357        enum_type_di_node,
358        variant_index,
359        None,
360        variant_struct_type_di_node,
361        variant_names_type_di_node,
362        tag_base_type_di_node,
363        tag_base_type,
364        DiscrResult::NoDiscriminant,
365        None,
366    );
367
368    smallvec![
369        build_field_di_node(
370            cx,
371            enum_type_di_node,
372            &variant_union_field_name(variant_index),
373            // NOTE: We use the layout of the entire type, not from variant_layout
374            //       since the later is sometimes smaller (if it has fewer fields).
375            enum_type_and_layout,
376            Size::ZERO,
377            visibility_flags,
378            variant_struct_type_wrapper_di_node,
379            None,
380        ),
381        create_static_member_type(
382            cx,
383            enum_type_di_node,
384            TAG_FIELD_NAME,
385            unknown_file_metadata(cx),
386            UNKNOWN_LINE_NUMBER,
387            variant_names_type_di_node,
388            visibility_flags,
389            Some(cx.const_u64(SINGLE_VARIANT_VIRTUAL_DISR)),
390            tag_base_type_align,
391        ),
392    ]
393}
394
395fn build_union_fields_for_enum<'ll, 'tcx>(
396    cx: &CodegenCx<'ll, 'tcx>,
397    enum_adt_def: AdtDef<'tcx>,
398    enum_type_and_layout: TyAndLayout<'tcx>,
399    enum_type_di_node: &'ll DIType,
400    variant_indices: impl Iterator<Item = VariantIdx> + Clone,
401    tag_field: FieldIdx,
402    untagged_variant_index: Option<VariantIdx>,
403) -> SmallVec<&'ll DIType> {
404    let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
405
406    let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
407        Some(enum_adt_def.did())
408    } else {
409        None
410    };
411
412    let variant_names_type_di_node = build_variant_names_type_di_node(
413        cx,
414        enum_type_di_node,
415        variant_indices.clone().map(|variant_index| {
416            let variant_name = Cow::from(enum_adt_def.variant(variant_index).name.as_str());
417            (variant_index, variant_name)
418        }),
419        enum_adt_def_id,
420    );
421    let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
422
423    let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_indices
424        .map(|variant_index| {
425            let variant_layout = enum_type_and_layout.for_variant(cx, variant_index);
426
427            let variant_def = enum_adt_def.variant(variant_index);
428
429            let variant_struct_type_di_node = super::build_enum_variant_struct_type_di_node(
430                cx,
431                enum_type_and_layout,
432                enum_type_di_node,
433                variant_index,
434                variant_def,
435                variant_layout,
436                visibility_flags,
437            );
438
439            VariantFieldInfo {
440                variant_index,
441                variant_struct_type_di_node,
442                source_info: None,
443                discr: super::compute_discriminant_value(cx, enum_type_and_layout, variant_index),
444            }
445        })
446        .collect();
447
448    build_union_fields_for_direct_tag_enum_or_coroutine(
449        cx,
450        enum_type_and_layout,
451        enum_type_di_node,
452        &variant_field_infos,
453        variant_names_type_di_node,
454        tag_base_type,
455        tag_field,
456        untagged_variant_index,
457        visibility_flags,
458    )
459}
460
461// The base type of the VariantNames DW_AT_enumeration_type is always the same.
462// It has nothing to do with the tag of the enum and just has to be big enough
463// to hold all variant names.
464fn variant_names_enum_base_type<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> Ty<'tcx> {
465    cx.tcx.types.u32
466}
467
468/// This function builds a DW_AT_enumeration_type that contains an entry for
469/// each variant. Note that this has nothing to do with the discriminant. The
470/// numeric value of each enumerator corresponds to the variant index. The
471/// type is only used for efficiently encoding the name of each variant in
472/// debuginfo.
473fn build_variant_names_type_di_node<'ll, 'tcx>(
474    cx: &CodegenCx<'ll, 'tcx>,
475    containing_scope: &'ll DIType,
476    variants: impl Iterator<Item = (VariantIdx, Cow<'tcx, str>)>,
477    enum_def_id: Option<rustc_span::def_id::DefId>,
478) -> &'ll DIType {
479    // Create an enumerator for each variant.
480    super::build_enumeration_type_di_node(
481        cx,
482        "VariantNames",
483        variant_names_enum_base_type(cx),
484        variants.map(|(variant_index, variant_name)| (variant_name, variant_index.as_u32().into())),
485        enum_def_id,
486        containing_scope,
487    )
488}
489
490fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
491    cx: &CodegenCx<'ll, 'tcx>,
492    enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
493    enum_or_coroutine_type_di_node: &'ll DIType,
494    variant_index: VariantIdx,
495    untagged_variant_index: Option<VariantIdx>,
496    variant_struct_type_di_node: &'ll DIType,
497    variant_names_type_di_node: &'ll DIType,
498    tag_base_type_di_node: &'ll DIType,
499    tag_base_type: Ty<'tcx>,
500    discr: DiscrResult,
501    source_info: Option<(&'ll DIFile, c_uint)>,
502) -> &'ll DIType {
503    type_map::build_type_with_children(
504        cx,
505        type_map::stub(
506            cx,
507            Stub::Struct,
508            UniqueTypeId::for_enum_variant_struct_type_wrapper(
509                cx.tcx,
510                enum_or_coroutine_type_and_layout.ty,
511                variant_index,
512            ),
513            &variant_struct_wrapper_type_name(variant_index),
514            source_info,
515            // NOTE: We use size and align of enum_type, not from variant_layout:
516            size_and_align_of(enum_or_coroutine_type_and_layout),
517            Some(enum_or_coroutine_type_di_node),
518            DIFlags::FlagZero,
519        ),
520        |cx, wrapper_struct_type_di_node| {
521            enum DiscrKind {
522                Exact(u64),
523                Exact128(u128),
524                Range(u64, u64),
525                Range128(u128, u128),
526            }
527
528            let (tag_base_type_size, tag_base_type_align) = cx.size_and_align_of(tag_base_type);
529            let is_128_bits = tag_base_type_size.bits() > 64;
530
531            let discr = match discr {
532                DiscrResult::NoDiscriminant => DiscrKind::Exact(SINGLE_VARIANT_VIRTUAL_DISR),
533                DiscrResult::Value(discr_val) => {
534                    if is_128_bits {
535                        DiscrKind::Exact128(discr_val)
536                    } else {
537                        assert_eq!(discr_val, discr_val as u64 as u128);
538                        DiscrKind::Exact(discr_val as u64)
539                    }
540                }
541                DiscrResult::Range(min, max) => {
542                    assert_eq!(Some(variant_index), untagged_variant_index);
543                    if is_128_bits {
544                        DiscrKind::Range128(min, max)
545                    } else {
546                        assert_eq!(min, min as u64 as u128);
547                        assert_eq!(max, max as u64 as u128);
548                        DiscrKind::Range(min as u64, max as u64)
549                    }
550                }
551            };
552
553            let mut fields = SmallVec::new();
554
555            // We always have a field for the value
556            fields.push(build_field_di_node(
557                cx,
558                wrapper_struct_type_di_node,
559                "value",
560                enum_or_coroutine_type_and_layout,
561                Size::ZERO,
562                DIFlags::FlagZero,
563                variant_struct_type_di_node,
564                None,
565            ));
566
567            let build_assoc_const = |name: &str,
568                                     type_di_node_: &'ll DIType,
569                                     value: u64,
570                                     align: Align|
571             -> &'ll llvm::Metadata {
572                // FIXME: Currently we force all DISCR_* values to be u64's as LLDB seems to have
573                // problems inspecting other value types. Since DISCR_* is typically only going to be
574                // directly inspected via the debugger visualizer - which compares it to the `tag` value
575                // (whose type is not modified at all) it shouldn't cause any real problems.
576                let (t_di, align) = if name == ASSOC_CONST_DISCR_NAME {
577                    (type_di_node_, align)
578                } else {
579                    let ty_u64 = Ty::new_uint(cx.tcx, ty::UintTy::U64);
580                    (type_di_node(cx, ty_u64), Align::EIGHT)
581                };
582
583                // must wrap type in a `const` modifier for LLDB to be able to inspect the value of the member
584                let field_type = unsafe {
585                    llvm::LLVMDIBuilderCreateQualifiedType(DIB(cx), DW_TAG_const_type, t_di)
586                };
587
588                create_static_member_type(
589                    cx,
590                    wrapper_struct_type_di_node,
591                    name,
592                    unknown_file_metadata(cx),
593                    UNKNOWN_LINE_NUMBER,
594                    field_type,
595                    DIFlags::FlagZero,
596                    Some(cx.const_u64(value)),
597                    align,
598                )
599            };
600
601            // We also always have an associated constant for the discriminant value
602            // of the variant.
603            fields.push(build_assoc_const(
604                ASSOC_CONST_DISCR_NAME,
605                variant_names_type_di_node,
606                variant_index.as_u32() as u64,
607                cx.align_of(variant_names_enum_base_type(cx)),
608            ));
609
610            // Emit the discriminant value (or range) corresponding to the variant.
611            match discr {
612                DiscrKind::Exact(discr_val) => {
613                    fields.push(build_assoc_const(
614                        ASSOC_CONST_DISCR_EXACT,
615                        tag_base_type_di_node,
616                        discr_val,
617                        tag_base_type_align,
618                    ));
619                }
620                DiscrKind::Exact128(discr_val) => {
621                    let align = cx.align_of(cx.tcx.types.u64);
622                    let type_di_node = type_di_node(cx, cx.tcx.types.u64);
623                    let Split128 { hi, lo } = split_128(discr_val);
624
625                    fields.push(build_assoc_const(
626                        ASSOC_CONST_DISCR128_EXACT_LO,
627                        type_di_node,
628                        lo,
629                        align,
630                    ));
631
632                    fields.push(build_assoc_const(
633                        ASSOC_CONST_DISCR128_EXACT_HI,
634                        type_di_node,
635                        hi,
636                        align,
637                    ));
638                }
639                DiscrKind::Range(begin, end) => {
640                    fields.push(build_assoc_const(
641                        ASSOC_CONST_DISCR_BEGIN,
642                        tag_base_type_di_node,
643                        begin,
644                        tag_base_type_align,
645                    ));
646
647                    fields.push(build_assoc_const(
648                        ASSOC_CONST_DISCR_END,
649                        tag_base_type_di_node,
650                        end,
651                        tag_base_type_align,
652                    ));
653                }
654                DiscrKind::Range128(begin, end) => {
655                    let align = cx.align_of(cx.tcx.types.u64);
656                    let type_di_node = type_di_node(cx, cx.tcx.types.u64);
657                    let Split128 { hi: begin_hi, lo: begin_lo } = split_128(begin);
658                    let Split128 { hi: end_hi, lo: end_lo } = split_128(end);
659
660                    fields.push(build_assoc_const(
661                        ASSOC_CONST_DISCR128_BEGIN_HI,
662                        type_di_node,
663                        begin_hi,
664                        align,
665                    ));
666
667                    fields.push(build_assoc_const(
668                        ASSOC_CONST_DISCR128_BEGIN_LO,
669                        type_di_node,
670                        begin_lo,
671                        align,
672                    ));
673
674                    fields.push(build_assoc_const(
675                        ASSOC_CONST_DISCR128_END_HI,
676                        type_di_node,
677                        end_hi,
678                        align,
679                    ));
680
681                    fields.push(build_assoc_const(
682                        ASSOC_CONST_DISCR128_END_LO,
683                        type_di_node,
684                        end_lo,
685                        align,
686                    ));
687                }
688            }
689
690            fields
691        },
692        NO_GENERICS,
693    )
694    .di_node
695}
696
697struct Split128 {
698    hi: u64,
699    lo: u64,
700}
701
702fn split_128(value: u128) -> Split128 {
703    Split128 { hi: (value >> 64) as u64, lo: value as u64 }
704}
705
706fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
707    cx: &CodegenCx<'ll, 'tcx>,
708    coroutine_type_and_layout: TyAndLayout<'tcx>,
709    coroutine_type_di_node: &'ll DIType,
710) -> SmallVec<&'ll DIType> {
711    let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } =
712        coroutine_type_and_layout.variants
713    else {
714        bug!("This function only supports layouts with directly encoded tags.")
715    };
716
717    let (coroutine_def_id, coroutine_args) = match coroutine_type_and_layout.ty.kind() {
718        &ty::Coroutine(def_id, args) => (def_id, args.as_coroutine()),
719        _ => unreachable!(),
720    };
721
722    let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();
723
724    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
725    let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);
726    let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
727
728    let tag_base_type = tag_base_type(cx.tcx, coroutine_type_and_layout);
729
730    let variant_names_type_di_node = build_variant_names_type_di_node(
731        cx,
732        coroutine_type_di_node,
733        variant_range
734            .clone()
735            .map(|variant_index| (variant_index, CoroutineArgs::variant_name(variant_index))),
736        if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
737            Some(coroutine_def_id)
738        } else {
739            None
740        },
741    );
742
743    let discriminants: IndexVec<VariantIdx, DiscrResult> = {
744        let discriminants_iter = coroutine_args.discriminants(coroutine_def_id, cx.tcx);
745        let mut discriminants: IndexVec<VariantIdx, DiscrResult> =
746            IndexVec::with_capacity(variant_count);
747        for (variant_index, discr) in discriminants_iter {
748            // Assert that the index in the IndexMap matches up with the given VariantIdx.
749            assert_eq!(variant_index, discriminants.next_index());
750            discriminants.push(DiscrResult::Value(discr.val));
751        }
752        discriminants
753    };
754
755    // Build the type node for each field.
756    let variant_field_infos: SmallVec<VariantFieldInfo<'ll>> = variant_range
757        .map(|variant_index| {
758            let variant_struct_type_di_node = super::build_coroutine_variant_struct_type_di_node(
759                cx,
760                variant_index,
761                coroutine_type_and_layout,
762                coroutine_type_di_node,
763                coroutine_layout,
764                common_upvar_names,
765            );
766
767            let span = coroutine_layout.variant_source_info[variant_index].span;
768            let source_info = if !span.is_dummy() {
769                let loc = cx.lookup_debug_loc(span.lo());
770                Some((file_metadata(cx, &loc.file), loc.line as c_uint))
771            } else {
772                None
773            };
774
775            VariantFieldInfo {
776                variant_index,
777                variant_struct_type_di_node,
778                source_info,
779                discr: discriminants[variant_index],
780            }
781        })
782        .collect();
783
784    build_union_fields_for_direct_tag_enum_or_coroutine(
785        cx,
786        coroutine_type_and_layout,
787        coroutine_type_di_node,
788        &variant_field_infos[..],
789        variant_names_type_di_node,
790        tag_base_type,
791        tag_field,
792        None,
793        DIFlags::FlagZero,
794    )
795}
796
797/// This is a helper function shared between enums and coroutines that makes sure fields have the
798/// expect names.
799fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
800    cx: &CodegenCx<'ll, 'tcx>,
801    enum_type_and_layout: TyAndLayout<'tcx>,
802    enum_type_di_node: &'ll DIType,
803    variant_field_infos: &[VariantFieldInfo<'ll>],
804    discr_type_di_node: &'ll DIType,
805    tag_base_type: Ty<'tcx>,
806    tag_field: FieldIdx,
807    untagged_variant_index: Option<VariantIdx>,
808    di_flags: DIFlags,
809) -> SmallVec<&'ll DIType> {
810    let tag_base_type_di_node = type_di_node(cx, tag_base_type);
811    let mut unions_fields = SmallVec::with_capacity(variant_field_infos.len() + 1);
812
813    // We create a field in the union for each variant ...
814    unions_fields.extend(variant_field_infos.into_iter().map(|variant_member_info| {
815        let (file_di_node, line_number) = variant_member_info
816            .source_info
817            .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
818
819        let field_name = variant_union_field_name(variant_member_info.variant_index);
820
821        let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node(
822            cx,
823            enum_type_and_layout,
824            enum_type_di_node,
825            variant_member_info.variant_index,
826            untagged_variant_index,
827            variant_member_info.variant_struct_type_di_node,
828            discr_type_di_node,
829            tag_base_type_di_node,
830            tag_base_type,
831            variant_member_info.discr,
832            if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
833                variant_member_info.source_info
834            } else {
835                None
836            },
837        );
838
839        // We use create_member_type() member type directly because
840        // the build_field_di_node() function does not support specifying a source location,
841        // which is something that we don't do anywhere else.
842        create_member_type(
843            cx,
844            enum_type_di_node,
845            &field_name,
846            file_di_node,
847            line_number,
848            // NOTE: We use the layout of the entire type, not from variant_layout
849            //       since the later is sometimes smaller (if it has fewer fields).
850            enum_type_and_layout,
851            // Union fields are always at offset zero
852            Size::ZERO,
853            di_flags,
854            variant_struct_type_wrapper,
855        )
856    }));
857
858    assert_eq!(
859        cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field.as_usize()).ty),
860        cx.size_and_align_of(self::tag_base_type(cx.tcx, enum_type_and_layout))
861    );
862
863    // ... and a field for the tag. If the tag is 128 bits wide, this will actually
864    // be two 64-bit fields.
865    let is_128_bits = cx.size_of(tag_base_type).bits() > 64;
866
867    if is_128_bits {
868        let type_di_node = type_di_node(cx, cx.tcx.types.u64);
869        let u64_layout = cx.layout_of(cx.tcx.types.u64);
870
871        let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian {
872            Endian::Little => (0, 8),
873            Endian::Big => (8, 0),
874        };
875
876        let tag_field_offset = enum_type_and_layout.fields.offset(tag_field.as_usize()).bytes();
877        let lo_offset = Size::from_bytes(tag_field_offset + lo_offset);
878        let hi_offset = Size::from_bytes(tag_field_offset + hi_offset);
879
880        unions_fields.push(build_field_di_node(
881            cx,
882            enum_type_di_node,
883            TAG_FIELD_NAME_128_LO,
884            u64_layout,
885            lo_offset,
886            di_flags,
887            type_di_node,
888            None,
889        ));
890
891        unions_fields.push(build_field_di_node(
892            cx,
893            enum_type_di_node,
894            TAG_FIELD_NAME_128_HI,
895            u64_layout,
896            hi_offset,
897            DIFlags::FlagZero,
898            type_di_node,
899            None,
900        ));
901    } else {
902        unions_fields.push(build_field_di_node(
903            cx,
904            enum_type_di_node,
905            TAG_FIELD_NAME,
906            enum_type_and_layout.field(cx, tag_field.as_usize()),
907            enum_type_and_layout.fields.offset(tag_field.as_usize()),
908            di_flags,
909            tag_base_type_di_node,
910            None,
911        ));
912    }
913
914    unions_fields
915}
916
917/// Information about a single field of the top-level DW_TAG_union_type.
918struct VariantFieldInfo<'ll> {
919    variant_index: VariantIdx,
920    variant_struct_type_di_node: &'ll DIType,
921    source_info: Option<(&'ll DIFile, c_uint)>,
922    discr: DiscrResult,
923}
924
925fn variant_union_field_name(variant_index: VariantIdx) -> Cow<'static, str> {
926    const PRE_ALLOCATED: [&str; 16] = [
927        "variant0",
928        "variant1",
929        "variant2",
930        "variant3",
931        "variant4",
932        "variant5",
933        "variant6",
934        "variant7",
935        "variant8",
936        "variant9",
937        "variant10",
938        "variant11",
939        "variant12",
940        "variant13",
941        "variant14",
942        "variant15",
943    ];
944
945    PRE_ALLOCATED
946        .get(variant_index.as_usize())
947        .map(|&s| Cow::from(s))
948        .unwrap_or_else(|| format!("variant{}", variant_index.as_usize()).into())
949}
950
951fn variant_struct_wrapper_type_name(variant_index: VariantIdx) -> Cow<'static, str> {
952    const PRE_ALLOCATED: [&str; 16] = [
953        "Variant0",
954        "Variant1",
955        "Variant2",
956        "Variant3",
957        "Variant4",
958        "Variant5",
959        "Variant6",
960        "Variant7",
961        "Variant8",
962        "Variant9",
963        "Variant10",
964        "Variant11",
965        "Variant12",
966        "Variant13",
967        "Variant14",
968        "Variant15",
969    ];
970
971    PRE_ALLOCATED
972        .get(variant_index.as_usize())
973        .map(|&s| Cow::from(s))
974        .unwrap_or_else(|| format!("Variant{}", variant_index.as_usize()).into())
975}
976
977fn create_static_member_type<'ll>(
978    cx: &CodegenCx<'ll, '_>,
979    scope: &'ll llvm::Metadata,
980    name: &str,
981    file: &'ll llvm::Metadata,
982    line_number: c_uint,
983    ty: &'ll llvm::Metadata,
984    flags: DIFlags,
985    value: Option<&'ll llvm::Value>,
986    align: Align,
987) -> &'ll llvm::Metadata {
988    unsafe {
989        llvm::LLVMDIBuilderCreateStaticMemberType(
990            DIB(cx),
991            scope,
992            name.as_ptr(),
993            name.len(),
994            file,
995            line_number,
996            ty,
997            flags,
998            value,
999            align.bits() as c_uint,
1000        )
1001    }
1002}