@@ -105,14 +105,6 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
105
105
/// that case. Both `DISCR_BEGIN` and `DISCR_END` are inclusive bounds.
106
106
/// Note that these ranges can wrap around, so that `DISCR_END < DISCR_BEGIN`.
107
107
///
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
- ///
116
108
/// Single-variant enums don't actually have a tag field. In this case we
117
109
/// emit a static tag field (that always has the value 0) so we can use the
118
110
/// same representation (and NatVis).
@@ -123,6 +115,72 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0;
123
115
/// Instead of the `tag` field, we generate two fields `tag128_lo` and `tag128_hi`,
124
116
/// Instead of `DISCR_EXACT`, we generate `DISCR128_EXACT_LO` and `DISCR128_EXACT_HI`,
125
117
/// 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
+ /// ```
126
184
pub ( super ) fn build_enum_type_di_node < ' ll , ' tcx > (
127
185
cx : & CodegenCx < ' ll , ' tcx > ,
128
186
unique_type_id : UniqueTypeId < ' tcx > ,
@@ -290,7 +348,7 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
290
348
build_field_di_node(
291
349
cx,
292
350
enum_type_di_node,
293
- & variant_union_field_name( variant_index, None ) ,
351
+ & variant_union_field_name( variant_index) ,
294
352
// NOTE: We use the size and align of the entire type, not from variant_layout
295
353
// since the later is sometimes smaller (if it has fewer fields).
296
354
size_and_align_of( enum_type_and_layout) ,
@@ -691,8 +749,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>(
691
749
. source_info
692
750
. unwrap_or_else ( || ( unknown_file_metadata ( cx) , UNKNOWN_LINE_NUMBER ) ) ;
693
751
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 ) ;
696
753
let ( size, align) = size_and_align_of ( enum_type_and_layout) ;
697
754
698
755
let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node (
@@ -795,10 +852,7 @@ struct VariantFieldInfo<'ll> {
795
852
discr : DiscrResult ,
796
853
}
797
854
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 > {
802
856
const PRE_ALLOCATED : [ & str ; 16 ] = [
803
857
"variant0" ,
804
858
"variant1" ,
@@ -818,10 +872,6 @@ fn variant_union_field_name(
818
872
"variant15" ,
819
873
] ;
820
874
821
- if Some ( variant_index) == dataful_variant_index {
822
- return Cow :: from ( "variant_fallback" ) ;
823
- }
824
-
825
875
PRE_ALLOCATED
826
876
. get ( variant_index. as_usize ( ) )
827
877
. map ( |& s| Cow :: from ( s) )
0 commit comments