Hello gentlemen.

Both of you suggested I revert my removal of deferred_asm_names from dwarf2out, since it may cause mangling of DECLs that may ultimately not be needed.

A little background...

This all started with a regression for pr44197.c in the branch. What is happening is that the C front-end uses the presence of DECL_ASSEMBLER_NAME to determine if an __asm__ alias is already present for a symbol. Unfortunately, passing said symbol through dwarf2out_early_global_decl, triggers DECL_ASSEMBLER_NAME, so all symbols will have their assembler name set, and there is no way to diagnose multiple conflicting __asm__ aliases.

Having thought about this some more, unless I'm misunderstanding something, I don't thing we'll cause mangling of DECLs that may not be eventually mangled. I mean, everything that ends up in deferred_asm_name, will ultimately end up in a DIE that will ultimately get a mangled DECL_ASSEMBLER_NAME. It's not like we're pruning unused DIEs _before_ we iterate through deferred_asm_name and generate DECL_ASSEMBLER_NAMEs for them (in mainline).

For that matter, the original reason for deferred_asm_name was not to avoid mangling but to avoid template instantiation (something which Jason fixed in mainline as part of my original removal of deferred_asm_name). The original raison d'etre is here:

        https://gcc.gnu.org/ml/gcc-patches/2009-06/msg00030.html

(Unless of course, another reason for deferred_asm_names was to avoid bloating memory usage earlier in the compilation process??? Although if we're going to generate the field, does it matter that much if we do it earlier?)

Be that as it may, even if you agree with me, the pr44197.c regression needs to be addressed, and resurrecting deferred_asm_names does the trick of delaying setting DECL_ASSEMBLER_NAME until after the parser has finished.

With this patch I have moved the flushing of deferred_asm_names to dwarf2out_early_finish instead of dwarf2out_finish, so it happens after the parser has finished, but does not live past LTO and upset Richi ;-).

Could either of you comment on this, so I may at least add a relevant comment to the reason for deferred_asm_names (whether it exists to avoid parser insanity or to avoid unnecessary mangling)?

Either way, I'm committing to the branch.  Regressions down to 2.

Aldy
commit c6cb62c9e8fbd60d800ed3aa709a50b77fedf9c8
Author: Aldy Hernandez <al...@redhat.com>
Date:   Thu Apr 30 15:52:12 2015 -0700

    Revert removal of deferred_asm_name and move its clearing to
    dwarf2out_early_finish.

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index f512ec7..c51cea1 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2806,6 +2806,10 @@ static GTY(()) comdat_type_node *comdat_type_list;
 /* A list of DIEs with a NULL parent waiting to be relocated.  */
 static GTY(()) limbo_die_node *limbo_die_list;
 
+/* A list of DIEs for which we may have to generate
+   DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set.  */
+static GTY(()) limbo_die_node *deferred_asm_name;
+
 struct dwarf_file_hasher : ggc_hasher<dwarf_file_data *>
 {
   typedef const char *compare_type;
@@ -17237,9 +17241,22 @@ add_linkage_name (dw_die_ref die, tree decl)
       && (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
       && TREE_PUBLIC (decl)
       && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
-      && die->die_tag != DW_TAG_member
-      && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-    add_linkage_attr (die, decl);
+      && die->die_tag != DW_TAG_member)
+    {
+      /* Defer until we have an assembler name set.  */
+      if (!DECL_ASSEMBLER_NAME_SET_P (decl))
+       {
+         limbo_die_node *asm_name;
+
+         asm_name = ggc_cleared_alloc<limbo_die_node> ();
+         asm_name->die = die;
+         asm_name->created_for = decl;
+         asm_name->next = deferred_asm_name;
+         deferred_asm_name = asm_name;
+       }
+      else if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+       add_linkage_attr (die, decl);
+    }
 }
 
 /* Add a DW_AT_name attribute and source coordinate attribute for the
@@ -23882,6 +23899,37 @@ comdat_type_hasher::equal (const comdat_type_node 
*type_node_1,
                     DWARF_TYPE_SIGNATURE_SIZE));
 }
 
+/* Move a DW_AT_{,MIPS_}linkage_name attribute just added to dw_die_ref
+   to the location it would have been added, should we know its
+   DECL_ASSEMBLER_NAME when we added other attributes.  This will
+   probably improve compactness of debug info, removing equivalent
+   abbrevs, and hide any differences caused by deferring the
+   computation of the assembler name, triggered by e.g. PCH.  */
+
+static inline void
+move_linkage_attr (dw_die_ref die)
+{
+  unsigned ix = vec_safe_length (die->die_attr);
+  dw_attr_node linkage = (*die->die_attr)[ix - 1];
+
+  gcc_assert (linkage.dw_attr == DW_AT_linkage_name
+             || linkage.dw_attr == DW_AT_MIPS_linkage_name);
+
+  while (--ix > 0)
+    {
+      dw_attr_node *prev = &(*die->die_attr)[ix - 1];
+
+      if (prev->dw_attr == DW_AT_decl_line || prev->dw_attr == DW_AT_name)
+       break;
+    }
+
+  if (ix != vec_safe_length (die->die_attr) - 1)
+    {
+      die->die_attr->pop ();
+      die->die_attr->quick_insert (ix, linkage);
+    }
+}
+
 /* Helper function for resolve_addr, mark DW_TAG_base_type nodes
    referenced from typed stack ops and count how often they are used.  */
 
@@ -25059,7 +25107,7 @@ dwarf2out_finish (const char *filename)
                || !node->die->dumped_early);
 
   /* Flush out any latecomers to the limbo party.  */
-  dwarf2out_early_finish();
+  dwarf2out_early_finish ();
 
   /* PCH might result in DW_AT_producer string being restored from the
      header compilation, so always fill it with empty string initially
@@ -25407,6 +25455,25 @@ dwarf2out_finish (const char *filename)
 static void
 dwarf2out_early_finish (void)
 {
+  limbo_die_node *node, *next_node;
+
+  /* Add DW_AT_linkage_name for all deferred DIEs.  */
+  for (node = deferred_asm_name; node; node = node->next)
+    {
+      tree decl = node->created_for;
+      /* When generating LTO bytecode we can not generate new assembler
+         names at this point and all important decls got theirs via
+        free-lang-data.  */
+      if (((!flag_generate_lto && !flag_generate_offload)
+          || DECL_ASSEMBLER_NAME_SET_P (decl))
+         && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+       {
+         add_linkage_attr (node->die, decl);
+         move_linkage_attr (node->die);
+       }
+    }
+  deferred_asm_name = NULL;
+
   /* Traverse the limbo die list, and add parent/child links.  The only
      dies without parents that should be here are concrete instances of
      inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
@@ -25415,7 +25482,6 @@ dwarf2out_early_finish (void)
 
      The point here is to flush out the limbo list so that it is empty
      and we don't need to stream it for LTO.  */
-  limbo_die_node *node, *next_node;
   for (node = limbo_die_list; node; node = next_node)
     {
       dw_die_ref die = node->die;

Reply via email to