22
33#include < llvm/Support/TargetSelect.h>
44#include < llvm/Passes/PassBuilder.h>
5+ #include < llvm/IR/Verifier.h>
56
67#include < scratchcpp/target.h>
78#include < iostream>
@@ -16,7 +17,8 @@ LLVMCompilerContext::LLVMCompilerContext(IEngine *engine, Target *target) :
1617 m_module(std::make_unique<llvm::Module>(target ? target->name () : "", *m_llvmCtx)),
1718 m_llvmCtxPtr(m_llvmCtx.get()),
1819 m_modulePtr(m_module.get()),
19- m_jit((initTarget(), llvm::orc::LLJITBuilder().create()))
20+ m_jit((initTarget(), llvm::orc::LLJITBuilder().create())),
21+ m_llvmCoroDestroyFunction(createCoroDestroyFunction())
2022{
2123 if (!m_jit) {
2224 llvm::errs () << " error: failed to create JIT: " << toString (m_jit.takeError ()) << " \n " ;
@@ -46,6 +48,8 @@ void LLVMCompilerContext::initJit()
4648 return ;
4749 }
4850
51+ assert (m_llvmCoroDestroyFunction);
52+ const std::string coroDestroyFuncName = m_llvmCoroDestroyFunction->getName ().str ();
4953 m_jitInitialized = true ;
5054 assert (m_llvmCtx);
5155 assert (m_module);
@@ -96,16 +100,56 @@ void LLVMCompilerContext::initJit()
96100#endif
97101 lookupFunction<void *>(name);
98102 }
103+
104+ // Lookup coro_destroy()
105+ m_coroDestroyFunction = lookupFunction<DestroyCoroFuncType>(coroDestroyFuncName);
106+ assert (m_coroDestroyFunction);
99107}
100108
101109bool LLVMCompilerContext::jitInitialized () const
102110{
103111 return m_jitInitialized;
104112}
105113
114+ void LLVMCompilerContext::destroyCoroutine (void *handle)
115+ {
116+ if (!m_jitInitialized) {
117+ std::cout << " error: JIT must be initialized to destroy coroutines" << std::endl;
118+ assert (false );
119+ }
120+
121+ assert (m_coroDestroyFunction);
122+ m_coroDestroyFunction (handle);
123+ }
124+
106125void LLVMCompilerContext::initTarget ()
107126{
108127 llvm::InitializeNativeTarget ();
109128 llvm::InitializeNativeTargetAsmPrinter ();
110129 llvm::InitializeNativeTargetAsmParser ();
111130}
131+
132+ llvm::Function *LLVMCompilerContext::createCoroDestroyFunction ()
133+ {
134+ llvm::IRBuilder<> builder (*m_llvmCtx);
135+
136+ // void coro_destroy(void *handle)
137+ llvm::FunctionType *funcType = llvm::FunctionType::get (builder.getVoidTy (), builder.getVoidTy ()->getPointerTo (), false );
138+ llvm::Function *func = llvm::Function::Create (funcType, llvm::Function::ExternalLinkage, " coro_destroy" , m_module.get ());
139+ func->setComdat (m_module->getOrInsertComdat (func->getName ()));
140+ func->setDSOLocal (true );
141+ func->addFnAttr (llvm::Attribute::NoInline);
142+ func->addFnAttr (llvm::Attribute::OptimizeNone);
143+
144+ llvm::BasicBlock *entry = llvm::BasicBlock::Create (*m_llvmCtx, " entry" , func);
145+ builder.SetInsertPoint (entry);
146+ builder.CreateCall (llvm::Intrinsic::getDeclaration (m_module.get (), llvm::Intrinsic::coro_destroy), { func->getArg (0 ) });
147+ builder.CreateRetVoid ();
148+
149+ if (llvm::verifyFunction (*func, &llvm::errs ())) {
150+ llvm::errs () << " error: coro_destroy() function verficiation failed!\n " ;
151+ llvm::errs () << " module name: " << m_module->getName () << " \n " ;
152+ }
153+
154+ return func;
155+ }
0 commit comments