re PR debug/83941 (Debug info generated with -flto contains useless forwarders)
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
This commit is contained in:
parent
59d2702625
commit
f6919d2011
@ -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
|
||||
|
185
gcc/dwarf2out.c
185
gcc/dwarf2out.c
@ -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);
|
||||
}
|
||||
|
||||
dw_die_ref die
|
||||
= TREE_CODE (decl) == BLOCK ? BLOCK_DIE (decl) : lookup_decl_die (decl);
|
||||
/* 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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user