On Tue, 18 Aug 2015, Aldy Hernandez wrote: > On 08/18/2015 07:20 AM, Richard Biener wrote: > > > > This starts a series of patches (still in development) to refactor > > dwarf2out.c to better cope with early debug (and LTO debug). > > Awesome! Thanks. > > > Aldyh, what other testing did you usually do for changes? Run > > the gdb testsuite against the new compiler? Anything else? > > gdb testsuite, and make sure you test GCC with --enable-languages=all,go,ada, > though the latter is mostly useful while you iron out bugs initially. I found > that ultimately, the best test was C++.
I see. > Pre merge I also bootstrapped the compiler and compared .debug* section sizes > in object files to make sure things were within reason. > > > + > > +static void > > +vmsdbgout_early_finish (const char *filename ATTRIBUTE_UNUSED) > > +{ > > + if (write_symbols == VMS_AND_DWARF2_DEBUG) > > + (*dwarf2_debug_hooks.early_finish) (filename); > > +} > > You can get rid of ATTRIBUTE_UNUSED now. Done. I've also refrained from moving gen_scheduled_generic_parms_dies (); gen_remaining_tmpl_value_param_die_attribute (); for now as that causes regressions I have to investigate. The patch below has passed bootstrap & regtest on x86_64-unknown-linux-gnu as well as gdb testing. Twice unpatched, twice patched - results seem to be somewhat unstable!? I even refrained from using any -j with make check-gdb... maybe it's just contrib/test_summary not coping well with gdb? any hints? Difference between unpatched run 1 & 2 is for example --- results.unpatched 2015-08-19 15:08:36.152899926 +0200 +++ results.unpatched2 2015-08-19 15:29:46.902060797 +0200 @@ -209,7 +209,6 @@ WARNING: remote_expect statement without a default case?! WARNING: remote_expect statement without a default case?! WARNING: remote_expect statement without a default case?! -FAIL: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3, fc4) FAIL: gdb.cp/inherit.exp: print g_vD FAIL: gdb.cp/inherit.exp: print g_vE FAIL: gdb.cp/no-dmgl-verbose.exp: setting breakpoint at 'f(std::string)' @@ -238,6 +237,7 @@ UNRESOLVED: gdb.fortran/types.exp: set print sevenbit-strings FAIL: gdb.fortran/whatis_type.exp: run to MAIN__ WARNING: remote_expect statement without a default case?! +FAIL: gdb.gdb/complaints.exp: print symfile_complaints->root->fmt WARNING: remote_expect statement without a default case?! WARNING: remote_expect statement without a default case?! WARNING: remote_expect statement without a default case?! @@ -362,12 +362,12 @@ === gdb Summary === -# of expected passes 30881 +# of expected passes 30884 # of unexpected failures 284 # of unexpected successes 2 -# of expected failures 85 +# of expected failures 83 # of unknown successes 2 -# of known failures 60 +# of known failures 59 # of unresolved testcases 6 # of untested testcases 32 # of unsupported tests 165 the sames changes randomly appear/disappear in the patched case. Otherwise patched/unpatched agree. Ok? Thanks, Richard. 2015-08-18 Richard Biener <rguent...@suse.de> * debug.h (gcc_debug_hooks::early_finish): Add filename argument. * dbxout.c (dbx_debug_hooks): Adjust. * debug.c (do_nothing_hooks): Likewise. * sdbout.c (sdb_debug_hooks): Likewise. * vmsdbgout.c (vmsdbgout_early_finish): New function dispatching to dwarf2out variant if needed. (vmsdbg_debug_hooks): Adjust. * dwarf2out.c (dwarf2_line_hooks): Adjust. (flush_limbo_die_list): New function. (dwarf2out_finish): Call flush_limbo_die_list instead of dwarf2out_early_finish. Assert there are no deferred asm-names. Move early stuff ... (dwarf2out_early_finish): ... here. * cgraphunit.c (symbol_table::finalize_compilation_unit): Call early_finish with main_input_filename argument. Index: gcc/cgraphunit.c =================================================================== --- gcc/cgraphunit.c (revision 226966) +++ gcc/cgraphunit.c (working copy) @@ -2490,7 +2490,7 @@ symbol_table::finalize_compilation_unit /* Clean up anything that needs cleaning up after initial debug generation. */ - (*debug_hooks->early_finish) (); + (*debug_hooks->early_finish) (main_input_filename); /* Finally drive the pass manager. */ compile (); Index: gcc/dbxout.c =================================================================== --- gcc/dbxout.c (revision 226966) +++ gcc/dbxout.c (working copy) @@ -354,7 +354,7 @@ const struct gcc_debug_hooks dbx_debug_h { dbxout_init, dbxout_finish, - debug_nothing_void, + debug_nothing_charstar, debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, Index: gcc/debug.c =================================================================== --- gcc/debug.c (revision 226966) +++ gcc/debug.c (working copy) @@ -28,7 +28,7 @@ const struct gcc_debug_hooks do_nothing_ { debug_nothing_charstar, debug_nothing_charstar, - debug_nothing_void, /* early_finish */ + debug_nothing_charstar, /* early_finish */ debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, Index: gcc/debug.h =================================================================== --- gcc/debug.h (revision 226966) +++ gcc/debug.h (working copy) @@ -31,7 +31,7 @@ struct gcc_debug_hooks void (* finish) (const char *main_filename); /* Run cleanups necessary after early debug generation. */ - void (* early_finish) (void); + void (* early_finish) (const char *main_filename); /* Called from cgraph_optimize before starting to assemble functions/variables/toplevel asms. */ Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 226966) +++ gcc/dwarf2out.c (working copy) @@ -2420,7 +2420,7 @@ build_cfa_aligned_loc (dw_cfa_location * static void dwarf2out_init (const char *); static void dwarf2out_finish (const char *); -static void dwarf2out_early_finish (void); +static void dwarf2out_early_finish (const char *); static void dwarf2out_assembly_start (void); static void dwarf2out_define (unsigned int, const char *); static void dwarf2out_undef (unsigned int, const char *); @@ -2494,7 +2494,7 @@ const struct gcc_debug_hooks dwarf2_line { dwarf2out_init, debug_nothing_charstar, - debug_nothing_void, + debug_nothing_charstar, debug_nothing_void, debug_nothing_int_charstar, debug_nothing_int_charstar, @@ -25128,47 +25128,81 @@ optimize_location_lists (dw_die_ref die) optimize_location_lists_1 (die, &htab); } +/* 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. + For concrete instances, we can get the parent die from the abstract + instance. */ + +static void +flush_limbo_die_list (void) +{ + limbo_die_node *node, *next_node; + + for (node = limbo_die_list; node; node = next_node) + { + dw_die_ref die = node->die; + next_node = node->next; + + if (die->die_parent == NULL) + { + dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); + + if (origin && origin->die_parent) + add_child_die (origin->die_parent, die); + else if (is_cu_die (die)) + ; + else if (seen_error ()) + /* It's OK to be confused by errors in the input. */ + add_child_die (comp_unit_die (), die); + else + { + /* In certain situations, the lexical block containing a + nested function can be optimized away, which results + in the nested function die being orphaned. Likewise + with the return type of that nested function. Force + this to be a child of the containing function. + + It may happen that even the containing function got fully + inlined and optimized out. In that case we are lost and + assign the empty child. This should not be big issue as + the function is likely unreachable too. */ + gcc_assert (node->created_for); + + if (DECL_P (node->created_for)) + origin = get_context_die (DECL_CONTEXT (node->created_for)); + else if (TYPE_P (node->created_for)) + origin = scope_die_for (node->created_for, comp_unit_die ()); + else + origin = comp_unit_die (); + + add_child_die (origin, die); + } + } + } + + limbo_die_list = NULL; +} + /* Output stuff that dwarf requires at the end of every file, and generate the DWARF-2 debugging info. */ static void -dwarf2out_finish (const char *filename) +dwarf2out_finish (const char *) { comdat_type_node *ctnode; dw_die_ref main_comp_unit_die; /* Flush out any latecomers to the limbo party. */ - dwarf2out_early_finish (); + flush_limbo_die_list (); - /* PCH might result in DW_AT_producer string being restored from the - header compilation, so always fill it with empty string initially - and overwrite only here. */ - dw_attr_ref producer = get_AT (comp_unit_die (), DW_AT_producer); - producer_string = gen_producer_string (); - producer->dw_attr_val.v.val_str->refcount--; - producer->dw_attr_val.v.val_str = find_AT_string (producer_string); + /* We shouldn't have any symbols with delayed asm names for + DIEs generated after early finish. */ + gcc_assert (deferred_asm_name == NULL); gen_scheduled_generic_parms_dies (); gen_remaining_tmpl_value_param_die_attribute (); - /* Add the name for the main input file now. We delayed this from - dwarf2out_init to avoid complications with PCH. - For LTO produced units use a fixed artificial name to avoid - leaking tempfile names into the dwarf. */ - if (!in_lto_p) - add_name_attribute (comp_unit_die (), remap_debug_filename (filename)); - else - add_name_attribute (comp_unit_die (), "<artificial>"); - if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir) - add_comp_dir_attribute (comp_unit_die ()); - else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL) - { - bool p = false; - file_table->traverse<bool *, file_table_relative_p> (&p); - if (p) - add_comp_dir_attribute (comp_unit_die ()); - } - #if ENABLE_ASSERT_CHECKING { dw_die_ref die = comp_unit_die (), c; @@ -25482,9 +25516,9 @@ dwarf2out_finish (const char *filename) has run. */ static void -dwarf2out_early_finish (void) +dwarf2out_early_finish (const char *filename) { - limbo_die_node *node, *next_node; + limbo_die_node *node; /* Add DW_AT_linkage_name for all deferred DIEs. */ for (node = deferred_asm_name; node; node = node->next) @@ -25502,57 +25536,35 @@ dwarf2out_early_finish (void) } 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. - For concrete instances, we can get the parent die from the abstract - instance. - - The point here is to flush out the limbo list so that it is empty + /* 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. */ - for (node = limbo_die_list; node; node = next_node) - { - dw_die_ref die = node->die; - next_node = node->next; - - if (die->die_parent == NULL) - { - dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin); - - if (origin && origin->die_parent) - add_child_die (origin->die_parent, die); - else if (is_cu_die (die)) - ; - else if (seen_error ()) - /* It's OK to be confused by errors in the input. */ - add_child_die (comp_unit_die (), die); - else - { - /* In certain situations, the lexical block containing a - nested function can be optimized away, which results - in the nested function die being orphaned. Likewise - with the return type of that nested function. Force - this to be a child of the containing function. + flush_limbo_die_list (); - It may happen that even the containing function got fully - inlined and optimized out. In that case we are lost and - assign the empty child. This should not be big issue as - the function is likely unreachable too. */ - gcc_assert (node->created_for); - - if (DECL_P (node->created_for)) - origin = get_context_die (DECL_CONTEXT (node->created_for)); - else if (TYPE_P (node->created_for)) - origin = scope_die_for (node->created_for, comp_unit_die ()); - else - origin = comp_unit_die (); + /* PCH might result in DW_AT_producer string being restored from the + header compilation, so always fill it with empty string initially + and overwrite only here. */ + dw_attr_ref producer = get_AT (comp_unit_die (), DW_AT_producer); + producer_string = gen_producer_string (); + producer->dw_attr_val.v.val_str->refcount--; + producer->dw_attr_val.v.val_str = find_AT_string (producer_string); - add_child_die (origin, die); - } - } + /* Add the name for the main input file now. We delayed this from + dwarf2out_init to avoid complications with PCH. + For LTO produced units use a fixed artificial name to avoid + leaking tempfile names into the dwarf. */ + if (!in_lto_p) + add_name_attribute (comp_unit_die (), remap_debug_filename (filename)); + else + add_name_attribute (comp_unit_die (), "<artificial>"); + if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir) + add_comp_dir_attribute (comp_unit_die ()); + else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL) + { + bool p = false; + file_table->traverse<bool *, file_table_relative_p> (&p); + if (p) + add_comp_dir_attribute (comp_unit_die ()); } - - limbo_die_list = NULL; } /* Reset all state within dwarf2out.c so that we can rerun the compiler Index: gcc/sdbout.c =================================================================== --- gcc/sdbout.c (revision 226966) +++ gcc/sdbout.c (working copy) @@ -278,7 +278,7 @@ const struct gcc_debug_hooks sdb_debug_h { sdbout_init, /* init */ sdbout_finish, /* finish */ - debug_nothing_void, /* early_finish */ + debug_nothing_charstar, /* early_finish */ debug_nothing_void, /* assembly_start */ debug_nothing_int_charstar, /* define */ debug_nothing_int_charstar, /* undef */ Index: gcc/vmsdbgout.c =================================================================== --- gcc/vmsdbgout.c (revision 226966) +++ gcc/vmsdbgout.c (working copy) @@ -147,6 +147,7 @@ static int write_srccorrs (int); static void vmsdbgout_init (const char *); static void vmsdbgout_finish (const char *); +static void vmsdbgout_early_finish (const char *); static void vmsdbgout_assembly_start (void); static void vmsdbgout_define (unsigned int, const char *); static void vmsdbgout_undef (unsigned int, const char *); @@ -174,7 +175,7 @@ static void vmsdbgout_abstract_function const struct gcc_debug_hooks vmsdbg_debug_hooks = {vmsdbgout_init, vmsdbgout_finish, - debug_nothing_void, + vmsdbgout_early_finish, vmsdbgout_assembly_start, vmsdbgout_define, vmsdbgout_undef, @@ -1552,7 +1553,17 @@ vmsdbgout_abstract_function (tree decl) VMS Debug debugging info. */ static void -vmsdbgout_finish (const char *filename ATTRIBUTE_UNUSED) +vmsdbgout_early_finish (const char *filename) +{ + if (write_symbols == VMS_AND_DWARF2_DEBUG) + (*dwarf2_debug_hooks.early_finish) (filename); +} + +/* Output stuff that Debug requires at the end of every file and generate the + VMS Debug debugging info. */ + +static void +vmsdbgout_finish (const char *filename) { unsigned int i, ifunc; int totsize;