re PR debug/83941 (Debug info generated with -flto contains useless forwarders)
authorRichard Biener <rguenther@suse.de>
Tue, 25 Sep 2018 07:30:56 +0000 (07:30 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 25 Sep 2018 07:30:56 +0000 (07:30 +0000)
2018-09-25  Richard Biener  <rguenther@suse.de>

PR debug/83941
* dwarf2out.c (struct sym_off_pair): New.
(external_die_map): New global.
(lookup_decl_die): When in LTO create DIEs lazily from the
external_die_map.
(lookup_block_die): New function, create DIEs lazily in LTO.
(equate_block_to_die): New function.
(dwarf2out_die_ref_for_decl): During WPA get the association
from the external DIE map.
(dwarf2out_register_external_die): Record mapping into the
external DIE map.
(maybe_create_die_with_external_ref): New function split out from
DIE generation part of old dwarf2out_register_external_die.
(add_abstract_origin_attribute): Do not return the DIE.  When
in LTO reference externals directly.
(dwarf2out_abstract_function): When in LTO ignore calls for
decls with external DIEs (already present abstract instances).
(gen_call_site_die): Adjust.
(add_high_low_attributes): Likewise.
(gen_lexical_block_die): Likewise.
(gen_inlined_subroutine_die): Likewie.
(gen_block_die): Likewise.
(dwarf2out_inline_entry): Likewise.
(dwarf2out_early_finish): In LTRANS phase create DW_TAG_imported_unit
DIEs.

From-SVN: r264564

gcc/ChangeLog
gcc/dwarf2out.c

index 780cf78cf60750212988afdb31fab5ccbd7f2917..61422ada6f1383452ec362231bc2bca2224cfe33 100644 (file)
@@ -1,3 +1,31 @@
+2018-09-25  Richard Biener  <rguenther@suse.de>
+
+       PR debug/83941
+       * dwarf2out.c (struct sym_off_pair): New.
+       (external_die_map): New global.
+       (lookup_decl_die): When in LTO create DIEs lazily from the
+       external_die_map.
+       (lookup_block_die): New function, create DIEs lazily in LTO.
+       (equate_block_to_die): New function.
+       (dwarf2out_die_ref_for_decl): During WPA get the association
+       from the external DIE map.
+       (dwarf2out_register_external_die): Record mapping into the
+       external DIE map.
+       (maybe_create_die_with_external_ref): New function split out from
+       DIE generation part of old dwarf2out_register_external_die.
+       (add_abstract_origin_attribute): Do not return the DIE.  When
+       in LTO reference externals directly.
+       (dwarf2out_abstract_function): When in LTO ignore calls for
+       decls with external DIEs (already present abstract instances).
+       (gen_call_site_die): Adjust.
+       (add_high_low_attributes): Likewise.
+       (gen_lexical_block_die): Likewise.
+       (gen_inlined_subroutine_die): Likewie.
+       (gen_block_die): Likewise.
+       (dwarf2out_inline_entry): Likewise.
+       (dwarf2out_early_finish): In LTRANS phase create DW_TAG_imported_unit
+       DIEs.
+
 2018-09-25  Martin Liska  <mliska@suse.cz>
 
        * ipa-fnsummary.c (estimate_node_size_and_time): Scale by two
index 66ee839b5cb596bc449e0d5296068d9d74e80b90..6f45794caf6f10e5d5249333dffb3596fed286b8 100644 (file)
@@ -3822,7 +3822,7 @@ static inline void add_bit_offset_attribute (dw_die_ref, tree,
                                             struct vlr_context *);
 static void add_bit_size_attribute (dw_die_ref, tree);
 static void add_prototyped_attribute (dw_die_ref, tree);
-static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
+static void add_abstract_origin_attribute (dw_die_ref, tree);
 static void add_pure_or_virtual_attribute (dw_die_ref, tree);
 static void add_src_coords_attributes (dw_die_ref, tree);
 static void add_name_and_src_coords_attributes (dw_die_ref, tree, bool = false);
@@ -5746,6 +5746,14 @@ equate_type_number_to_die (tree type, dw_die_ref type_die)
   TYPE_SYMTAB_DIE (type) = type_die;
 }
 
+static dw_die_ref maybe_create_die_with_external_ref (tree);
+struct GTY(()) sym_off_pair 
+{
+  const char * GTY((skip)) sym;
+  unsigned HOST_WIDE_INT off;
+};
+static GTY(()) hash_map<tree, sym_off_pair> *external_die_map;
+
 /* Returns a hash value for X (which really is a die_struct).  */
 
 inline hashval_t
@@ -5770,7 +5778,11 @@ lookup_decl_die (tree decl)
   dw_die_ref *die = decl_die_table->find_slot_with_hash (decl, DECL_UID (decl),
                                                         NO_INSERT);
   if (!die)
-    return NULL;
+    {
+      if (in_lto_p)
+       return maybe_create_die_with_external_ref (decl);
+      return NULL;
+    }
   if ((*die)->removed)
     {
       decl_die_table->clear_slot (die);
@@ -5780,6 +5792,27 @@ lookup_decl_die (tree decl)
 }
 
 
+/* Return the DIE associated with BLOCK.  */
+
+static inline dw_die_ref
+lookup_block_die (tree block)
+{
+  dw_die_ref die = BLOCK_DIE (block);
+  if (!die && in_lto_p)
+    return maybe_create_die_with_external_ref (block);
+  return die;
+}
+
+/* Associate DIE with BLOCK.  */
+
+static inline void
+equate_block_to_die (tree block, dw_die_ref die)
+{
+  BLOCK_DIE (block) = die;
+}
+#undef BLOCK_DIE
+
+
 /* For DECL which might have early dwarf output query a SYMBOL + OFFSET
    style reference.  Return true if we found one refering to a DIE for
    DECL, otherwise return false.  */
@@ -5790,32 +5823,27 @@ dwarf2out_die_ref_for_decl (tree decl, const char **sym,
 {
   dw_die_ref die;
 
-  if (in_lto_p && !decl_die_table)
-    return false;
+  if (in_lto_p)
+    {
+      /* During WPA stage and incremental linking we use a hash-map
+        to store the decl <-> label + offset map.  */
+      if (!external_die_map)
+       return false;
+      sym_off_pair *desc = external_die_map->get (decl);
+      if (!desc)
+       return false;
+      *sym = desc->sym;
+      *off = desc->off;
+      return true;
+    }
 
   if (TREE_CODE (decl) == BLOCK)
-    die = BLOCK_DIE (decl);
+    die = lookup_block_die (decl);
   else
     die = lookup_decl_die (decl);
   if (!die)
     return false;
 
-  /* During WPA stage and incremental linking we currently use DIEs
-     to store the decl <-> label + offset map.  That's quite inefficient
-     but it works for now.  */
-  if (in_lto_p)
-    {
-      dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
-      if (!ref)
-       {
-         gcc_assert (die == comp_unit_die ());
-         return false;
-       }
-      *off = ref->die_offset;
-      *sym = ref->die_id.die_symbol;
-      return true;
-    }
-
   /* Similar to get_ref_die_offset_label, but using the "correct"
      label.  */
   *off = die->die_offset;
@@ -5837,6 +5865,8 @@ add_AT_external_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind,
 {
   /* Create a fake DIE that contains the reference.  Don't use
      new_die because we don't want to end up in the limbo list.  */
+  /* ???  We probably want to share these, thus put a ref to the DIE
+     we create here to the external_die_map entry.  */
   dw_die_ref ref = new_die_raw (die->die_tag);
   ref->die_id.die_symbol = IDENTIFIER_POINTER (get_identifier (symbol));
   ref->die_offset = offset;
@@ -5854,13 +5884,33 @@ dwarf2out_register_external_die (tree decl, const char *sym,
   if (debug_info_level == DINFO_LEVEL_NONE)
     return;
 
-  if ((flag_wpa
-       || flag_incremental_link == INCREMENTAL_LINK_LTO) && !decl_die_table)
-    decl_die_table = hash_table<decl_die_hasher>::create_ggc (1000);
+  if (!external_die_map)
+    external_die_map = hash_map<tree, sym_off_pair>::create_ggc (1000);
+  gcc_checking_assert (!external_die_map->get (decl));
+  sym_off_pair p = { IDENTIFIER_POINTER (get_identifier (sym)), off };
+  external_die_map->put (decl, p);
+}
+
+/* If we have a registered external DIE for DECL return a new DIE for
+   the concrete instance with an appropriate abstract origin.  */
+
+static dw_die_ref
+maybe_create_die_with_external_ref (tree decl)
+{
+  if (!external_die_map)
+    return NULL;
+  sym_off_pair *desc = external_die_map->get (decl);
+  if (!desc)
+    return NULL;
+
+  const char *sym = desc->sym;
+  unsigned HOST_WIDE_INT off = desc->off;
 
-  dw_die_ref die
-    = TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
+  in_lto_p = false;
+  dw_die_ref die = (TREE_CODE (decl) == BLOCK
+                   ? lookup_block_die (decl) : lookup_decl_die (decl));
   gcc_assert (!die);
+  in_lto_p = true;
 
   tree ctx;
   dw_die_ref parent = NULL;
@@ -5872,7 +5922,7 @@ dwarf2out_register_external_die (tree decl, const char *sym,
       /* ???  We do not output DIEs for all scopes thus skip as
         many DIEs as needed.  */
       while (TREE_CODE (ctx) == BLOCK
-            && !BLOCK_DIE (ctx))
+            && !lookup_block_die (ctx))
        ctx = BLOCK_SUPERCONTEXT (ctx);
     }
   else
@@ -5887,7 +5937,7 @@ dwarf2out_register_external_die (tree decl, const char *sym,
   if (ctx)
     {
       if (TREE_CODE (ctx) == BLOCK)
-       parent = BLOCK_DIE (ctx);
+       parent = lookup_block_die (ctx);
       else if (TREE_CODE (ctx) == TRANSLATION_UNIT_DECL
               /* Keep the 1:1 association during WPA.  */
               && !flag_wpa
@@ -5914,18 +5964,14 @@ dwarf2out_register_external_die (tree decl, const char *sym,
   switch (TREE_CODE (decl))
     {
     case TRANSLATION_UNIT_DECL:
-      if (! flag_wpa && flag_incremental_link != INCREMENTAL_LINK_LTO)
-       {
-         die = comp_unit_die ();
-         dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
-         add_AT_external_die_ref (import, DW_AT_import, sym, off);
-         /* We re-target all CU decls to the LTRANS CU DIE, so no need
-            to create a DIE for the original CUs.  */
-         return;
-       }
-      /* Keep the 1:1 association during WPA.  */
-      die = new_die (DW_TAG_compile_unit, NULL, decl);
-      break;
+      {
+       die = comp_unit_die ();
+       dw_die_ref import = new_die (DW_TAG_imported_unit, die, NULL_TREE);
+       add_AT_external_die_ref (import, DW_AT_import, sym, off);
+       /* We re-target all CU decls to the LTRANS CU DIE, so no need
+          to create a DIE for the original CUs.  */
+       return die;
+      }
     case NAMESPACE_DECL:
       if (is_fortran (decl))
        die = new_die (DW_TAG_module, parent, decl);
@@ -5957,7 +6003,7 @@ dwarf2out_register_external_die (tree decl, const char *sym,
       gcc_unreachable ();
     }
   if (TREE_CODE (decl) == BLOCK)
-    BLOCK_DIE (decl) = die;
+    equate_block_to_die (decl, die);
   else
     equate_decl_number_to_die (decl, die);
 
@@ -5965,6 +6011,8 @@ dwarf2out_register_external_die (tree decl, const char *sym,
 
   /* Add a reference to the DIE providing early debug at $sym + off.  */
   add_AT_external_die_ref (die, DW_AT_abstract_origin, sym, off);
+
+  return die;
 }
 
 /* Returns a hash value for X (which really is a var_loc_list).  */
@@ -21081,28 +21129,28 @@ add_prototyped_attribute (dw_die_ref die, tree func_type)
    by looking in the type declaration, the object declaration equate table or
    the block mapping.  */
 
-static inline dw_die_ref
+static inline void
 add_abstract_origin_attribute (dw_die_ref die, tree origin)
 {
   dw_die_ref origin_die = NULL;
 
   if (DECL_P (origin))
     {
-      dw_die_ref c;
-      origin_die = lookup_decl_die (origin);
-      /* "Unwrap" the decls DIE which we put in the imported unit context.
-         We are looking for the abstract copy here.  */
+      sym_off_pair *desc;
       if (in_lto_p
-         && origin_die
-         && (c = get_AT_ref (origin_die, DW_AT_abstract_origin))
-         /* ???  Identify this better.  */
-         && c->with_offset)
-       origin_die = c;
+         && external_die_map
+         && (desc = external_die_map->get (origin)))
+       {
+         add_AT_external_die_ref (die, DW_AT_abstract_origin,
+                                  desc->sym, desc->off);
+         return;
+       }
+      origin_die = lookup_decl_die (origin);
     }
   else if (TYPE_P (origin))
     origin_die = lookup_type_die (origin);
   else if (TREE_CODE (origin) == BLOCK)
-    origin_die = BLOCK_DIE (origin);
+    origin_die = lookup_block_die (origin);
 
   /* XXX: Functions that are never lowered don't always have correct block
      trees (in the case of java, they simply have no block tree, in some other
@@ -21115,7 +21163,6 @@ add_abstract_origin_attribute (dw_die_ref die, tree origin)
 
   if (origin_die)
     add_AT_die_ref (die, DW_AT_abstract_origin, origin_die);
-  return origin_die;
 }
 
 /* We do not currently support the pure_virtual attribute.  */
@@ -22411,6 +22458,13 @@ dwarf2out_abstract_function (tree decl)
   if (DECL_IGNORED_P (decl))
     return;
 
+  /* Do not lazily create a DIE for decl here just because we
+     got called via debug_hooks->outlining_inline_function.  */
+  if (in_lto_p
+      && external_die_map
+      && external_die_map->get (decl))
+    return;
+
   old_die = lookup_decl_die (decl);
   /* With early debug we always have an old DIE unless we are in LTO
      and the user did not compile but only link with debug.  */
@@ -22529,7 +22583,7 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
         && block != DECL_INITIAL (decl)
         && TREE_CODE (block) == BLOCK)
     {
-      stmt_die = BLOCK_DIE (block);
+      stmt_die = lookup_block_die (block);
       if (stmt_die)
        break;
       block = BLOCK_SUPERCONTEXT (block);
@@ -24011,12 +24065,12 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
 static void
 gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 {
-  dw_die_ref old_die = BLOCK_DIE (stmt);
+  dw_die_ref old_die = lookup_block_die (stmt);
   dw_die_ref stmt_die = NULL;
   if (!old_die)
     {
       stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
-      BLOCK_DIE (stmt) = stmt_die;
+      equate_block_to_die (stmt, stmt_die);
     }
 
   if (BLOCK_ABSTRACT (stmt))
@@ -24044,7 +24098,7 @@ gen_lexical_block_die (tree stmt, dw_die_ref context_die)
       if (old_die)
        {
          stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
-         BLOCK_DIE (stmt) = stmt_die;
+         equate_block_to_die (stmt, stmt_die);
          old_die = NULL;
        }
 
@@ -24091,7 +24145,7 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
        = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
 
       if (call_arg_locations || debug_inline_points)
-       BLOCK_DIE (stmt) = subr_die;
+       equate_block_to_die (stmt, subr_die);
       add_abstract_origin_attribute (subr_die, decl);
       if (TREE_ASM_WRITTEN (stmt))
         add_high_low_attributes (stmt, subr_die);
@@ -25591,7 +25645,7 @@ gen_block_die (tree stmt, dw_die_ref context_die)
     /* The outer scopes for inlinings *must* always be represented.  We
        generate DW_TAG_inlined_subroutine DIEs for them.  (See below.) */
     must_output_die = 1;
-  else if (BLOCK_DIE (stmt))
+  else if (lookup_block_die (stmt))
     /* If we already have a DIE then it was filled early.  Meanwhile
        we might have pruned all BLOCK_VARS as optimized out but we
        still want to generate high/low PC attributes so output it.  */
@@ -27422,7 +27476,7 @@ dwarf2out_inline_entry (tree block)
                                      true));
 
   gcc_assert (inlined_function_outer_scope_p (block));
-  gcc_assert (!BLOCK_DIE (block));
+  gcc_assert (!lookup_block_die (block));
 
   if (BLOCK_FRAGMENT_ORIGIN (block))
     block = BLOCK_FRAGMENT_ORIGIN (block);
@@ -31846,6 +31900,17 @@ dwarf2out_early_finish (const char *filename)
      sure to adjust the phase after annotating the LTRANS CU DIE.  */
   if (in_lto_p)
     {
+      /* Force DW_TAG_imported_unit to be created now, otherwise
+        we might end up without it or ordered after DW_TAG_inlined_subroutine
+        referencing DIEs from it.  */
+      if (! flag_wpa && flag_incremental_link != INCREMENTAL_LINK_LTO)
+       {
+         unsigned i;
+         tree tu;
+         FOR_EACH_VEC_SAFE_ELT (all_translation_units, i, tu)
+           maybe_create_die_with_external_ref (tu);
+       }
+
       early_dwarf_finished = true;
       if (dump_file)
        {