rustc_codegen_llvm/debuginfo/metadata/enums/
cpp_like.rs

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