about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa/src/debuginfo
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_ssa/src/debuginfo')
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs59
1 files changed, 50 insertions, 9 deletions
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 626c71abf63..1f3e9493318 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -3,7 +3,8 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt};
+use rustc_target::abi::{TagEncoding, Variants};
 
 use std::fmt::Write;
 
@@ -46,14 +47,10 @@ pub fn push_debuginfo_type_name<'tcx>(
         ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
         ty::Adt(def, substs) => {
             if def.is_enum() && cpp_like_names {
-                output.push_str("_enum<");
-            }
-
-            push_item_name(tcx, def.did, qualified, output);
-            push_type_params(tcx, substs, output, visited);
-
-            if def.is_enum() && cpp_like_names {
-                output.push('>');
+                msvc_enum_fallback(tcx, t, def, substs, output, visited);
+            } else {
+                push_item_name(tcx, def.did, qualified, output);
+                push_type_params(tcx, substs, output, visited);
             }
         }
         ty::Tuple(component_types) => {
@@ -241,6 +238,50 @@ pub fn push_debuginfo_type_name<'tcx>(
         }
     }
 
+    fn msvc_enum_fallback(
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        def: &AdtDef,
+        substs: SubstsRef<'tcx>,
+        output: &mut String,
+        visited: &mut FxHashSet<Ty<'tcx>>,
+    ) {
+        let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error");
+
+        if let Variants::Multiple {
+            tag_encoding: TagEncoding::Niche { dataful_variant, .. },
+            tag,
+            variants,
+            ..
+        } = &layout.variants
+        {
+            let dataful_variant_layout = &variants[*dataful_variant];
+
+            // calculate the range of values for the dataful variant
+            let dataful_discriminant_range =
+                &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
+
+            let min = dataful_discriminant_range.start();
+            let min = tag.value.size(&tcx).truncate(*min);
+
+            let max = dataful_discriminant_range.end();
+            let max = tag.value.size(&tcx).truncate(*max);
+
+            output.push_str("_enum<");
+            push_item_name(tcx, def.did, true, output);
+            push_type_params(tcx, substs, output, visited);
+
+            let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
+
+            output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name));
+        } else {
+            output.push_str("_enum<");
+            push_item_name(tcx, def.did, true, output);
+            push_type_params(tcx, substs, output, visited);
+            output.push('>');
+        }
+    }
+
     fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
         if qualified {
             output.push_str(&tcx.crate_name(def_id.krate).as_str());