[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread rguenth at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

Richard Biener  changed:

   What|Removed |Added

   Last reconfirmed||2023-03-03
 Ever confirmed|0   |1
 Status|UNCONFIRMED |NEW
 CC||aoliva at gcc dot gnu.org,
   ||jakub at gcc dot gnu.org
   Severity|normal  |enhancement
Version|unknown |13.0

--- Comment #1 from Richard Biener  ---
It might be possible to run a reduced dataflow var-tracking at -O0 for this
kind of things (the target could provide a set of interesting entry/exit
parameters/registers to track).  For other targets the biggest issue is when
debugging the prologue code.

I'm not sure how easy it would be to run var-tracking for a subset of
insns/regs and how to then make use of such partial information when
outputting DWARF.

Alex/Jakub might have some ideas.

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #2 from Jakub Jelinek  ---
I think there are several open PRs about var-tracking at -O0, which would be
nice e.g. for VLAs.  The main problem is that var-tracking is very expensive,
so if we do it, it should track a very small subset of what is normally tracked
(say primarily register vars (i.e. what doesn't live at -O0 in memory) and
expressions before they are fully initialized and stored into their memory
slots.
Regarding the call sites, I guess we could get at least some arguments there by
just scanning a few instructions before each call rather than actually tracking
the values,
say on x86_64 the f2 call is:
(insn 33 6 8 2 (set (reg:DI 0 ax [84])
(plus:DI (reg/f:DI 6 bp)
(const_int -12 [0xfff4]))) "pr108996.C":31:22 241
{*leadi}
 (nil))
(insn 8 33 9 2 (set (reg:SI 1 dx [85])
(mem/c:SI (plus:DI (reg/f:DI 6 bp)
(const_int -8 [0xfff8])) [4 i2+0 S4 A64]))
"pr108996.C":31:22 83 {*movsi_internal}
 (nil))
(insn 9 8 11 2 (set (reg:SI 2 cx [86])
(mem/c:SI (plus:DI (reg/f:DI 6 bp)
(const_int -4 [0xfffc])) [4 i1+0 S4 A32]))
"pr108996.C":31:22 83 {*movsi_internal}
 (nil))
(insn 11 9 12 2 (set (reg:SI 4 si)
(reg:SI 2 cx [86])) "pr108996.C":31:22 83 {*movsi_internal}
 (nil))
(insn 12 11 13 2 (set (reg:DI 5 di)
(reg:DI 0 ax [84])) "pr108996.C":31:22 82 {*movdi_internal}
 (nil))
(call_insn 13 12 14 2 (call (mem:QI (symbol_ref:DI ("_Z2f2ii") [flags 0x3] 
) [0 f2 S1 A8])
(const_int 0 [0])) "pr108996.C":31:22 1003 {*call}
 (expr_list:REG_EH_REGION (const_int 0 [0])
(nil))
(expr_list:DI (use (reg:DI 5 di))
(expr_list:SI (use (reg:SI 4 si))
(expr_list:SI (use (reg:SI 1 dx))
(nil)
aka
leaq-12(%rbp), %rax
movl-8(%rbp), %edx
movl-4(%rbp), %ecx
movl%ecx, %esi
movq%rax, %rdi
call_Z2f2ii
so we could from just scanning the above sequence determine that first argument
is &[bp - 12], second argument [bp - 4] and third [bp - 8].
Of course using DW_OP_entry_value in DWARF expressions would be much harder.

But, on the other side, the r3 in the powerpc case (aka &b) is spilled in the
f2's prologue like other parameters, and e.g. debug info
for the b return value says that correctly:
mflr 0
std 0,16(1)
std 31,-8(1)
stdu 1,-64(1)
mr 31,1
std 3,32(31)
^^^ above
and
.byte   0x1  # uleb128 0x1; (DIE (0xcc) DW_TAG_variable)
.ascii "b\0" # DW_AT_name
 # DW_AT_decl_file (1, pr108996.C)
.byte   0x1f # DW_AT_decl_line
.byte   0x8  # DW_AT_decl_column
.4byte  0x2a # DW_AT_type
.byte   0x2  # uleb128 0x2; DW_AT_location
.byte   0x91 # DW_OP_fbreg
.byte   0x68 # sleb128 -24
Like everywhere else, the debug info at -O0 isn't accurate before the
corresponding memory slot is initialized, in this case in the first 5
instructions of the function.
But otherwise it is there.  Except that DWARF doesn't say that b is the return
value...

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #3 from Jakub Jelinek  ---
What is done on other arches?  I mean the situation is basically the same on
x86_64,
where the artificial return value pointer argument is spilled early, then
clobbered
on calls and again b debug info is correct after the spill:
pushq   %rbp
movq%rsp, %rbp
subq$16, %rsp
movq%rdi, -8(%rbp)
movl%esi, -12(%rbp)
movl%edx, -16(%rbp)
movq-8(%rbp), %rax
movq%rax, %rdi
call_ZN1BC1Ev
movl-12(%rbp), %edx
movl-16(%rbp), %eax
addl%eax, %edx
movq-8(%rbp), %rax
movl%edx, (%rax)
nop
movq-8(%rbp), %rax
leave
ret
...
.byte   0x1 # uleb128 0x1; (DIE (0xcc) DW_TAG_variable)
.ascii "b\0"# DW_AT_name
# DW_AT_decl_file (1, pr108996.C)
.byte   0x1f# DW_AT_decl_line
.byte   0x8 # DW_AT_decl_column
.long   0x2a# DW_AT_type
.byte   0x2 # uleb128 0x2; DW_AT_location
.byte   0x91# DW_OP_fbreg
.byte   0x64# sleb128 -28

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread uweigand at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #4 from Ulrich Weigand  ---
(In reply to Jakub Jelinek from comment #3)
> What is done on other arches?

That depends on the platform ABI.  On some arches, including x86/x86_64 and
arm/aarch64, the ABI requires the generated code reloads the return buffer
pointer into a defined register at function exit (either the same it was in on
function entry, or some other ABI-defined register).  On those arches, GDB can
at least inspect the return value at the point the function return happens.

On a few arches, in particular SPARC and RISC-V, the ABI even guarantees that
the return buffer pointer register remains valid throughout execution of the
function, so that GDB can inspect and/or modify the return value at any point.

But on most other arches, including s390x and ppc/ppc64, the ABI does not
guarantee anything, so GDB simply cannot access the function return value at
all (after the point the return buffer pointer register is no longer needed by
generated code and the register has been reused).

However, *if* the debug info contains an entry-value record for that register
at the call site in the current caller, then the return buffer can be accessed
at any time, on all arches.   Given that in this specific case, most callers
will actually just point the return buffer register to a local stack buffer
(i.e. set the register to "stack pointer plus some constant"), generating an
entry-value record for these special cases should actually be quite
straightforward for the compiler, without requiring a lot of value-tracking
machinery.

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

Jakub Jelinek  changed:

   What|Removed |Added

 CC||mark at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek  ---
(In reply to Ulrich Weigand from comment #4)
> (In reply to Jakub Jelinek from comment #3)
> > What is done on other arches?
> 
> That depends on the platform ABI.  On some arches, including x86/x86_64 and

Ah, you're right here, such functions effectively return that invisible return
address pointer on x86.
Though, relying on DW_OP_entry_value is not reliable, if e.g. tail calls are
(or could be) involved, then GDB needs to punt.
So, I wonder if we just shouldn't ask for a DWARF 6 extension here, have some
way for the compiler to specify DW_AT_location for the return value.
Then for -O1+ -g with var-tracking that address could be for PowerPC r3
register in such functions or wherever its initial value is tracked (including
DW_OP_entry_value).
While for -O0, we'd see we've spilled that parameter to stack and would set
DW_AT_location to that place spilled on the stack.

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread mark at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #6 from Mark Wielaard  ---
(In reply to Jakub Jelinek from comment #5)
> So, I wonder if we just shouldn't ask for a DWARF 6 extension here, have
> some way for the compiler to specify DW_AT_location for the return value.

There is https://dwarfstd.org/ShowIssue.php?issue=221105.1 "Add a mechanism for
specifying subprogram return value locations"

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-03 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #7 from Andrew Pinski  ---
(In reply to Ulrich Weigand from comment #4)
> (In reply to Jakub Jelinek from comment #3)
> > What is done on other arches?
> 
> That depends on the platform ABI.  On some arches, including x86/x86_64 and
> arm/aarch64, the ABI requires the generated code reloads the return buffer
> pointer into a defined register at function exit (either the same it was in
> on function entry, or some other ABI-defined register).  On those arches,
> GDB can at least inspect the return value at the point the function return
> happens.

aarch64 does not require that. GCC produces it yes but that is a missed
optimization, see PR 103010 which I filed against GCC for that case.

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-07 Thread uweigand at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #8 from Ulrich Weigand  ---
(In reply to Jakub Jelinek from comment #5)
> Though, relying on DW_OP_entry_value is not reliable, if e.g. tail calls are
> (or could be) involved, then GDB needs to punt.

The only way a tail call could happen is if the return value is
passed through directly to the (caller's) caller, so the return
buffer address should still be correct, right?

> So, I wonder if we just shouldn't ask for a DWARF 6 extension here, have
> some way for the compiler to specify DW_AT_location for the return value.
> Then for -O1+ -g with var-tracking that address could be for PowerPC r3
> register in such functions or wherever its initial value is tracked
> (including DW_OP_entry_value).
> While for -O0, we'd see we've spilled that parameter to stack and would set
> DW_AT_location to that place spilled on the stack.

I don't think it is possible to track the value in the callee - the value may
not be available *anywhere* because it is no longer needed.  (Also, I don't
think the implicit return buffer address is guaranteed to be spilled to the
stack even at -O0.)

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-07 Thread uweigand at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #9 from Ulrich Weigand  ---
(In reply to Andrew Pinski from comment #7)
> (In reply to Ulrich Weigand from comment #4)
> > (In reply to Jakub Jelinek from comment #3)
> > > What is done on other arches?
> > 
> > That depends on the platform ABI.  On some arches, including x86/x86_64 and
> > arm/aarch64, the ABI requires the generated code reloads the return buffer
> > pointer into a defined register at function exit (either the same it was in
> > on function entry, or some other ABI-defined register).  On those arches,
> > GDB can at least inspect the return value at the point the function return
> > happens.
> 
> aarch64 does not require that. GCC produces it yes but that is a missed
> optimization, see PR 103010 which I filed against GCC for that case.

Well, I was looking at GDB code that at least *assumes* that the aarch64 ABI
does require that:
https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/aarch64-tdep.c;h=5b1b9921f87e588f8251a77d858f8f312be1e5ac;hb=HEAD#l2500

If this is incorrect, I guess GDB would have to be fixed.

[Bug debug/108996] Proposal for adding DWARF call site information in GCC with -O0

2023-03-07 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108996

--- Comment #10 from Jakub Jelinek  ---
(In reply to Ulrich Weigand from comment #8)
> (In reply to Jakub Jelinek from comment #5)
> > Though, relying on DW_OP_entry_value is not reliable, if e.g. tail calls are
> > (or could be) involved, then GDB needs to punt.
> 
> The only way a tail call could happen is if the return value is
> passed through directly to the (caller's) caller, so the return
> buffer address should still be correct, right?

If there is just a single possible tail call, I think GDB still handles it,
so that would be ok.  But if you have multiple possible tail calls, I think GDB
for DW_OP_entry_value evaluation punts (at least should, because it doesn't
know which
sequence of calls has been taken).

> I don't think it is possible to track the value in the callee - the value
> may not be available *anywhere* because it is no longer needed.  (Also, I
> don't think the implicit return buffer address is guaranteed to be spilled
> to the stack even at -O0.)

Well, at -O0 we can certainly guarantee it is available somewhere, even if we
currently don't do it already (it would surprise me if it is not spilled).