================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits