On Wed, 26 Sep 2018, Jason Merrill wrote: > On Wed, Sep 26, 2018 at 9:35 AM, Richard Biener <rguent...@suse.de> wrote: > > > > We do not create a DW_AT_lexical_block for the outermost block in > > functions but we do for DW_AT_inlined_subroutines. That makes > > debuginfo look like if there were two of each local, the outer > > one (from the abstract instance) optimized out (visible via > > info locals in gdb). > > > > The following elides the outermost block also from inline instances. > > It's a bit tricky to reliably track that block given we remove unused > > blocks here and there. The trick is to have the block in the abstract > > instance _not_ point to itself (given we do not output it it isn't > > the abstract origin for itself). > > > > Bootstrapped on x86_64-unkown-linux-gnu, testing in progress. > > > > Again with some scan-assembler testcase, guality cannot do 'info locals'. > > > > OK? > > > > Thanks, > > Richard. > > > > 2018-09-26 Richard Biener <rguent...@suse.de> > > > > PR debug/87440 > > * dwarf2out.c (set_block_origin_self): Do not mark outermost > > block as we do not output that. > > (gen_inlined_subroutine_die): Elide the originally outermost > > block, matching what we do for concrete instances. > > (decls_for_scope): Add parameter specifying whether to recurse > > to subblocks. > > > > * gcc.dg/debug/dwarf2/inline4.c: New testcase. > > > > Index: gcc/testsuite/gcc.dg/debug/dwarf2/inline4.c > > =================================================================== > > --- gcc/testsuite/gcc.dg/debug/dwarf2/inline4.c (nonexistent) > > +++ gcc/testsuite/gcc.dg/debug/dwarf2/inline4.c (working copy) > > @@ -0,0 +1,17 @@ > > +/* Verify that the inline instance has no extra DW_TAG_lexical_block > > between > > + the DW_TAG_inlined_subroutine and the DW_TAG_variable for the local. */ > > +/* { dg-options "-O -gdwarf -dA" } */ > > +/* { dg-do compile } */ > > +/* { dg-final { scan-assembler > > "DW_TAG_inlined_subroutine\[^\\(\]*\\(\[^\\)\]*\\)\[^\\(\]*\\(DIE > > \\(0x\[0-9a-f\]*\\) DW_TAG_formal_parameter\[^\\(\]*\\(DIE > > \\(0x\[0-9a-f\]*\\) DW_TAG_variable" } } */ > > +/* { dg-final { scan-assembler-times "DW_TAG_inlined_subroutine" 2 } } */ > > + > > +static int foo (int i) > > +{ > > + volatile int j = i + 3; > > + return j - 2; > > +} > > +int main() > > +{ > > + volatile int z = foo (-1); > > + return z; > > +} > > Index: gcc/dwarf2out.c > > =================================================================== > > --- gcc/dwarf2out.c (revision 264640) > > +++ gcc/dwarf2out.c (working copy) > > @@ -3867,7 +3867,7 @@ static void gen_subroutine_type_die (tre > > static void gen_typedef_die (tree, dw_die_ref); > > static void gen_type_die (tree, dw_die_ref); > > static void gen_block_die (tree, dw_die_ref); > > -static void decls_for_scope (tree, dw_die_ref); > > +static void decls_for_scope (tree, dw_die_ref, bool = true); > > static bool is_naming_typedef_decl (const_tree); > > static inline dw_die_ref get_context_die (tree); > > static void gen_namespace_die (tree, dw_die_ref); > > @@ -22389,7 +22389,13 @@ set_block_origin_self (tree stmt) > > { > > if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) > > { > > - BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; > > + /* We do not mark the outermost block as we are not outputting it. > > + This is then a reliable way of determining whether we should > > + do the same for an inline instance. */ > > + if (TREE_CODE (BLOCK_SUPERCONTEXT (stmt)) != FUNCTION_DECL) > > + BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; > > + else > > + gcc_assert (DECL_INITIAL (BLOCK_SUPERCONTEXT (stmt)) == stmt); > > > > { > > tree local_decl; > > @@ -24149,7 +24155,24 @@ gen_inlined_subroutine_die (tree stmt, d > > add_high_low_attributes (stmt, subr_die); > > add_call_src_coords_attributes (stmt, subr_die); > > > > - decls_for_scope (stmt, subr_die); > > + /* The inliner creates an extra BLOCK for the parameter setup, > > + we want to merge that with the actual outermost BLOCK of the > > + inlined function to avoid duplicate locals in consumers. Note > > + we specially mark that not as origin-self. > > + Do that by doing the recursion to subblocks on the single subblock > > + of STMT. */ > > + bool unwrap_one = false; > > + if (BLOCK_SUBBLOCKS (stmt) && !BLOCK_CHAIN (BLOCK_SUBBLOCKS (stmt))) > > + { > > + tree origin = block_ultimate_origin (BLOCK_SUBBLOCKS (stmt)); > > + if (origin > > + && TREE_CODE (origin) == BLOCK > > + && !BLOCK_ABSTRACT_ORIGIN (origin)) > > Can we look at BLOCK_SUPERCONTEXT here rather than above?
Ah, yes. It could be simply + && BLOCK_SUPERCONTEXT (origin) == decl) I guess. I also noticed that the very same bug was noticed in the fixed PP37801 in comment #4 by you but the fix that was installed didn't fix that part thus with the fix we now regress gcc.dg/debug/dwarf2/inline2.c which explicitely looks for the bogus DW_TAG_lexical_blocks. I have adjusted that testcase now. Re-bootstrap & regtest in progress on x86_64-unknown-linux-gnu, OK? Thanks, Richard. 2018-09-27 Richard Biener <rguent...@suse.de> PR debug/37801 PR debug/87440 * dwarf2out.c (set_block_origin_self): Do not mark outermost block as we do not output that. (gen_inlined_subroutine_die): Elide the originally outermost block, matching what we do for concrete instances. (decls_for_scope): Add parameter specifying whether to recurse to subblocks. * gcc.dg/debug/dwarf2/inline2.c: Adjust. * gcc.dg/debug/dwarf2/inline4.c: New testcase. Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c (revision 264662) +++ gcc/dwarf2out.c (working copy) @@ -3867,7 +3867,7 @@ static void gen_subroutine_type_die (tre static void gen_typedef_die (tree, dw_die_ref); static void gen_type_die (tree, dw_die_ref); static void gen_block_die (tree, dw_die_ref); -static void decls_for_scope (tree, dw_die_ref); +static void decls_for_scope (tree, dw_die_ref, bool = true); static bool is_naming_typedef_decl (const_tree); static inline dw_die_ref get_context_die (tree); static void gen_namespace_die (tree, dw_die_ref); @@ -24147,7 +24147,24 @@ gen_inlined_subroutine_die (tree stmt, d add_high_low_attributes (stmt, subr_die); add_call_src_coords_attributes (stmt, subr_die); - decls_for_scope (stmt, subr_die); + /* The inliner creates an extra BLOCK for the parameter setup, + we want to merge that with the actual outermost BLOCK of the + inlined function to avoid duplicate locals in consumers. Note + we specially mark that not as origin-self. + Do that by doing the recursion to subblocks on the single subblock + of STMT. */ + bool unwrap_one = false; + if (BLOCK_SUBBLOCKS (stmt) && !BLOCK_CHAIN (BLOCK_SUBBLOCKS (stmt))) + { + tree origin = block_ultimate_origin (BLOCK_SUBBLOCKS (stmt)); + if (origin + && TREE_CODE (origin) == BLOCK + && BLOCK_SUPERCONTEXT (origin) == decl) + unwrap_one = true; + } + decls_for_scope (stmt, subr_die, !unwrap_one); + if (unwrap_one) + decls_for_scope (BLOCK_SUBBLOCKS (stmt), subr_die); } } @@ -25775,7 +25792,7 @@ process_scope_var (tree stmt, tree decl, all of its sub-blocks. */ static void -decls_for_scope (tree stmt, dw_die_ref context_die) +decls_for_scope (tree stmt, dw_die_ref context_die, bool recurse) { tree decl; unsigned int i; @@ -25818,10 +25835,11 @@ decls_for_scope (tree stmt, dw_die_ref c /* Output the DIEs to represent all sub-blocks (and the items declared therein) of this block. */ - for (subblocks = BLOCK_SUBBLOCKS (stmt); - subblocks != NULL; - subblocks = BLOCK_CHAIN (subblocks)) - gen_block_die (subblocks, context_die); + if (recurse) + for (subblocks = BLOCK_SUBBLOCKS (stmt); + subblocks != NULL; + subblocks = BLOCK_CHAIN (subblocks)) + gen_block_die (subblocks, context_die); } /* Is this a typedef we can avoid emitting? */ Index: gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c =================================================================== --- gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c (revision 264662) +++ gcc/testsuite/gcc.dg/debug/dwarf2/inline2.c (working copy) @@ -23,12 +23,10 @@ of third, second and first. */ /* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_inlined_subroutine" 6 } } */ -/* Likewise we should have 6 DW_TAG_lexical_block DIEs: - - One for each subroutine inlined into main, so that's 3. - - One for each subroutine inlined in the out of line instances - of third, second and first, that's 3. -*/ -/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_lexical_block" 6 } } */ +/* We should have no DW_TAG_lexical_block DIEs, all inline instances + should have the first subblock elided to match the abstract instance + layout. */ +/* { dg-final { scan-assembler-times "\\(DIE \\(\[^\n\]*\\) DW_TAG_lexical_block" 0 } } */ /* There are 3 DW_AT_inline attributes: one per abstract inline instance. Index: gcc/testsuite/gcc.dg/debug/dwarf2/inline4.c =================================================================== --- gcc/testsuite/gcc.dg/debug/dwarf2/inline4.c (nonexistent) +++ gcc/testsuite/gcc.dg/debug/dwarf2/inline4.c (working copy) @@ -0,0 +1,17 @@ +/* Verify that the inline instance has no extra DW_TAG_lexical_block between + the DW_TAG_inlined_subroutine and the DW_TAG_variable for the local. */ +/* { dg-options "-O -gdwarf -dA" } */ +/* { dg-do compile } */ +/* { dg-final { scan-assembler "DW_TAG_inlined_subroutine\[^\\(\]*\\(\[^\\)\]*\\)\[^\\(\]*\\(DIE \\(0x\[0-9a-f\]*\\) DW_TAG_formal_parameter\[^\\(\]*\\(DIE \\(0x\[0-9a-f\]*\\) DW_TAG_variable" } } */ +/* { dg-final { scan-assembler-times "DW_TAG_inlined_subroutine" 2 } } */ + +static int foo (int i) +{ + volatile int j = i + 3; + return j - 2; +} +int main() +{ + volatile int z = foo (-1); + return z; +}