This reverts commit 4346318f5c.
This test case is failing on macOS, reverting until it can be
looked at more closely to unblock the macOS CI bots.
```
File "/Volumes/work/llvm/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py", line 121, in test_libcpp
self.do_test(USE_LIBCPP)
File "/Volumes/work/llvm/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py", line 45, in do_test
self.expect_expr("noop_hdl",
File "/Volumes/work/llvm/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 2441, in expect_expr
value_check.check_value(self, eval_result, str(eval_result))
File "/Volumes/work/llvm/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 306, in check_value
test_base.assertEqual(self.expect_summary, val.GetSummary(),
AssertionError: 'noop_coroutine' != 'coro frame = 0x100004058'
- noop_coroutine+ coro frame = 0x100004058 : (std::coroutine_handle<void>) $1 = coro frame = 0x100004058 {
resume = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
destroy = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
}
Checking SBValue: (std::coroutine_handle<void>) $1 = coro frame = 0x100004058 {
resume = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
destroy = 0x0000000100003344 (a.out`___lldb_unnamed_symbol223)
}
```
Those lldb_unnamed_symbols are synthetic names that ObjectFileMachO
adds to the symbol table, most often seen with stripped binaries,
based off of the function start addresses for all the functions -
if a function has no symbol name, lldb adds one of these names.
This change was originally landed via https://reviews.llvm.org/D132624
This reverts commit cd3091a88f.
This change crashes on macOS systems in
formatters::StdlibCoroutineHandleSyntheticFrontEnd when
it fails to create the `ValueObjectSP promise` and calls
a method on it. The failure causes a segfault while running
TestCoroutineHandle.py on the "LLDB Incremental" CI bot,
https://green.lab.llvm.org/green/view/LLDB/job/lldb-cmake/
This change originally landed via https://reviews.llvm.org/D132815
So far, the pretty printer for `std::coroutine_handle` internally
dereferenced the contained frame pointer displayed the `promise`
as a sub-value. As noticed in https://reviews.llvm.org/D132624
by @labath, this can lead to an endless loop in lldb during printing
if the coroutine frame pointers form a cycle.
This commit breaks the cycle by exposing the `promise` as a pointer
type instead of a value type. The depth to which the `frame variable`
and the `expression` commands dereference those pointers can be
controlled using the `--ptr-depth` argument.
Differential Revision: https://reviews.llvm.org/D132815
With this commit, the `std::coroutine_handle` pretty printer now
recognizes `std::noop_coroutine()` handles. For noop coroutine handles,
we identify use the summary string `noop_coroutine` and we don't print
children
Instead of
```
(std::coroutine_handle<void>) $3 = coro frame = 0x555555559058 {
resume = 0x00005555555564f0 (a.out`std::__1::coroutine_handle<std::__1::noop_coroutine_promise>::__noop_coroutine_frame_ty_::__dummy_resume_destroy_func() at noop_coroutine_handle.h:79)
destroy = 0x00005555555564f0 (a.out`std::__1::coroutine_handle<std::__1::noop_coroutine_promise>::__noop_coroutine_frame_ty_::__dummy_resume_destroy_func() at noop_coroutine_handle.h:79)
}
```
we now print
```
(std::coroutine_handle<void>) $3 = noop_coroutine
```
Differential Revision: https://reviews.llvm.org/D132735
The original commit was missing a `ClangASTImporter::CopyType` call.
Original commit message:
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.
Differential Revision: https://reviews.llvm.org/D132624
When a process gets restarted TypeSystem objects associated with it
may get deleted, and any CompilerType objects holding on to a
reference to that type system are a use-after-free in waiting. Because
of the SBAPI, we don't have tight control over where CompilerTypes go
and when they are used. This is particularly a problem in the Swift
plugin, where the scratch TypeSystem can be restarted while the
process is still running. The Swift plugin has a lock to prevent
abuse, but where there's a lock there can be bugs.
This patch changes CompilerType to store a std::weak_ptr<TypeSystem>.
Most of the std::weak_ptr<TypeSystem>* uglyness is hidden by
introducing a wrapper class CompilerType::WrappedTypeSystem that has a
dyn_cast_or_null() method. The only sites that need to know about the
weak pointer implementation detail are the ones that deal with
creating TypeSystems.
rdar://101505232
Differential Revision: https://reviews.llvm.org/D136650
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.
Differential Revision: https://reviews.llvm.org/D132624
This patch adds a formatter for `std::coroutine_handle`, both for libc++
and libstdc++. For the type-erased `coroutine_handle<>`, it shows the
`resume` and `destroy` function pointers. For a non-type-erased
`coroutine_handle<promise_type>` it also shows the `promise` value.
With this change, executing the `v t` command on the example from
https://clang.llvm.org/docs/DebuggingCoroutines.html now outputs
```
(task) t = {
handle = coro frame = 0x55555555b2a0 {
resume = 0x0000555555555a10 (a.out`coro_task(int, int) at llvm-example.cpp:36)
destroy = 0x0000555555556090 (a.out`coro_task(int, int) at llvm-example.cpp:36)
}
}
```
instead of just
```
(task) t = {
handle = {
__handle_ = 0x55555555b2a0
}
}
```
Note, how the symbols for the `resume` and `destroy` function pointer
reveal which coroutine is stored inside the `std::coroutine_handle`.
A follow-up commit will use this fact to infer the coroutine's promise
type and the representation of its internal coroutine state based on
the `resume` and `destroy` pointers.
The same formatter is used for both libc++ and libstdc++. It would
also work for MSVC's standard library, however it is not registered
for MSVC, given that lldb does not provide pretty printers for other
MSVC types, either.
The formatter is in a newly added `Coroutines.{h,cpp}` file because there
does not seem to be an already existing place where we could share
formatters across libc++ and libstdc++. Also, I expect this code to grow
as we improve debugging experience for coroutines further.
**Testing**
* Added API test
Differential Revision: https://reviews.llvm.org/D132415