Die symbols are used for external references.
Typically during LTO, early debug emits 'die_symbol+offset' for each
possibly referenced DIE in future. Partitions in LTRANS phase then
use these references.

Originally die symbols are handled only in root comp_unit and
in attributes.

This patch allows die symbols to be attached to any DIE.
References then choose closest parent with die symbol.

gcc/ChangeLog:

        * dwarf2out.cc (dwarf2out_die_ref_for_decl):
          Choose closest parent with die_symbol.
        (output_die): Output asm label.
        (output_unit_die_symbol_list): New.
        (output_comp_unit): Output die_symbol list.
        (reset_dies): Reset all die_symbols.
        (dwarf2out_finish): Don't reset comp_unit die_symbol.
---
 gcc/dwarf2out.cc | 80 +++++++++++++++++++++++++++---------------------
 1 file changed, 45 insertions(+), 35 deletions(-)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index e10a5c78fe9..bf1ac45ed73 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -6039,14 +6039,14 @@ dwarf2out_die_ref_for_decl (tree decl, const char **sym,
 
   /* Similar to get_ref_die_offset_label, but using the "correct"
      label.  */
-  *off = die->die_offset;
-  while (die->die_parent)
+  unsigned HOST_WIDE_INT unit_offset = die->die_offset;
+  while (die->die_parent && (die->comdat_type_p || !die->die_id.die_symbol))
     die = die->die_parent;
-  /* For the containing CU DIE we compute a die_symbol in
+  /* Root CU DIE always contains die_symbol computed in
      compute_comp_unit_symbol.  */
-  if (die->die_tag == DW_TAG_compile_unit)
+  if (!die->comdat_type_p && die->die_id.die_symbol)
     {
-      gcc_assert (die->die_id.die_symbol != NULL);
+      *off = unit_offset - die->die_offset;
       *sym = die->die_id.die_symbol;
       return true;
     }
@@ -10798,6 +10798,10 @@ output_die (dw_die_ref die)
   unsigned long size;
   unsigned ix;
 
+  if ((flag_generate_lto || flag_generate_offload)
+      && !die->comdat_type_p && die->die_id.die_symbol)
+    ASM_OUTPUT_LABEL (asm_out_file, die->die_id.die_symbol);
+
   dw2_asm_output_data_uleb128 (die->die_abbrev, "(DIE (%#lx) %s)",
                               (unsigned long)die->die_offset,
                               dwarf_tag_name (die->die_tag));
@@ -11228,14 +11232,41 @@ output_compilation_unit_header (enum dwarf_unit_type 
ut)
     dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
 }
 
+/* Output list of all die symbols in the DIE.  */
+static void
+output_unit_die_symbol_list (dw_die_ref die)
+{
+  if (!die->comdat_type_p && die->die_id.die_symbol)
+    {
+      const char* sym = die->die_id.die_symbol;
+      /* ???  No way to get visibility assembled without a decl.  */
+      tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+                             get_identifier (sym), char_type_node);
+      TREE_PUBLIC (decl) = true;
+      TREE_STATIC (decl) = true;
+      DECL_ARTIFICIAL (decl) = true;
+      DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+      DECL_VISIBILITY_SPECIFIED (decl) = true;
+      targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
+#ifdef ASM_WEAKEN_LABEL
+      /* We prefer a .weak because that handles duplicates from duplicate
+        archive members in a graceful way.  */
+      ASM_WEAKEN_LABEL (asm_out_file, sym);
+#else
+      targetm.asm_out.globalize_label (asm_out_file, sym);
+#endif
+    }
+
+  dw_die_ref c;
+  FOR_EACH_CHILD (die, c, output_unit_die_symbol_list (c));
+}
+
 /* Output the compilation unit DIE and its children.  */
 
 static void
 output_comp_unit (dw_die_ref die, int output_if_empty,
                  const unsigned char *dwo_id)
 {
-  const char *oldsym;
-
   /* Unless we are outputting main CU, we may throw away empty ones.  */
   if (!output_if_empty && die->die_child == NULL)
     return;
@@ -11267,34 +11298,12 @@ output_comp_unit (dw_die_ref die, int output_if_empty,
                     : DWARF_COMPILE_UNIT_HEADER_SIZE);
   calc_die_sizes (die);
 
-  oldsym = die->die_id.die_symbol;
-
   switch_to_section (debug_info_section);
   ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label);
   info_section_emitted = true;
 
-  /* For LTO cross unit DIE refs we want a symbol on the start of the
-     debuginfo section, not on the CU DIE.  */
-  if ((flag_generate_lto || flag_generate_offload) && oldsym)
-    {
-      /* ???  No way to get visibility assembled without a decl.  */
-      tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
-                             get_identifier (oldsym), char_type_node);
-      TREE_PUBLIC (decl) = true;
-      TREE_STATIC (decl) = true;
-      DECL_ARTIFICIAL (decl) = true;
-      DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
-      DECL_VISIBILITY_SPECIFIED (decl) = true;
-      targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
-#ifdef ASM_WEAKEN_LABEL
-      /* We prefer a .weak because that handles duplicates from duplicate
-         archive members in a graceful way.  */
-      ASM_WEAKEN_LABEL (asm_out_file, oldsym);
-#else
-      targetm.asm_out.globalize_label (asm_out_file, oldsym);
-#endif
-      ASM_OUTPUT_LABEL (asm_out_file, oldsym);
-    }
+  if (flag_generate_lto || flag_generate_offload)
+    output_unit_die_symbol_list (die);
 
   /* Output debugging information.  */
   output_compilation_unit_header (dwo_id
@@ -11309,7 +11318,7 @@ output_comp_unit (dw_die_ref die, int output_if_empty,
 
   /* Leave the marks on the main CU, so we can check them in
      output_pubnames.  */
-  if (oldsym)
+  if (die->die_id.die_symbol)
     unmark_dies (die);
 }
 
@@ -32297,6 +32306,10 @@ reset_dies (dw_die_ref die)
   die->die_abbrev = 0;
   remove_AT (die, DW_AT_sibling);
 
+  /* Reset die symbols so we don't output them twice.  */
+  if (!die->comdat_type_p)
+    die->die_id.die_symbol = NULL;
+
   FOR_EACH_CHILD (die, c, reset_dies (c));
 }
 
@@ -32388,9 +32401,6 @@ dwarf2out_finish (const char *filename)
            reset_dies (ctnode->root_die);
        }
 
-      /* Reset die CU symbol so we don't output it twice.  */
-      comp_unit_die ()->die_id.die_symbol = NULL;
-
       /* Remove DW_AT_macro and DW_AT_stmt_list from the early output.  */
       remove_AT (comp_unit_die (), DW_AT_stmt_list);
       if (have_macinfo)
-- 
2.47.0

Reply via email to