@@ -161,8 +161,13 @@ void LLVMBuildUtils::init(llvm::Function *function, BlockPrototype *procedurePro
161161 reloadVariables ();
162162 reloadLists ();
163163
164- // Create end branch
164+ // Mark the target as valid
165+ m_targetValidFlag = m_builder.CreateAlloca (m_builder.getInt1Ty ());
166+ m_builder.CreateStore (m_builder.getInt1 (true ), m_targetValidFlag);
167+
168+ // Create end branches
165169 m_endBranch = llvm::BasicBlock::Create (m_llvmCtx, " end" , m_function);
170+ m_endThreadBranch = llvm::BasicBlock::Create (m_llvmCtx, " endThread" , m_function);
166171}
167172
168173void LLVMBuildUtils::end (LLVMInstruction *lastInstruction, LLVMRegister *lastConstant)
@@ -184,9 +189,9 @@ void LLVMBuildUtils::end(LLVMInstruction *lastInstruction, LLVMRegister *lastCon
184189 syncVariables ();
185190 m_builder.CreateBr (m_endBranch);
186191
192+ // End branch
187193 m_builder.SetInsertPoint (m_endBranch);
188194
189- // End the script function
190195 llvm::PointerType *pointerType = llvm::PointerType::get (llvm::Type::getInt8Ty (m_llvmCtx), 0 );
191196
192197 switch (m_codeType) {
@@ -216,6 +221,33 @@ void LLVMBuildUtils::end(LLVMInstruction *lastInstruction, LLVMRegister *lastCon
216221 m_builder.CreateRet (castValue (lastConstant, Compiler::StaticType::Bool));
217222 break ;
218223 }
224+
225+ // Thread end branch (stop the entire thread, including procedure callers)
226+ m_builder.SetInsertPoint (m_endThreadBranch);
227+
228+ switch (m_codeType) {
229+ case Compiler::CodeType::Script:
230+ // Mark the thread as finished
231+ m_builder.CreateCall (m_functions.resolve_llvm_mark_thread_as_finished (), { m_executionContextPtr });
232+
233+ // Return a sentinel value (special pointer) to terminate any procedure callers
234+ if (m_warp)
235+ m_builder.CreateRet (threadEndSentinel ());
236+ else if (m_procedurePrototype)
237+ m_coroutine->endWithSentinel (threadEndSentinel ());
238+ else {
239+ // There's no need to return the sentinel value in standard scripts because they don't have any callers
240+ m_coroutine->end ();
241+ }
242+
243+ break ;
244+
245+ case Compiler::CodeType::Reporter:
246+ case Compiler::CodeType::HatPredicate:
247+ // Procedures cannot be called by these scripts, so we don't have to return the sentinel value
248+ m_builder.CreateBr (m_endBranch);
249+ break ;
250+ }
219251}
220252
221253LLVMCompilerContext *LLVMBuildUtils::compilerCtx () const
@@ -323,6 +355,17 @@ llvm::BasicBlock *LLVMBuildUtils::endBranch() const
323355 return m_endBranch;
324356}
325357
358+ llvm::BasicBlock *LLVMBuildUtils::endThreadBranch () const
359+ {
360+ return m_endThreadBranch;
361+ }
362+
363+ llvm::Value *LLVMBuildUtils::threadEndSentinel () const
364+ {
365+ llvm::PointerType *pointerType = llvm::PointerType::get (llvm::Type::getInt8Ty (m_llvmCtx), 0 );
366+ return m_builder.CreateIntToPtr (m_builder.getInt64 (1 ), pointerType, " threadEndSentinel" );
367+ }
368+
326369BlockPrototype *LLVMBuildUtils::procedurePrototype () const
327370{
328371 return m_procedurePrototype;
@@ -401,6 +444,12 @@ LLVMListPtr &LLVMBuildUtils::listPtr(List *list)
401444
402445void LLVMBuildUtils::syncVariables ()
403446{
447+ llvm::BasicBlock *syncBlock = llvm::BasicBlock::Create (m_llvmCtx, " syncVariables" , m_function);
448+ llvm::BasicBlock *syncNextBlock = llvm::BasicBlock::Create (m_llvmCtx, " syncVariables.next" , m_function);
449+ m_builder.CreateCondBr (m_builder.CreateLoad (m_builder.getInt1Ty (), m_targetValidFlag), syncBlock, syncNextBlock);
450+
451+ m_builder.SetInsertPoint (syncBlock);
452+
404453 // Copy stack variables to the actual variables
405454 for (auto &[var, varPtr] : m_variablePtrs) {
406455 llvm::BasicBlock *copyBlock = llvm::BasicBlock::Create (m_llvmCtx, " syncVar" , m_function);
@@ -414,6 +463,9 @@ void LLVMBuildUtils::syncVariables()
414463
415464 m_builder.SetInsertPoint (nextBlock);
416465 }
466+
467+ m_builder.CreateBr (syncNextBlock);
468+ m_builder.SetInsertPoint (syncNextBlock);
417469}
418470
419471void LLVMBuildUtils::reloadVariables ()
@@ -444,6 +496,11 @@ void LLVMBuildUtils::reloadLists()
444496 }
445497}
446498
499+ void LLVMBuildUtils::invalidateTarget ()
500+ {
501+ m_builder.CreateStore (m_builder.getInt1 (false ), m_targetValidFlag);
502+ }
503+
447504std::vector<LLVMIfStatement> &LLVMBuildUtils::ifStatements ()
448505{
449506 return m_ifStatements;
0 commit comments