@@ -53,6 +53,10 @@ struct clang::CodeGen::CGCoroData {
5353 // handler, this is null.
5454 llvm::Value *ResumeEHVar = nullptr ;
5555
56+ // Stores the i1 that identify if control flows off the end of the coroutine
57+ // body
58+ llvm::PHINode *BodyDone = nullptr ;
59+
5660 // Stores the jump destination just before the coroutine memory is freed.
5761 // This is the destination that every suspend point jumps to for the cleanup
5862 // branch.
@@ -599,14 +603,18 @@ namespace {
599603struct CallCoroDelete final : public EHScopeStack::Cleanup {
600604 Stmt *Deallocate;
601605
602- // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
606+ void Emit (CodeGenFunction &CGF, Flags F) override {
607+ // Cleanup always happens on unwind. No need for pre-cleanup block.
608+ if (F.isForNormalCleanup ())
609+ EmitPreCleanupBB (CGF);
610+ // Emit "if (coro.free(CoroId, CoroBegin)) Deallocate;"
611+
612+ // Note: That deallocation will be emitted twice: once for a normal exit and
613+ // once for exceptional exit. This usage is safe because Deallocate does not
614+ // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
615+ // builds a single call to a deallocation function which is safe to emit
616+ // multiple times.
603617
604- // Note: That deallocation will be emitted twice: once for a normal exit and
605- // once for exceptional exit. This usage is safe because Deallocate does not
606- // contain any declarations. The SubStmtBuilder::makeNewAndDeleteExpr()
607- // builds a single call to a deallocation function which is safe to emit
608- // multiple times.
609- void Emit (CodeGenFunction &CGF, Flags) override {
610618 // Remember the current point, as we are going to emit deallocation code
611619 // first to get to coro.free instruction that is an argument to a delete
612620 // call.
@@ -642,6 +650,37 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup {
642650 CGF.Builder .SetInsertPoint (AfterFreeBB);
643651 }
644652 explicit CallCoroDelete (Stmt *DeallocStmt) : Deallocate(DeallocStmt) {}
653+
654+ private:
655+ // [dcl.fct.def.coroutine]: The coroutine state is destroyed when control
656+ // flows off the end of the coroutine or the destroy member function of a
657+ // coroutine handle that refers to the coroutine is invoked.
658+ void EmitPreCleanupBB (CodeGenFunction &CGF) {
659+ auto &Builder = CGF.Builder ;
660+ auto &Data = *CGF.CurCoro .Data ;
661+ auto *BodyDone = Data.BodyDone ;
662+ BasicBlock *SaveInsertBlock = Builder.GetInsertBlock ();
663+ BasicBlock *PreConvBB = BodyDone->getParent ();
664+ BasicBlock *AfterConvBB =
665+ cast<llvm::BranchInst>(PreConvBB->getTerminator ())->getSuccessor (1 );
666+ BasicBlock *CleanupBB = AfterConvBB->getSingleSuccessor ();
667+ BasicBlock *PreCleanupBB = CleanupBB->splitBasicBlock (
668+ CleanupBB->getFirstNonPHIIt (), " pre.coro.cleanup" , true );
669+ Builder.SetInsertPoint (PreCleanupBB);
670+ PreCleanupBB->getTerminator ()->eraseFromParent ();
671+
672+ auto *NeedCleanup = Builder.CreatePHI (
673+ Builder.getInt1Ty (), llvm::pred_size (PreCleanupBB), " is.completed" );
674+ for (auto *Pred : llvm::predecessors (PreCleanupBB)) {
675+ auto *V = (Pred == AfterConvBB) ? cast<Value>(BodyDone)
676+ : cast<Value>(Builder.getTrue ());
677+ NeedCleanup->addIncoming (V, Pred);
678+ }
679+
680+ auto *RetBB = Data.CleanupJD .getBlock ();
681+ Builder.CreateCondBr (NeedCleanup, CleanupBB, RetBB);
682+ Builder.SetInsertPoint (SaveInsertBlock);
683+ }
645684};
646685}
647686
@@ -691,7 +730,7 @@ struct GetReturnObjectManager {
691730 // split its emission in two parts. EmitGroAlloca emits an alloca and sets up
692731 // cleanups. Later when coroutine promise is available we initialize the gro
693732 // and sets the flag that the cleanup is now active.
694- void EmitGroAlloca () {
733+ void EmitGroActive () {
695734 if (DirectEmit)
696735 return ;
697736
@@ -701,12 +740,23 @@ struct GetReturnObjectManager {
701740 return ;
702741 }
703742
704- auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl ());
705-
706743 // Set GRO flag that it is not initialized yet
707744 GroActiveFlag = CGF.CreateTempAlloca (Builder.getInt1Ty (), CharUnits::One (),
708745 " gro.active" );
709746 Builder.CreateStore (Builder.getFalse (), GroActiveFlag);
747+ }
748+
749+ void EmitGroAlloca () {
750+ if (DirectEmit)
751+ return ;
752+
753+ auto *GroDeclStmt = dyn_cast_or_null<DeclStmt>(S.getResultDecl ());
754+ if (!GroDeclStmt) {
755+ // If get_return_object returns void, no need to do an alloca.
756+ return ;
757+ }
758+
759+ auto *GroVarDecl = cast<VarDecl>(GroDeclStmt->getSingleDecl ());
710760
711761 GroEmission = CGF.EmitAutoVarAlloca (*GroVarDecl);
712762
@@ -768,6 +818,38 @@ struct GetReturnObjectManager {
768818 CGF.EmitAutoVarInit (GroEmission);
769819 Builder.CreateStore (Builder.getTrue (), GroActiveFlag);
770820 }
821+
822+ void EmitGroConv () {
823+ auto *InsertPt = Builder.GetInsertBlock ();
824+ auto *PreConvBB = CGF.CurCoro .Data ->SuspendBB ;
825+ auto *AfterConvBB = CGF.createBasicBlock (" after.gro.conv" , CGF.CurFn , InsertPt);
826+ Builder.SetInsertPoint (AfterConvBB);
827+ BasicBlock *AfterFinalBB = nullptr ;
828+ if (InsertPt) {
829+ AfterFinalBB = InsertPt->getSinglePredecessor ();
830+ InsertPt->replaceAllUsesWith (PreConvBB);
831+ Builder.CreateBr (InsertPt);
832+ }
833+
834+ auto *ConvBB = CGF.createBasicBlock (" gro.conv" , CGF.CurFn , AfterConvBB);
835+ Builder.SetInsertPoint (ConvBB);
836+ Builder.CreateBr (AfterConvBB);
837+
838+ CGF.EmitBlock (PreConvBB);
839+ PreConvBB->moveBefore (ConvBB);
840+ auto *BodyDone =
841+ Builder.CreatePHI (Builder.getInt1Ty (), llvm::pred_size (PreConvBB));
842+ for (auto *Pred : llvm::predecessors (PreConvBB)) {
843+ auto *V = (Pred == AfterFinalBB) ? Builder.getTrue () : Builder.getFalse ();
844+ BodyDone->addIncoming (V, Pred);
845+ }
846+ CGF.CurCoro .Data ->BodyDone = BodyDone;
847+ auto *InRampFn = CGF.CGM .getIntrinsic (llvm::Intrinsic::coro_is_in_ramp);
848+ auto *InRamp = Builder.CreateCall (InRampFn, {}, " InRamp" );
849+ Builder.CreateCondBr (InRamp, ConvBB, AfterConvBB);
850+
851+ Builder.SetInsertPoint (InsertPt == nullptr ? AfterConvBB : InsertPt);
852+ }
771853};
772854} // namespace
773855
@@ -790,12 +872,13 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
790872 auto *InitBB = createBasicBlock (" coro.init" );
791873 auto *FinalBB = createBasicBlock (" coro.final" );
792874 auto *RetBB = createBasicBlock (" coro.ret" );
875+ auto *PreConvBB = createBasicBlock (" pre.gvo.conv" );
793876
794877 auto *CoroId = Builder.CreateCall (
795878 CGM.getIntrinsic (llvm::Intrinsic::coro_id),
796879 {Builder.getInt32 (NewAlign), NullPtr, NullPtr, NullPtr});
797880 createCoroData (*this , CurCoro, CoroId);
798- CurCoro.Data ->SuspendBB = RetBB ;
881+ CurCoro.Data ->SuspendBB = PreConvBB ;
799882 assert (ShouldEmitLifetimeMarkers &&
800883 " Must emit lifetime intrinsics for coroutines" );
801884
@@ -840,7 +923,6 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
840923 CurCoro.Data ->CoroBegin = CoroBegin;
841924
842925 GetReturnObjectManager GroManager (*this , S);
843- GroManager.EmitGroAlloca ();
844926
845927 CurCoro.Data ->CleanupJD = getJumpDestInCurrentScope (RetBB);
846928 {
@@ -884,6 +966,7 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
884966 // not needed.
885967 }
886968
969+ GroManager.EmitGroActive ();
887970 EmitStmt (S.getPromiseDeclStmt ());
888971
889972 Address PromiseAddr = GetAddrOfLocalVar (S.getPromiseDecl ());
@@ -895,6 +978,7 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
895978 CoroId->setArgOperand (1 , PromiseAddrVoidPtr);
896979
897980 // Now we have the promise, initialize the GRO
981+ GroManager.EmitGroAlloca ();
898982 GroManager.EmitGroInit ();
899983
900984 EHStack.pushCleanup <CallCoroEnd>(EHCleanup);
@@ -950,11 +1034,12 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
9501034 // We don't need FinalBB. Emit it to make sure the block is deleted.
9511035 EmitBlock (FinalBB, /* IsFinished=*/ true );
9521036 }
1037+ GroManager.EmitGroConv ();
9531038 }
9541039
9551040 EmitBlock (RetBB);
956- // Emit coro.end before getReturnStmt ( and parameter destructors), since
957- // resume and destroy parts of the coroutine should not include them .
1041+ // Emit coro.end before ret instruction, since resume and destroy parts of the
1042+ // coroutine should return void .
9581043 llvm::Function *CoroEnd = CGM.getIntrinsic (llvm::Intrinsic::coro_end);
9591044 Builder.CreateCall (CoroEnd,
9601045 {NullPtr, Builder.getFalse (),
@@ -973,8 +1058,13 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
9731058 // shouldn't change the AST.
9741059 if (PreviousRetValue)
9751060 cast<ReturnStmt>(Ret)->setRetValue (PreviousRetValue);
1061+ // Send GRO conversion to ConvBB
1062+ auto *ConvBB =
1063+ cast<llvm::BranchInst>(PreConvBB->getTerminator ())->getSuccessor (0 );
1064+ auto FromIt = ++RetBB->getFirstInsertionPt ();
1065+ auto ToIt = RetBB->getTerminator ()->getIterator ();
1066+ ConvBB->splice (ConvBB->getFirstNonPHIIt (), RetBB, FromIt, ToIt);
9761067 }
977-
9781068 // LLVM require the frontend to mark the coroutine.
9791069 CurFn->setPresplitCoroutine ();
9801070
0 commit comments