diff mbox

[1/n] dwarf2out refactoring for early (LTO) debug

Message ID alpine.LSU.2.11.1508191531490.19998@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Aug. 19, 2015, 1:45 p.m. UTC
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

Comments

Aldy Hernandez Aug. 19, 2015, 1:55 p.m. UTC | #1
On 08/19/2015 06:45 AM, Richard Biener wrote:

[copying gdb folks]

> On Tue, 18 Aug 2015, Aldy Hernandez wrote:
>
>> On 08/18/2015 07:20 AM, Richard Biener wrote:

[snip]

> 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.


This is somewhat expected. Well, at least I never found a good 
explanation. Some tests seemed to be thread related and inconsistent. 
Others, I have no idea.

After running the tests enough times I got a feeling of which tests 
would always pass, and use those as reference. It was confusing at 
first. Perhaps the GDB folks could shed some light? I've found them very 
helpful.

Also, -j made things worse. I never used it.

Aldy
Pedro Alves Aug. 19, 2015, 2:50 p.m. UTC | #2
On 08/19/2015 02:55 PM, Aldy Hernandez wrote:
> On 08/19/2015 06:45 AM, Richard Biener wrote:
> 
> [copying gdb folks]

Thanks.

> 
>> On Tue, 18 Aug 2015, Aldy Hernandez wrote:
>>
>>> On 08/18/2015 07:20 AM, Richard Biener wrote:
> 
> [snip]
> 
>> 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)


if {![target_info exists gdb,skip_float_tests]} {
    gdb_test_stdio "print find_max_double(5,1.0,17.0,2.0,3.0,4.0)" \
        "find_max\\(.*\\) returns 17\\.000000\[ \r\n\]+" \
        ".\[0-9\]+ = 17" \
        "print find_max_double(5,1.0,17.0,2.0,3.0,4.0)"
}

# Test _Complex type here if supported.
if [support_complex_tests] {
    global gdb_prompt

    set test "print find_max_float_real(4, fc1, fc2, fc3, fc4)"
    gdb_test $test ".*= 4 \\+ 4 \\* I" $test

>>   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


    # Prime the system
    gdb_test_stdio "call complaint (&symfile_complaints, \"Register a complaint\")" \
            "During symbol reading, Register a complaint."

    # Check that the complaint was inserted and where
    gdb_test "print symfile_complaints->root->fmt" \
            ".\[0-9\]+ =.*\"Register a complaint\""


So in both cases, there was a "gdb_test_stdio" test just before
the test that failed.  gdb_test_stdio is new, and it expects output
from two different spawn ids simultaneously.  Sounds like it still
needs fixing...  I'll guess that Richard has a much faster machine than
my getting-old laptop, which exposes races that I didn't trip on...

> This is somewhat expected. Well, at least I never found a good 
> explanation. Some tests seemed to be thread related and inconsistent. 
> Others, I have no idea.
> 

Indeed there are still some threading tests that unfortunately still
cause intermittent fails.  We've been fixing them but it's a
slow process.  Judging by the GDB build bots, x86_64 GNU/Linux
testing seems to be mostly stable though.  There's one DejaGNU issue
that is consistently causing trouble  -- see below.

> After running the tests enough times I got a feeling of which tests 
> would always pass, and use those as reference. It was confusing at 
> first. Perhaps the GDB folks could shed some light? I've found them very 
> helpful.
> 
> Also, -j made things worse. I never used it.

It gets much better if you use git master DejaGNU, to pick this up:

  http://lists.gnu.org/archive/html/dejagnu/2015-07/msg00005.html

Thanks,
Pedro Alves
Richard Biener Aug. 20, 2015, 9:23 a.m. UTC | #3
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.

Tricky beast ;)  For g++.dg/debug/dwarf2/template-func-params-3.C
we run into the issue that when doing early dwarf the
rtl_for_decl_init (&bleh) call will fail because it ends up asking

15809              && ! walk_tree (&init, reference_to_unused, NULL, NULL)

which uses TREE_ASM_WRITTEN to see of 'bleh' was emitted or not.
That's not going to work at this stage - we even have no idea
whether 'bleh' is going to survive IPA or not (might be inlined).
With LTO it gets even tricker as we only see a subset of the whole
program (or original TU) at LTRANS stage.

So it somehow looks like late dwarf thing for this kind of
symbolic constants - but it _also_ looks like a very bad
dwarf representation to me (going through RTL is bad enough, heh).
We expect DW_OP_addr and a reference to _Z4blehv as follows:

        .byte   0x3     # DW_OP_addr
        .quad   _Z4blehv

but I wonder if DWARF has something better so we can refer
to _Z4blehv by means of the DIE for its declaration (so the
debugger can resolve the constant value)?  That would allow
the debugger to print &bleh even if bleh was optimized out
(it just would have to print <optimized out> for the actual
address).

So what I'll do is have two phases of
gen_remaining_tmpl_value_param_die_attribute 
(gen_scheduled_generic_parms_dies doesn't have a similar issue
AFAICS), during early-debug add those we can, retaining those
we can only handle late (just checking the return value of
tree_add_const_value_attribute).  For LTO the remaining ones
will be dropped on the floor (or we'd have to stream them
somehow) unless we can change the DWARF representation of
these symbolic constants.

Thanks,
Richard.
Richard Biener Aug. 20, 2015, 10:22 a.m. UTC | #4
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.

So I thought gen_scheduled_generic_parms_dies was fine but it exposes
a hole in

  /* Generate early debug for global variables.  Any local variables will
     be handled by either handling reachable functions from
     finalize_compilation_unit (and by consequence, locally scoped
     symbols), or by rest_of_type_compilation below.
...
      && !decl_type_context (decl))
    (*debug_hooks->early_global_decl) (decl);

for __timepunct_cache::_S_timezones where through the
rest_of_type_compilation we quickly finish processing __timepunct_cache
as it is TYPE_DECL_SUPPRESS_DEBUG (so ->type_decl exits w/o doing
anything).  So we fail to generate a type DIE for the global which
causes us, at late_global_decl time (we do output this global var)
ends up doing

#12 0x0000000000b831f1 in gen_decl_die (decl=0x7ffff5650a20, origin=0x0, 
    context_die=0x7ffff62ab000)
    at /space/rguenther/src/svn/trunk/gcc/dwarf2out.c:21535
21532         /* And its containing type.  */
21533         class_origin = decl_class_context (decl_or_origin);
21534         if (class_origin != NULL_TREE)
21535           gen_type_die_for_member (class_origin, decl_or_origin, 
context_die);

and thus create the type DIE for __timepunct_cache late.

This is a hole in current early-debug.  IMHO we should force
early_global_decl even for globals in decl_type_context ()
or at least for a type DIE to be created for TYPE_DECL_SUPPRESS_DEBUG
type decls.

Jason, any advice on this?  I note

/* In a TYPE_DECL nonzero means the detail info about this type is not 
dumped
   into stabs.  Instead it will generate cross reference ('x') of names.
   This uses the same flag as DECL_EXTERNAL.  */
#define TYPE_DECL_SUPPRESS_DEBUG(NODE) \
  (TYPE_DECL_CHECK (NODE)->decl_common.decl_flag_1)

refering to STABS and "This uses the same flag as DECL_EXTERNAL" so
maybe this is just bad co-incidence?  DECL_EXTERNAL doesn't check
it operates on a non-TYPE_DECL.

So without knowing that the flag is supposed to be doing in DWARF
(also the desired effect on any of its static members) I can only
suggest we maybe do not want any debug info for 
__timepunct_cache::_S_timezones at all?

Thanks,
Richard.
Richard Biener Aug. 26, 2015, 10:43 a.m. UTC | #5
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;
>
diff mbox

Patch

--- 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  <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;