On 8/21/24 10:45, Richard Biener wrote: > On Wed, 21 Aug 2024, Richard Biener wrote: > >> On Tue, 20 Aug 2024, Bernd Edlinger wrote: >> >>> On 8/20/24 13:00, Richard Biener wrote: >>>> On Fri, Aug 16, 2024 at 12:49 PM Bernd Edlinger >>>> <bernd.edlin...@hotmail.de> wrote: >>>>> >>>>> While this already works correctly for the case when an inlined >>>>> subroutine contains only one subrange, a redundant DW_TAG_lexical_block >>>>> is still emitted when the subroutine has multiple blocks. >>>> >>>> Huh. The point is that the inline context is a single scope block with no >>>> siblings - how did that get messed up? The patch unfortunately does not >>>> contain a testcase. >>>> >>> >>> Well, I became aware of this because I am working on a gdb patch, >>> which improves the debug experience of optimized C code, and to my surprise >>> the test case did not work with gcc-8, while gcc-9 and following were fine. >>> Initially I did not see what is wrong, therefore I started to bisect when >>> this changed, and so I found your patch, which removed some lexical blocks >>> in the debug info of this gdb test case: >>> >>> from binutils-gdb/gdb/testsuite/gdb.cp/step-and-next-inline.cc >>> in case you have the binutils-gdb already downloaded you can skip this: >>> $ git clone git://sourceware.org/git/binutils-gdb >>> $ cd binutils-gdb/gdb/testsuite/gdb.cp >>> $ gcc -g -O2 step-and-next-inline.cc >>> >>> when you look at the debug info with readelf -w a.out >>> you will see, that the function "tree_check" >>> is inlined three times, one looks like this >>> <2><86b>: Abbrev Number: 40 (DW_TAG_inlined_subroutine) >>> <86c> DW_AT_abstract_origin: <0x95b> >>> <870> DW_AT_entry_pc : 0x1175 >>> <878> DW_AT_GNU_entry_view: 0 >>> <879> DW_AT_ranges : 0x21 >>> <87d> DW_AT_call_file : 1 >>> <87e> DW_AT_call_line : 52 >>> <87f> DW_AT_call_column : 10 >>> <880> DW_AT_sibling : <0x8bf> >>> <3><884>: Abbrev Number: 8 (DW_TAG_formal_parameter) >>> <885> DW_AT_abstract_origin: <0x974> >>> <889> DW_AT_location : 0x37 (location list) >>> <88d> DW_AT_GNU_locviews: 0x35 >>> <3><891>: Abbrev Number: 8 (DW_TAG_formal_parameter) >>> <892> DW_AT_abstract_origin: <0x96c> >>> <896> DW_AT_location : 0x47 (location list) >>> <89a> DW_AT_GNU_locviews: 0x45 >>> <3><89e>: Abbrev Number: 41 (DW_TAG_lexical_block) >>> <89f> DW_AT_ranges : 0x21 >>> >>> see the lexical block has the same DW_AT_ranges, as the >>> inlined subroutine, but the other invocations do not >>> have this lexical block, since your original fix removed >>> those. >>> And this lexical block triggered an unexpected issue >>> in my gdb patch, which I owe you one, for helping me >>> finding it :-) >>> >>> Before that I have never looked at these lexical blocks, >>> but all I can say is that while compiling this test case, >>> in the first invocation of gen_inlined_subroutine_die >>> there are several SUBBLOCKS linked via BLOCK_CHAIN, >>> and only the first one is used to emit the lexical_block, >>> while the other siblings must be fully decoded, otherwise >>> there is an internal error, that I found by try-and-error. >>> I thought that is since the subroutine is split over several >>> places, and therefore it appeared natural to me, that the >>> subroutine is also using several SUBBLOCKS. >> >> OK, so the case in question looks like >> >> { Scope block #8 step-and-next-inline.cc:52 Originating from : static >> struct tree * tree_check (struct tree *, int); Fragment chain : #16 #17 >> struct tree * t; >> int i; >> >> { Scope block #9 Originating from :#0 Fragment chain : #10 #11 >> struct tree * x; >> >> } >> >> { Scope block #10 Originating from :#0 Fragment of : #9 >> struct tree * x; >> >> } >> >> { Scope block #11 Originating from :#0 Fragment of : #9 >> struct tree * x; >> >> } >> >> } >> >> so we have fragments here which we should ignore, but then fragments >> are to collect multiple ranges which, when we do not emit a >> lexical block for block #9 above, we will likely fail to emit and >> which we instead should associate with block #8, the >> DW_TAG_inlined_subroutine. >> >> Somehow it seems to "work" as to associate DW_AT_ranges with the >> DW_TAG_inlined_subroutine. >> >> I've used the following - there's no need to process BLOCK_CHAIN >> as fragments are ignored by gen_block_die. >> >> diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc >> index d5144714c6e..4e6ad2ab7e1 100644 >> --- a/gcc/dwarf2out.cc >> +++ b/gcc/dwarf2out.cc >> @@ -25194,8 +25194,13 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref >> context_die) >> 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))) >> + if (BLOCK_SUBBLOCKS (stmt)) >> { >> + tree subblock = BLOCK_SUBBLOCKS (stmt); >> + /* We should never elide that BLOCK, but we may have multiple >> fragments. >> + Assert that there's only a single real inline-scope block. */ >> + for (tree next = BLOCK_CHAIN (subblock); next; next = BLOCK_CHAIN >> (next)) >> + gcc_checking_assert (BLOCK_FRAGMENT_ORIGIN (next) == subblock); >> tree origin = block_ultimate_origin (BLOCK_SUBBLOCKS (stmt)); >> if (origin >> && TREE_CODE (origin) == BLOCK >> >> I'm quite sure this will blow up, so the appropriate thing would be >> to only unwrap the block if the assertion would hold. > > ICEs for example c-c++-common/torture/complex-sign-mixed-div.c > and gcc.dg/torture/pr50823.c. The latter has > > { Scope block #24 > /space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr50823.c:25 > Originating from : static void emit_pattern_after_noloc (int (*<T3dc>) > (void)); Fragment chain : #31 > int (*<T3dc>) (void) make_raw; > > { Scope block #25 > /space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr50823.c:29 > Originating from : static int make_insn_raw (void); Fragment chain : #28 > > { Scope block #26 Originating from :#0 Fragment chain : #27 > > } > > { Scope block #27 Originating from :#0 Fragment of : #26 > > } > > } > > { Scope block #28 > /space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr50823.c:29 > Originating from : static int make_insn_raw (void); Fragment of : #25 > > } > > { Scope block #29 > /space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr50823.c:30 > Originating from : static void add_insn_after (void); > > { Scope block #30 Originating from :#0 > > } > > } > > } > > so that's for a function without any local vars, it does seem we > have to check explicitly for the case with "proper" fragments and > otherwise not unwrap. > > Can you update your patch accordingly? >
Ah, okay, so in terms of my current patch, you mean: diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc index 79f97b5a55e..c30dad1513a 100644 --- a/gcc/dwarf2out.cc +++ b/gcc/dwarf2out.cc @@ -25183,6 +25183,10 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die) && TREE_CODE (origin) == BLOCK && BLOCK_SUPERCONTEXT (origin) == decl) unwrap_one = true; + for (tree next = BLOCK_CHAIN (sub); unwrap_one && next; + next = BLOCK_CHAIN (next)) + if (BLOCK_FRAGMENT_ORIGIN (next) != sub) + unwrap_one = false; } decls_for_scope (stmt, subr_die, !unwrap_one); if (unwrap_one) I will bootstrap this and post a new patch tomorrow. Thanks Bernd. > Richard. > >> I'm testing the above. >> >> Richard. >> >>> >>> Thanks >>> Bernd. >>> >>>> Richard. >>>> >>>>> Fixes: ac02e5b75451 ("re PR debug/37801 (DWARF output for inlined >>>>> functions >>>>> doesn't always use DW_TAG_inlined_subroutine)") >>>>> >>>>> gcc/ChangeLog: >>>>> >>>>> PR debug/87440 >>>>> * dwarf2out.cc (gen_inlined_subroutine_die): Handle the case >>>>> of multiple subranges correctly. >>>>> --- >>>>> some more context is here: >>>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87440#c5 >>>>> Bootstrapped and regression-tested on x86_64-pc-linux-gnu, OK for trunk? >>>>> >>>>> gcc/dwarf2out.cc | 11 ++++++++--- >>>>> 1 file changed, 8 insertions(+), 3 deletions(-) >>>>> >>>>> diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc >>>>> index 357efaa5990..346feeb53c8 100644 >>>>> --- a/gcc/dwarf2out.cc >>>>> +++ b/gcc/dwarf2out.cc >>>>> @@ -25171,9 +25171,10 @@ gen_inlined_subroutine_die (tree stmt, >>>>> dw_die_ref context_die) >>>>> 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 sub = BLOCK_SUBBLOCKS (stmt); >>>>> + if (sub) >>>>> { >>>>> - tree origin = block_ultimate_origin (BLOCK_SUBBLOCKS (stmt)); >>>>> + tree origin = block_ultimate_origin (sub); >>>>> if (origin >>>>> && TREE_CODE (origin) == BLOCK >>>>> && BLOCK_SUPERCONTEXT (origin) == decl) >>>>> @@ -25181,7 +25182,11 @@ gen_inlined_subroutine_die (tree stmt, >>>>> dw_die_ref context_die) >>>>> } >>>>> decls_for_scope (stmt, subr_die, !unwrap_one); >>>>> if (unwrap_one) >>>>> - decls_for_scope (BLOCK_SUBBLOCKS (stmt), subr_die); >>>>> + { >>>>> + decls_for_scope (sub, subr_die); >>>>> + for (sub = BLOCK_CHAIN (sub); sub; sub = BLOCK_CHAIN (sub)) >>>>> + gen_block_die (sub, subr_die); >>>>> + } >>>>> } >>>>> >>>>> /* Generate a DIE for a field in a record, or structure. CTX is >>>>> required: see >>>>> -- >>>>> 2.39.2 >>>>> >>> >> >> >