[coroutines] Support coroutine-handle returning await-suspend (i.e symmetric control transfer)
Summary:
If await_suspend returns a coroutine_handle, as in the example below:
```
coroutine_handle<> await_suspend(coroutine_handle<> h) {
coro.promise().waiter = h;
return coro;
}
```
suspensionExpression processing will resume the coroutine pointed at by that handle.
Related LLVM change rL311751 makes resume calls of this kind `musttail` at any optimization level.
This enables unlimited symmetric control transfer from coroutine to coroutine without blowing up the stack.
Reviewers: GorNishanov
Reviewed By: GorNishanov
Subscribers: rsmith, EricWF, cfe-commits
Differential Revision: https://reviews.llvm.org/D37131
llvm-svn: 311762
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index d23697a..5842e7b 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -181,10 +181,8 @@
auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr());
- if (SuspendRet != nullptr) {
+ if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) {
// Veto suspension if requested by bool returning await_suspend.
- assert(SuspendRet->getType()->isIntegerTy(1) &&
- "Sema should have already checked that it is void or bool");
BasicBlock *RealSuspendBlock =
CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);