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:
Richard Biener 2018-09-25 07:30:56 +00:00 committed by Richard Biener
parent 59d2702625
commit f6919d2011
2 changed files with 153 additions and 60 deletions

View 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

View 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);
}
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)
{