<div><div dir="auto">Apologies for the slow response here Jeremy. Your reply has been incredibly helpful so far, I just need to try adding 'llvm.dbg.addr' myself to confirm that works. Thank you! - Brian Gesiak</div></div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Feb 6, 2020 at 11:04 AM Jeremy Morse <<a href="mailto:jeremy.morse.llvm@gmail.com">jeremy.morse.llvm@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Brian,<br>
<br>
Thanks for working on coroutines, the debugging experience, and in<br>
particular thanks for the comprehensive write-up!,<br>
<br>
On Thu, Feb 6, 2020 at 1:19 PM Brian Gesiak via llvm-dev<br>
<<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> Specifically, I’m trying to improve lldb’s behavior when showing<br>
> variables in the current stack frame, when that frame corresponds to a<br>
> coroutine function.<br>
<br>
[...]<br>
<br>
Everything in the IR appears correct to my eyes, although I know next<br>
to nothing about coroutines and might have missed something. The<br>
simplest explanation of why the variable location goes missing can be<br>
seen in the disassembly:<br>
<br>
> ```<br>
> 0x401885 <+373>: movq -0x8(%rbp), %rax<br>
> 0x401889 <+377>: movl $0x0, 0x40(%rax)<br>
> 0x401890 <+384>: X movl 0x28(%rax), %edx<br>
> 0x401893 <+387>: X addl $0x1, %edx<br>
> 0x401896 <+390>: X movl %edx, 0x28(%rax)<br>
> 0x401899 <+393>: X movl 0x40(%rax), %edx<br>
> 0x40189c <+396>: addl $0x1, %edx<br>
> 0x40189f <+399>: movl %edx, 0x40(%rax)<br>
> -> 0x4018a2 <+402>: movl 0x28(%rax), %esi<br>
> ```<br>
<br>
Where I've marked with 'X' before the mnemonic the instructions that<br>
the variable location list covers. The location of "i" is correctly<br>
given as edx from its load to its store, and ends when edx is<br>
overwritten with the value of "j". In all the rest of the code, the<br>
variables value is in memory, and the DWARF data doesn't record this.<br>
<br>
Ideally debug info would track variables when they're stored to memory<br>
-- however we don't automatically know whether any subsequent store to<br>
memory will overwrite that variable, and so we don't track locations<br>
into memory. PR40628 [0] is an example of what can go wrong, where we<br>
described a variable as being in memory, but didn't know when that<br>
location was overwritten.<br>
<br>
If whatever's producing the coroutine IR has guarantees about where<br>
and when variables are loaded/stored from/to memory, it should be<br>
possible to put more information into the IR, so that the rest of LLVM<br>
doesn't have to guess. For example, this portion of IR:<br>
<br>
%15 = load i32, i32* %i.reload.addr62, align 4, !dbg !670<br>
call void @llvm.dbg.value(metadata i32 %15, metadata !659, metadata<br>
!DIExpression()), !dbg !661<br>
%inc19 = add nsw i32 %15, 1, !dbg !670<br>
call void @llvm.dbg.value(metadata i32 %inc19, metadata !659,<br>
metadata !DIExpression()), !dbg !661<br>
store i32 %inc19, i32* %i.reload.addr62, align 4, !dbg !670<br>
<br>
Could have a call to llvm.dbg.addr(metadata i32 *%i.reload.addr66,<br>
...) inserted after the store, indicating that the variable is located<br>
in memory. This should work (TM) so long as that memory is never<br>
overwritten with something that isn't the current value of "i" on<br>
every path after the call to llvm.dbg.addr; and on every path after<br>
the call to llvm.dbg.addr, when the variable is loaded form memory,<br>
there's a call to llvm.dbg.value to indicate that the variable is<br>
located somewhere other than memory now.<br>
<br>
Providing that extra information should improve the location coverage<br>
for your example, certainly when unoptimised. However, I believe (80%)<br>
this method isn't safe against optimisation, because (for example)<br>
dead stores can be deleted by LLVM passes without deleting the call to<br>
llvm.dbg.addr, pointing the variable location at a stale value in<br>
memory. Unfortunately I'm not aware of a facility or technique that<br>
protects against this right now. (CC Reid who I think ran into this<br>
last?).<br>
<br>
Note that there's some support for tracking variables through stack<br>
spills in post-isel debug data passes, however those loads and stores<br>
operate in well defined ways, and general loads and stores might not.<br>
<br>
[0] <a href="https://bugs.llvm.org/show_bug.cgi?id=40628" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_bug.cgi?id=40628</a><br>
<br>
--<br>
Thanks,<br>
Jeremy<br>
</blockquote></div></div>