This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][1/n] dwarf2out refactoring for early (LTO) debug
- From: Richard Biener <rguenther at suse dot de>
- To: Aldy Hernandez <aldyh at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org, jason at redhat dot com
- Date: Wed, 26 Aug 2015 12:43:19 +0200 (CEST)
- Subject: Re: [PATCH][1/n] dwarf2out refactoring for early (LTO) debug
- Authentication-results: sourceware.org; auth=none
- References: <alpine dot LSU dot 2 dot 11 dot 1508181615190 dot 19998 at zhemvz dot fhfr dot qr> <55D38853 dot 5010702 at redhat dot com> <alpine dot LSU dot 2 dot 11 dot 1508191531490 dot 19998 at zhemvz dot fhfr dot qr>
On Wed, 19 Aug 2015, Richard Biener wrote:
> 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?
Jason, are you willing to review these refactoring patches or can
I invoke my middle-end maintainer powers to remove some of this noise
from the LTO parts?
Thanks,
Richard.
> Thanks,
> Richard.
>
> 2015-08-18 Richard Biener <rguenther@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;
>
--
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)