@@ -35,15 +35,23 @@ LLVMCoroutine::LLVMCoroutine(llvm::Module *module, llvm::IRBuilder<> *builder, l
3535
3636 // Begin
3737 m_handle = builder->CreateCall (coroBegin, { coroIdRet, alloc });
38+
3839 m_didSuspendVar = builder->CreateAlloca (builder->getInt1Ty (), nullptr , " didSuspend" );
3940 builder->CreateStore (builder->getInt1 (false ), m_didSuspendVar);
41+
42+ m_sentinelVar = builder->CreateAlloca (pointerType, nullptr , " sentinel" );
43+ builder->CreateStore (nullPointer, m_sentinelVar);
44+
4045 llvm::BasicBlock *entry = builder->GetInsertBlock ();
4146
4247 // Create suspend branch
4348 m_suspendBlock = llvm::BasicBlock::Create (ctx, " suspend" , func);
4449 builder->SetInsertPoint (m_suspendBlock);
50+
51+ llvm::Value *sentinelValue = builder->CreateLoad (pointerType, m_sentinelVar);
52+ llvm::Value *sentinelIsNull = builder->CreateIsNull (sentinelValue);
4553 builder->CreateCall (coroEnd, { m_handle, builder->getInt1 (false ), llvm::ConstantTokenNone::get (ctx) });
46- builder->CreateRet (m_handle);
54+ builder->CreateRet (builder-> CreateSelect (sentinelIsNull, m_handle, sentinelValue) );
4755
4856 // Create free branches
4957 m_freeMemRetBlock = llvm::BasicBlock::Create (ctx, " freeMemRet" , func);
@@ -63,6 +71,15 @@ LLVMCoroutine::LLVMCoroutine(llvm::Module *module, llvm::IRBuilder<> *builder, l
6371 llvm::Value *needFree = builder->CreateIsNotNull (mem);
6472 builder->CreateCondBr (needFree, freeBranch, m_suspendBlock);
6573
74+ // Create final suspend point
75+ m_finalSuspendBlock = llvm::BasicBlock::Create (ctx, " finalSuspend" , m_function);
76+
77+ m_builder->SetInsertPoint (m_finalSuspendBlock);
78+ llvm::Value *suspendResult = m_builder->CreateCall (llvm::Intrinsic::getDeclaration (m_module, llvm::Intrinsic::coro_suspend), { llvm::ConstantTokenNone::get (ctx), m_builder->getInt1 (true ) });
79+ llvm::SwitchInst *sw = m_builder->CreateSwitch (suspendResult, m_suspendBlock, 2 );
80+ sw->addCase (m_builder->getInt8 (0 ), m_freeMemRetBlock);
81+ sw->addCase (m_builder->getInt8 (1 ), m_cleanupBlock);
82+
6683 builder->SetInsertPoint (entry);
6784}
6885
@@ -135,20 +152,11 @@ llvm::Value *LLVMCoroutine::createResume(llvm::Module *module, llvm::IRBuilder<>
135152
136153void LLVMCoroutine::end ()
137154{
138- llvm::LLVMContext &ctx = m_builder->getContext ();
139-
140- // Add final suspend point
141- llvm::BasicBlock *endBranch = llvm::BasicBlock::Create (ctx, " end" , m_function);
142- llvm::BasicBlock *finalSuspendBranch = llvm::BasicBlock::Create (ctx, " finalSuspend" , m_function);
143- m_builder->CreateCondBr (m_builder->CreateLoad (m_builder->getInt1Ty (), m_didSuspendVar), finalSuspendBranch, endBranch);
144-
145- m_builder->SetInsertPoint (finalSuspendBranch);
146- llvm::Value *suspendResult = m_builder->CreateCall (llvm::Intrinsic::getDeclaration (m_module, llvm::Intrinsic::coro_suspend), { llvm::ConstantTokenNone::get (ctx), m_builder->getInt1 (true ) });
147- llvm::SwitchInst *sw = m_builder->CreateSwitch (suspendResult, m_suspendBlock, 2 );
148- sw->addCase (m_builder->getInt8 (0 ), endBranch); // unreachable
149- sw->addCase (m_builder->getInt8 (1 ), m_cleanupBlock);
155+ m_builder->CreateCondBr (m_builder->CreateLoad (m_builder->getInt1Ty (), m_didSuspendVar), m_finalSuspendBlock, m_freeMemRetBlock);
156+ }
150157
151- // Jump to "free and return" branch
152- m_builder->SetInsertPoint (endBranch);
153- m_builder->CreateBr (m_freeMemRetBlock);
158+ void LLVMCoroutine::endWithSentinel (llvm::Value *sentinel)
159+ {
160+ m_builder->CreateStore (sentinel, m_sentinelVar);
161+ end ();
154162}
0 commit comments