@@ -105,14 +105,6 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
105105/// that case. Both `DISCR_BEGIN` and `DISCR_END` are inclusive bounds.
106106/// Note that these ranges can wrap around, so that `DISCR_END < DISCR_BEGIN`.
107107///
108- /// The field in the top-level union that corresponds to the dataful variant
109- /// is called `variant_fallback` instead of `variant<index>`. This is mainly
110- /// an optimization that enables a shorter NatVis definition. That way we
111- /// only need to specify a `tag == variantX.DISCR_EXACT` entry for the indexed
112- /// variants. Otherwise we'd need to have that and then an additional entry
113- /// checking `in_range(variantX.DISCR_BEGIN, variantX.DISCR_END)` for each
114- /// index.
115- ///
116108/// Single-variant enums don't actually have a tag field. In this case we
117109/// emit a static tag field (that always has the value 0) so we can use the
118110/// same representation (and NatVis).
@@ -123,6 +115,72 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
123115/// Instead of the `tag` field, we generate two fields `tag128_lo` and `tag128_hi`,
124116/// Instead of `DISCR_EXACT`, we generate `DISCR128_EXACT_LO` and `DISCR128_EXACT_HI`,
125117/// and so on.
118+ ///
119+ ///
120+ /// The following pseudocode shows how to decode an enum value in a debugger:
121+ ///
122+ /// ```ignore
123+ ///
124+ /// fn find_active_variant(enum_value) -> (VariantName, VariantValue) {
125+ /// let is_128_bit = enum_value.has_field("tag128_lo");
126+ ///
127+ /// if !is_128_bit {
128+ /// // Note: `tag` can be a static field for enums with only one
129+ /// // inhabited variant.
130+ /// let tag = enum_value.field("tag").value;
131+ ///
132+ /// // For each variant, check if it is a match. Only one of them will match,
133+ /// // so if we find it we can return it immediately.
134+ /// for variant_field in enum_value.fields().filter(|f| f.name.starts_with("variant")) {
135+ /// if variant_field.has_field("DISCR_EXACT") {
136+ /// // This variant corresponds to a single tag value
137+ /// if variant_field.field("DISCR_EXACT").value == tag {
138+ /// return (variant_field.field("NAME"), variant_field.value);
139+ /// }
140+ /// } else {
141+ /// // This is a range variant
142+ /// let begin = variant_field.field("DISCR_BEGIN");
143+ /// let end = variant_field.field("DISCR_END");
144+ ///
145+ /// if tag >= begin && tag <= end {
146+ /// return (variant_field.field("NAME"), variant_field.value);
147+ /// }
148+ /// }
149+ /// }
150+ /// } else {
151+ /// // Basically the same as with smaller tags, we just have to
152+ /// // stitch the values together.
153+ /// let tag: u128 = (enum_value.field("tag128_lo").value as u128) |
154+ /// (enum_value.field("tag128_hi").value as u128 << 64);
155+ ///
156+ /// for variant_field in enum_value.fields().filter(|f| f.name.starts_with("variant")) {
157+ /// if variant_field.has_field("DISCR128_EXACT_LO") {
158+ /// let discr_exact = (variant_field.field("DISCR128_EXACT_LO" as u128) |
159+ /// (variant_field.field("DISCR128_EXACT_HI") as u128 << 64);
160+ ///
161+ /// // This variant corresponds to a single tag value
162+ /// if discr_exact.value == tag {
163+ /// return (variant_field.field("NAME"), variant_field.value);
164+ /// }
165+ /// } else {
166+ /// // This is a range variant
167+ /// let begin = (variant_field.field("DISCR128_BEGIN_LO").value as u128) |
168+ /// (variant_field.field("DISCR128_BEGIN_HI").value as u128 << 64);
169+ /// let end = (variant_field.field("DISCR128_END_LO").value as u128) |
170+ /// (variant_field.field("DISCR128_END_HI").value as u128 << 64);
171+ ///
172+ /// if tag >= begin && tag <= end {
173+ /// return (variant_field.field("NAME"), variant_field.value);
174+ /// }
175+ /// }
176+ /// }
177+ /// }
178+ ///
179+ /// // We should have found an active variant at this point.
180+ /// unreachable!();
181+ /// }
182+ ///
183+ /// ```
126184pub ( super ) fn build_enum_type_di_node < ' ll , ' tcx > (
127185 cx : & CodegenCx < ' ll , ' tcx > ,
128186 unique_type_id : UniqueTypeId < ' tcx > ,
@@ -290,7 +348,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
290348 build_field_di_node(
291349 cx,
292350 enum_type_di_node,
293- & variant_union_field_name( variant_index, None ) ,
351+ & variant_union_field_name( variant_index) ,
294352 // NOTE: We use the size and align of the entire type, not from variant_layout
295353 // since the later is sometimes smaller (if it has fewer fields).
296354 size_and_align_of( enum_type_and_layout) ,
@@ -691,8 +749,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
691749 . source_info
692750 . unwrap_or_else ( || ( unknown_file_metadata ( cx) , UNKNOWN_LINE_NUMBER ) ) ;
693751
694- let field_name =
695- variant_union_field_name ( variant_member_info. variant_index , dataful_variant_index) ;
752+ let field_name = variant_union_field_name ( variant_member_info. variant_index ) ;
696753 let ( size, align) = size_and_align_of ( enum_type_and_layout) ;
697754
698755 let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node (
@@ -795,10 +852,7 @@ struct VariantFieldInfo<'ll> {
795852 discr : DiscrResult ,
796853}
797854
798- fn variant_union_field_name (
799- variant_index : VariantIdx ,
800- dataful_variant_index : Option < VariantIdx > ,
801- ) -> Cow < ' static , str > {
855+ fn variant_union_field_name ( variant_index : VariantIdx ) -> Cow < ' static , str > {
802856 const PRE_ALLOCATED : [ & str ; 16 ] = [
803857 "variant0" ,
804858 "variant1" ,
@@ -818,10 +872,6 @@ fn variant_union_field_name(
818872 "variant15" ,
819873 ] ;
820874
821- if Some ( variant_index) == dataful_variant_index {
822- return Cow :: from ( "variant_fallback" ) ;
823- }
824-
825875 PRE_ALLOCATED
826876 . get ( variant_index. as_usize ( ) )
827877 . map ( |& s| Cow :: from ( s) )
0 commit comments