[llvm] [clang] [coroutine] Implement llvm.coro.await.suspend intrinsic (PR #79712)
Chuanqi Xu via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 30 19:42:34 PST 2024
================
@@ -232,16 +237,59 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);
auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
- CGF.CurCoro.InSuspendBlock = true;
- auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr());
- CGF.CurCoro.InSuspendBlock = false;
+ const auto AwaitSuspendCanThrow =
+ AwaitSuspendStmtCanThrow(S.getSuspendExpr());
+
+ auto SuspendHelper = CodeGenFunction(CGF.CGM).generateAwaitSuspendHelper(
+ CGF.CurFn->getName(), Prefix, S, AwaitSuspendCanThrow);
- if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) {
- // Veto suspension if requested by bool returning await_suspend.
- BasicBlock *RealSuspendBlock =
- CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
- CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
- CGF.EmitBlock(RealSuspendBlock);
+ llvm::CallBase *SuspendRet = nullptr;
+
+ {
+ CGF.CurCoro.InSuspendBlock = true;
+
+ auto FramePtrBinder = CodeGenFunction::OpaqueValueMappingData::bind(
+ CGF, S.getOpaqueFramePtr(), S.getOpaqueFramePtr()->getSourceExpr());
+ auto UnbindFramePtrOnExit =
+ llvm::make_scope_exit([&] { FramePtrBinder.unbind(CGF); });
+
+ SmallVector<llvm::Value *, 3> SuspendHelperCallArgs;
+ SuspendHelperCallArgs.push_back(
+ CGF.getOrCreateOpaqueLValueMapping(S.getOpaqueValue()).getPointer(CGF));
+ SuspendHelperCallArgs.push_back(
+ CGF.getOrCreateOpaqueRValueMapping(S.getOpaqueFramePtr())
+ .getScalarVal());
+ SuspendHelperCallArgs.push_back(SuspendHelper);
+
+ auto IID = llvm::Intrinsic::coro_await_suspend;
+ if (S.getSuspendExpr()->getType()->isBooleanType())
+ IID = llvm::Intrinsic::coro_await_suspend_bool;
+ else if (S.getSuspendExpr()->getType()->isVoidPointerType())
+ IID = llvm::Intrinsic::coro_await_suspend_handle;
+
+ llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(IID);
+ // FIXME: add call attributes?
+ if (AwaitSuspendCanThrow)
+ SuspendRet =
+ CGF.EmitCallOrInvoke(AwaitSuspendIntrinsic, SuspendHelperCallArgs);
+ else
+ SuspendRet = CGF.EmitNounwindRuntimeCall(AwaitSuspendIntrinsic,
+ SuspendHelperCallArgs);
+
+ CGF.CurCoro.InSuspendBlock = false;
+ }
+
+ if (SuspendRet != nullptr) {
+ if (SuspendRet->getType()->isIntegerTy(1)) {
+ // Veto suspension if requested by bool returning await_suspend.
+ BasicBlock *RealSuspendBlock =
+ CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
+ CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
+ CGF.EmitBlock(RealSuspendBlock);
+ } else if (SuspendRet->getType()->isPointerTy()) {
+ auto ResumeIntrinsic = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_resume);
+ Builder.CreateCall(ResumeIntrinsic, SuspendRet);
+ }
----------------
ChuanqiXu9 wrote:
```suggestion
} else
llvm_unreachable(...);
```
nit: personal interest.
https://github.com/llvm/llvm-project/pull/79712
More information about the llvm-commits
mailing list