[Lldb-commits] [PATCH] D132624: [LLDB] Devirtualize coroutine promise types for `std::coroutine_handle`

Adrian Vogelsgesang via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Wed Aug 24 17:10:35 PDT 2022


avogelsgesang created this revision.
avogelsgesang added reviewers: Chuanfeng, aprantl, dblaikie, ychen, jryans, JDevlieghere.
Herald added subscribers: ChuanqiXu, Prazek.
Herald added a project: All.
avogelsgesang requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This commit teaches the `std::coroutine_handle` pretty-printer to
devirtualize type-erased promise types. This is particularly useful to
resonstruct call stacks, either of asynchronous control flow or of
recursive invocations of `std::generator`. For the example recently
introduced by https://reviews.llvm.org/D132451, printing the `__promise`
variable now shows

  (std::__coroutine_traits_sfinae<task, void>::promise_type) __promise = {
    continuation = coro frame = 0x555555562430 {
      resume = 0x0000555555556310 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
      destroy = 0x0000555555556700 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
      promise = {
        continuation = coro frame = 0x5555555623e0 {
          resume = 0x0000555555557070 (a.out`task detail::chain_fn<2>() at llvm-nested-example.cpp:66)
          destroy = 0x0000555555557460 (a.out`task detail::chain_fn<2>() at llvm-nested-example.cpp:66)
          promise = {
            ...
          }
        }
        result = 0
      }
    }
    result = 0
  }

(shortened to keep the commit message readable) instead of

  (std::__coroutine_traits_sfinae<task, void>::promise_type) __promise = {
    continuation = coro frame = 0x555555562430 {
      resume = 0x0000555555556310 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
      destroy = 0x0000555555556700 (a.out`task detail::chain_fn<1>() at llvm-nested-example.cpp:66)
    }
    result = 0
  }

Note how the new debug output reveals the complete asynchronous call
stack: our own function resumes `chain_fn<1>` which in turn will resume
`chain_fn<2>` and so on. Thereby this change allows users of lldb to
inspect the logical coroutine call stack without using any custom debug
scripts (although the display is still a bit clumsy. It would be nicer
to also integrate this into lldb's backtrace feature, but I don't know
how to do so)

The devirtualization currently works by introspecting the function
pointed to by the `destroy` pointer. (The `resume` pointer is not worth
much, given that for the final suspend point `resume` is set to a
nullptr. We have to use the `destroy` pointer instead.) We then look
for a `__promise` variable inside the `destroy` function. This
`__promise` variable is synthetically generated by LLVM, and looking at
its type reveals the type-erased promise_type.

This approach only works for clang-generated code, though. While gcc
also adds a `_Coro_promise` variable to the `resume` function, it does
not do so for the `destroy` function. However, we can't use the `resume`
function, as it will be reset to a nullptr at the final suspension
point. For the time being, I am happy with de-virtualization only working
for clang. A follow-up commit will further improve devirtualization and
also expose the variables spilled to the coroutine frame. As part of
this, I will also revisit gcc support.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132624

Files:
  lldb/source/Plugins/Language/CPlusPlus/Coroutines.cpp
  lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py
  lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/main.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D132624.455431.patch
Type: text/x-patch
Size: 7666 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20220825/c531e36e/attachment-0001.bin>


More information about the lldb-commits mailing list