From f6919d2011ed694971f54a9e3bfe63ff0fcb864c Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 25 Sep 2018 07:30:56 +0000 Subject: [PATCH] re PR debug/83941 (Debug info generated with -flto contains useless forwarders) 2018-09-25 Richard Biener 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 | 28 ++++++++ gcc/dwarf2out.c | 185 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 153 insertions(+), 60 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 780cf78cf60..61422ada6f1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2018-09-25 Richard Biener + + 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 * ipa-fnsummary.c (estimate_node_size_and_time): Scale by two diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 66ee839b5cb..6f45794caf6 100644 --- a/gcc/dwarf2out.c +++ b/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 *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::create_ggc (1000); + if (!external_die_map) + external_die_map = hash_map::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) { -- 2.30.2