Hi all, I’m working on improving the debugging experience for C++20 coroutines when compiled with LLVM/Clang, and I could use some help from someone who understands debug information and DWARF (knowledge of coroutines isn't necessary, I don't think).
Specifically, I’m trying to improve lldb’s behavior when showing variables in the current stack frame, when that frame corresponds to a coroutine function. To illustrate my problem, I uploaded C++ source, LLVM IR, a DWARF dump, and a shellscript demonstrating the invocations I used to create each of these, as a gist on GitHub: https://gist.github.com/modocache/670bc38e5a5ea2e0a3d6bafe8ea9c693 I'm looking at lldb's behavior on lines 23-40 of the C++ program, https://gist.github.com/modocache/670bc38e5a5ea2e0a3d6bafe8ea9c693#file-test-cpp-L23-L40, which I’ll paste below: ``` coro foo() { int i = 0; ++i; printf("%d\n", i); // 1 // Breakpoint 1: // (lldb) frame variable i // (int) i = 1 co_await suspend_always(); int j = 0; ++i; ++j; printf("%d, %d\n", i, j); // 2, 1 // Breakpoint 2: // (lldb) frame variable i // (int) i = <variable not available> // (lldb) frame variable j // (int) j = 1 ``` Here 'foo' is a coroutine, and the comments denote commands executed at the lldb prompt when stopped at a breakpoint placed at the 'printf' above. At breakpoint 1, lldb correctly shows the value of 'i' to be 1. At breakpoint 2, 'i' is shown as 'variable not available'. ('j', however, is shown correctly.) Looking at the LLVM IR debug info metadata, (and keeping in mind I'm no expert at this stuff) I don't see anything out of the ordinary. Coroutine passes outline sections of the coroutine function, and to maintain state, they replace references to stack frame variables with loads and stores onto a "coroutine frame" object. But, looking at the IR in test.ll lines 221-238, the 'llvm.dbg.value' intrinsic is being used to denote the location of the values, which I think should allow lldb to print the correct values: https://gist.github.com/modocache/670bc38e5a5ea2e0a3d6bafe8ea9c693#file-test-ll-L221-L238 The 'llvm.dbg.value' intrinsics reference metadata in slots !659 and !668, and these seem correct to me as well: ``` !659 = !DILocalVariable(name: "i", scope: !660, file: !5, line: 24, type: !130) !668 = !DILocalVariable(name: "j", scope: !660, file: !5, line: 32, type: !130) ``` Finally, I looked at the DWARF being produced for the program. When broken at breakpoint two above, executing 'disassemble' at the lldb prompt shows me the program counters for the region I'm interested in: ``` 0x401885 <+373>: movq -0x8(%rbp), %rax 0x401889 <+377>: movl $0x0, 0x40(%rax) 0x401890 <+384>: movl 0x28(%rax), %edx 0x401893 <+387>: addl $0x1, %edx 0x401896 <+390>: movl %edx, 0x28(%rax) 0x401899 <+393>: movl 0x40(%rax), %edx 0x40189c <+396>: addl $0x1, %edx 0x40189f <+399>: movl %edx, 0x40(%rax) -> 0x4018a2 <+402>: movl 0x28(%rax), %esi ``` Specifically, I think 0x401893 and 0x40189c respectively show 'i' and 'j' being incremented by 1. Now, looking at the DWARF dump, I can see that 'i' is live between 0x401893 and 0x40189c, and 'j' is live between 0x40189c and 0x4018b9: https://gist.github.com/modocache/670bc38e5a5ea2e0a3d6bafe8ea9c693#file-test-dwarfdump-txt-L4063-L4086 Sure enough, when I break in lldb within 'i' region 0x401893 and 0x40189c, 'frame variable i' succeeds. But outside of that region, lldb tells me '(int) i = <variable not available>'. How do I improve the debug info here such that lldb can show 'i' outside of that small live range? Any and all help, questions, comments, are very much appreciated! - Brian Gesiak _______________________________________________ lldb-dev mailing list lldb-dev@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev