Function rustc_codegen_llvm::debuginfo::metadata::enums::cpp_like::build_enum_type_di_node
source · [−]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.