about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-03-27 12:43:47 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-03-27 12:43:47 +0000
commite48d7d242fcf378d66d27dddea546029239bd5c6 (patch)
treeeceb9490802c307dc8aebdaebb8907559d85b407
parentc76c269aa466b786d4ca3a78dae9cb84912406ed (diff)
downloadrust-e48d7d242fcf378d66d27dddea546029239bd5c6.tar.gz
rust-e48d7d242fcf378d66d27dddea546029239bd5c6.zip
Emit namespace debuginfo
-rw-r--r--src/base.rs2
-rw-r--r--src/debuginfo/mod.rs63
2 files changed, 60 insertions, 5 deletions
diff --git a/src/base.rs b/src/base.rs
index dbce6d165d2..4e60f820594 100644
--- a/src/base.rs
+++ b/src/base.rs
@@ -70,7 +70,7 @@ pub(crate) fn codegen_fn<'tcx>(
     let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);
 
     let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
-        Some(debug_context.define_function(tcx, &symbol_name, mir.span))
+        Some(debug_context.define_function(tcx, instance, &symbol_name, mir.span))
     } else {
         None
     };
diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs
index 44ee2b822a9..2b5f472c5fc 100644
--- a/src/debuginfo/mod.rs
+++ b/src/debuginfo/mod.rs
@@ -13,6 +13,8 @@ use gimli::write::{
 };
 use gimli::{AArch64, Encoding, Format, LineEncoding, Register, RiscV, RunTimeEndian, X86_64};
 use indexmap::IndexSet;
+use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_hir::def_id::DefIdMap;
 use rustc_session::Session;
 
 pub(crate) use self::emit::{DebugReloc, DebugRelocName};
@@ -29,6 +31,7 @@ pub(crate) struct DebugContext {
     dwarf: DwarfUnit,
     unit_range_list: RangeList,
     stack_pointer_register: Register,
+    namespace_map: DefIdMap<UnitEntryId>,
 
     should_remap_filepaths: bool,
 }
@@ -122,14 +125,42 @@ impl DebugContext {
             dwarf,
             unit_range_list: RangeList(Vec::new()),
             stack_pointer_register,
+            namespace_map: DefIdMap::default(),
             should_remap_filepaths,
         }
     }
 
-    pub(crate) fn define_function(
+    fn item_namespace(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> UnitEntryId {
+        if let Some(&scope) = self.namespace_map.get(&def_id) {
+            return scope;
+        }
+
+        let def_key = tcx.def_key(def_id);
+        let parent_scope = def_key
+            .parent
+            .map(|parent| self.item_namespace(tcx, DefId { krate: def_id.krate, index: parent }))
+            .unwrap_or(self.dwarf.unit.root());
+
+        let namespace_name = {
+            let mut output = String::new();
+            type_names::push_item_name(tcx, def_id, false, &mut output);
+            output
+        };
+        let namespace_name_id = self.dwarf.strings.add(namespace_name);
+
+        let scope = self.dwarf.unit.add(parent_scope, gimli::DW_TAG_namespace);
+        let scope_entry = self.dwarf.unit.get_mut(scope);
+        scope_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(namespace_name_id));
+
+        self.namespace_map.insert(def_id, scope);
+        scope
+    }
+
+    pub(crate) fn define_function<'tcx>(
         &mut self,
-        tcx: TyCtxt<'_>,
-        name: &str,
+        tcx: TyCtxt<'tcx>,
+        instance: Instance<'tcx>,
+        linkage_name: &str,
         function_span: Span,
     ) -> FunctionDebugContext {
         let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span);
@@ -137,10 +168,31 @@ impl DebugContext {
         let file_id = self.add_source_file(&file);
 
         // FIXME: add to appropriate scope instead of root
-        let scope = self.dwarf.unit.root();
+        let scope = self.item_namespace(tcx, tcx.parent(instance.def_id()));
+
+        let mut name = String::new();
+        type_names::push_item_name(tcx, instance.def_id(), false, &mut name);
+
+        // Find the enclosing function, in case this is a closure.
+        let enclosing_fn_def_id = tcx.typeck_root_def_id(instance.def_id());
+
+        // We look up the generics of the enclosing function and truncate the args
+        // to their length in order to cut off extra stuff that might be in there for
+        // closures or coroutines.
+        let generics = tcx.generics_of(enclosing_fn_def_id);
+        let args = instance.args.truncate_to(tcx, generics);
+
+        type_names::push_generic_params(
+            tcx,
+            tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
+            enclosing_fn_def_id,
+            &mut name,
+        );
 
         let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_subprogram);
         let entry = self.dwarf.unit.get_mut(entry_id);
+        let linkage_name_id =
+            if name != linkage_name { Some(self.dwarf.strings.add(linkage_name)) } else { None };
         let name_id = self.dwarf.strings.add(name);
 
         // These will be replaced in FunctionDebugContext::finalize. They are
@@ -153,6 +205,9 @@ impl DebugContext {
         frame_base_expr.op_reg(self.stack_pointer_register);
         entry.set(gimli::DW_AT_frame_base, AttributeValue::Exprloc(frame_base_expr));
 
+        if let Some(linkage_name_id) = linkage_name_id {
+            entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
+        }
         // Gdb requires DW_AT_name. Otherwise the DW_TAG_subprogram is skipped.
         // FIXME only include the function name and not the full mangled symbol
         entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));