pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId<'tcx>
) -> DINodeCreationResult<'ll>
Expand description

In CPP-like mode, we generate a union of structs for each variant and an explicit discriminant field roughly equivalent to the following C/C++ code:

union enum$<{fully-qualified-name}> {
  struct {variant 0 name} {
    <variant 0 fields>
  } variant0;
  <other variant structs>
  {name} discriminant;
}

As you can see, the type name is wrapped enum$. This way we can have a single NatVis rule for handling all enums.

At the LLVM IR level this looks like

      DW_TAG_union_type              (top-level type for enum)
        DW_TAG_member                    (member for variant 1)
        DW_TAG_member                    (member for variant 2)
        DW_TAG_member                    (member for variant 3)
        DW_TAG_structure_type            (type of variant 1)
        DW_TAG_structure_type            (type of variant 2)
        DW_TAG_structure_type            (type of variant 3)
        DW_TAG_enumeration_type          (type of tag)

The above encoding applies for enums with a direct tag. For niche-tag we have to do things differently in order to allow a NatVis visualizer to extract all the information needed: We generate a union of two fields, one for the dataful variant and one that just points to the discriminant (which is some field within the dataful variant). We also create a DW_TAG_enumeration_type DIE that contains tag values for the non-dataful variants and make the discriminant field that type. We then use NatVis to render the enum type correctly in Windbg/VS. This will generate debuginfo roughly equivalent to the following C:

union enum$<{name}, {min niche}, {max niche}, {dataful variant name}> {
  struct <dataful variant name> {
    <fields in dataful variant>
  } dataful_variant;
  enum Discriminant$ {
    <non-dataful variants>
  } discriminant;
}

The NatVis in intrinsic.natvis matches on the type name enum$<*, *, *, *> and evaluates this.discriminant. If the value is between the min niche and max niche, then the enum is in the dataful variant and this.dataful_variant is rendered. Otherwise, the enum is in one of the non-dataful variants. In that case, we just need to render the name of the this.discriminant enum.