Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Coroutine][Sema] Tighten the lifetime of symmetric transfer returned…
… handle In generating the code for symmetric transfer, a temporary object is created to store the returned handle from await_suspend() call of the awaiter. Previously this temp won't be cleaned up until very later, which ends up causing this temp to be spilled to the heap. However, we know that this temp will no longer be needed after the coro_resume call. We can clean it up right after. Differential Revision: https://reviews.llvm.org/D87470
- Loading branch information
Showing
3 changed files
with
58 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// RUN: %clang -std=c++14 -fcoroutines-ts -emit-llvm -S -O1 %s -o - | ||
|
||
#include "Inputs/coroutine.h" | ||
|
||
namespace coro = std::experimental::coroutines_v1; | ||
|
||
struct detached_task { | ||
struct promise_type { | ||
detached_task get_return_object() noexcept { | ||
return detached_task{coro::coroutine_handle<promise_type>::from_promise(*this)}; | ||
} | ||
|
||
void return_void() noexcept {} | ||
|
||
struct final_awaiter { | ||
bool await_ready() noexcept { return false; } | ||
coro::coroutine_handle<> await_suspend(coro::coroutine_handle<promise_type> h) noexcept { | ||
h.destroy(); | ||
return {}; | ||
} | ||
void await_resume() noexcept {} | ||
}; | ||
|
||
void unhandled_exception() noexcept {} | ||
|
||
final_awaiter final_suspend() noexcept { return {}; } | ||
|
||
coro::suspend_always initial_suspend() noexcept { return {}; } | ||
}; | ||
|
||
~detached_task() { | ||
if (coro_) { | ||
coro_.destroy(); | ||
coro_ = {}; | ||
} | ||
} | ||
|
||
void start() && { | ||
auto tmp = coro_; | ||
coro_ = {}; | ||
tmp.resume(); | ||
} | ||
|
||
coro::coroutine_handle<promise_type> coro_; | ||
}; | ||
|
||
detached_task foo() { | ||
co_return; | ||
} | ||
|
||
// check that the lifetime of the coroutine handle used to obtain the address ended right away. | ||
// CHECK: %{{.*}} = call i8* @{{.*address.*}}(%"struct.std::experimental::coroutines_v1::coroutine_handle.0"* nonnull %{{.*}}) | ||
// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %{{.*}}) |