diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/debuginfo/mod.rs | 37 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 110 |
2 files changed, 94 insertions, 53 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 61e49fab6ff..833604c533c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -25,7 +25,7 @@ use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_index::vec::IndexVec; use rustc_middle::mir; -use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable}; use rustc_session::config::{self, DebugInfo}; @@ -307,9 +307,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn_abi: &FnAbi<'tcx, Ty<'tcx>>, maybe_definition_llfn: Option<&'ll Value>, ) -> &'ll DIScope { + let tcx = self.tcx; + let def_id = instance.def_id(); let containing_scope = get_containing_scope(self, instance); - let span = self.tcx.def_span(def_id); + let span = tcx.def_span(def_id); let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file); @@ -319,16 +321,24 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { }; let mut name = String::new(); - type_names::push_item_name(self.tcx(), def_id, false, &mut name); + type_names::push_item_name(tcx, def_id, false, &mut name); // Find the enclosing function, in case this is a closure. - let enclosing_fn_def_id = self.tcx().typeck_root_def_id(def_id); + let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id); + + // We look up the generics of the enclosing function and truncate the substs + // to their length in order to cut off extra stuff that might be in there for + // closures or generators. + let generics = tcx.generics_of(enclosing_fn_def_id); + let substs = instance.substs.truncate_to(tcx, generics); + + type_names::push_generic_params( + tcx, + tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs), + &mut name, + ); - // Get_template_parameters() will append a `<...>` clause to the function - // name if necessary. - let generics = self.tcx().generics_of(enclosing_fn_def_id); - let substs = instance.substs.truncate_to(self.tcx(), generics); - let template_parameters = get_template_parameters(self, generics, substs, &mut name); + let template_parameters = get_template_parameters(self, generics, substs); let linkage_name = &mangled_name_of_instance(self, instance).name; // Omit the linkage_name if it is the same as subprogram name. @@ -350,7 +360,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if self.sess().opts.optimize != config::OptLevel::No { spflags |= DISPFlags::SPFlagOptimized; } - if let Some((id, _)) = self.tcx.entry_fn(()) { + if let Some((id, _)) = tcx.entry_fn(()) { if id == def_id { spflags |= DISPFlags::SPFlagMainSubprogram; } @@ -429,14 +439,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { cx: &CodegenCx<'ll, 'tcx>, generics: &ty::Generics, substs: SubstsRef<'tcx>, - name_to_append_suffix_to: &mut String, ) -> &'ll DIArray { - type_names::push_generic_params( - cx.tcx, - cx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs), - name_to_append_suffix_to, - ); - if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 9687fd09a53..831c34d8f1f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -13,9 +13,9 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; +use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, AdtDef, ExistentialProjection, Ty, TyCtxt}; @@ -102,14 +102,14 @@ fn push_debuginfo_type_name<'tcx>( ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { if cpp_like_debuginfo { match mutbl { - hir::Mutability::Not => output.push_str("ptr_const$<"), - hir::Mutability::Mut => output.push_str("ptr_mut$<"), + Mutability::Not => output.push_str("ptr_const$<"), + Mutability::Mut => output.push_str("ptr_mut$<"), } } else { output.push('*'); match mutbl { - hir::Mutability::Not => output.push_str("const "), - hir::Mutability::Mut => output.push_str("mut "), + Mutability::Not => output.push_str("const "), + Mutability::Mut => output.push_str("mut "), } } @@ -131,8 +131,8 @@ fn push_debuginfo_type_name<'tcx>( output.push_str(mutbl.prefix_str()); } else if !is_slice_or_str { match mutbl { - hir::Mutability::Not => output.push_str("ref$<"), - hir::Mutability::Mut => output.push_str("ref_mut$<"), + Mutability::Not => output.push_str("ref$<"), + Mutability::Mut => output.push_str("ref_mut$<"), } } @@ -345,14 +345,39 @@ fn push_debuginfo_type_name<'tcx>( // processing visited.remove(t); } - ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { - let key = tcx.def_key(def_id); + ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) => { + // Name will be "{closure_env#0}<T1, T2, ...>", "{generator_env#0}<T1, T2, ...>", or + // "{async_fn_env#0}<T1, T2, ...>", etc. + let def_key = tcx.def_key(def_id); + if qualified { - let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let parent_def_id = DefId { index: def_key.parent.unwrap(), ..def_id }; push_item_name(tcx, parent_def_id, true, output); output.push_str("::"); } - push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output); + + let mut label = String::with_capacity(20); + write!(&mut label, "{}_env", generator_kind_label(tcx.generator_kind(def_id))).unwrap(); + + push_disambiguated_special_name( + &label, + def_key.disambiguated_data.disambiguator, + cpp_like_debuginfo, + output, + ); + + // We also need to add the generic arguments of the async fn/generator or + // the enclosing function (for closures or async blocks), so that we end + // up with a unique name for every instantiation. + + // Find the generics of the enclosing function, as defined in the source code. + let enclosing_fn_def_id = tcx.typeck_root_def_id(def_id); + let generics = tcx.generics_of(enclosing_fn_def_id); + + // Truncate the substs to the length of the above generics. This will cut off + // anything closure- or generator-specific. + let substs = substs.truncate_to(tcx, generics); + push_generic_params_internal(tcx, substs, output, visited); } // Type parameters from polymorphized functions. ty::Param(_) => { @@ -509,6 +534,29 @@ pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: & push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); } +fn generator_kind_label(generator_kind: Option<GeneratorKind>) -> &'static str { + match generator_kind { + Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) => "async_block", + Some(GeneratorKind::Async(AsyncGeneratorKind::Closure)) => "async_closure", + Some(GeneratorKind::Async(AsyncGeneratorKind::Fn)) => "async_fn", + Some(GeneratorKind::Gen) => "generator", + None => "closure", + } +} + +fn push_disambiguated_special_name( + label: &str, + disambiguator: u32, + cpp_like_debuginfo: bool, + output: &mut String, +) { + if cpp_like_debuginfo { + write!(output, "{}${}", label, disambiguator).unwrap(); + } else { + write!(output, "{{{}#{}}}", label, disambiguator).unwrap(); + } +} + fn push_unqualified_item_name( tcx: TyCtxt<'_>, def_id: DefId, @@ -519,42 +567,32 @@ fn push_unqualified_item_name( DefPathData::CrateRoot => { output.push_str(tcx.crate_name(def_id.krate).as_str()); } - DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { - let key = match tcx.generator_kind(def_id).unwrap() { - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn", - hir::GeneratorKind::Gen => "generator", - }; - // Generators look like closures, but we want to treat them differently - // in the debug info. - if cpp_like_debuginfo(tcx) { - write!(output, "{}${}", key, disambiguated_data.disambiguator).unwrap(); - } else { - write!(output, "{{{}#{}}}", key, disambiguated_data.disambiguator).unwrap(); - } + DefPathData::ClosureExpr => { + let label = generator_kind_label(tcx.generator_kind(def_id)); + + push_disambiguated_special_name( + label, + disambiguated_data.disambiguator, + cpp_like_debuginfo(tcx), + output, + ); } _ => match disambiguated_data.data.name() { DefPathDataName::Named(name) => { output.push_str(name.as_str()); } DefPathDataName::Anon { namespace } => { - if cpp_like_debuginfo(tcx) { - write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); - } else { - write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) - .unwrap(); - } + push_disambiguated_special_name( + namespace.as_str(), + disambiguated_data.disambiguator, + cpp_like_debuginfo(tcx), + output, + ); } }, }; } -// Pushes the generic parameters in the given `InternalSubsts` to the output string. -// This ignores region parameters, since they can't reliably be -// reconstructed for items from non-local crates. For local crates, this -// would be possible but with inlining and LTO we have to use the least -// common denominator - otherwise we would run into conflicts. fn push_generic_params_internal<'tcx>( tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, |
