Skip to content

Commit 096036f

Browse files
committed
LLVMCodeBuilder: Create a global resume function in LLVMCompilerContext
The previous logic was incorrect because the resume function was resolved using getOrCreateFunction() and then filled with code, even if it existed. Since it's global and can be used in the entire LLVM module, create it in LLVMCompilerContext.
1 parent 83f3aa5 commit 096036f

File tree

6 files changed

+64
-51
lines changed

6 files changed

+64
-51
lines changed

src/engine/internal/llvm/llvmcodebuilder.cpp

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,8 +1268,7 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
12681268

12691269
m_builder.SetInsertPoint(suspendBranch);
12701270
createSuspend(coro.get(), warpArg, targetVariables);
1271-
name = getResumeFunctionName(step.procedurePrototype);
1272-
llvm::Value *done = m_builder.CreateCall(resolveFunction(name, m_resumeFuncType), { handle });
1271+
llvm::Value *done = m_builder.CreateCall(m_ctx->coroutineResumeFunction(), { handle });
12731272
m_builder.CreateCondBr(done, nextBranch, suspendBranch);
12741273

12751274
m_builder.SetInsertPoint(nextBranch);
@@ -1329,24 +1328,7 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
13291328

13301329
verifyFunction(m_function);
13311330

1332-
// Create resume function
1333-
// bool resume(void *)
1334-
funcName = getResumeFunctionName(m_procedurePrototype);
1335-
llvm::Function *resumeFunc = getOrCreateFunction(funcName, m_resumeFuncType);
1336-
resumeFunc->addFnAttr(llvm::Attribute::NoInline);
1337-
resumeFunc->addFnAttr(llvm::Attribute::OptimizeNone);
1338-
1339-
entry = llvm::BasicBlock::Create(m_llvmCtx, "entry", resumeFunc);
1340-
m_builder.SetInsertPoint(entry);
1341-
1342-
if (m_warp)
1343-
m_builder.CreateRet(m_builder.getInt1(true));
1344-
else
1345-
m_builder.CreateRet(coro->createResume(resumeFunc, resumeFunc->getArg(0)));
1346-
1347-
verifyFunction(resumeFunc);
1348-
1349-
return std::make_shared<LLVMExecutableCode>(m_ctx, m_function->getName().str(), resumeFunc->getName().str(), m_codeType);
1331+
return std::make_shared<LLVMExecutableCode>(m_ctx, m_function->getName().str(), m_ctx->coroutineResumeFunction()->getName().str(), m_codeType);
13501332
}
13511333

13521334
CompilerValue *LLVMCodeBuilder::addFunctionCall(const std::string &functionName, Compiler::StaticType returnType, const Compiler::ArgTypes &argTypes, const Compiler::Args &args)
@@ -1890,7 +1872,6 @@ void LLVMCodeBuilder::initTypes()
18901872
llvm::PointerType *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0);
18911873
m_valueDataType = LLVMTypes::createValueDataType(&m_builder);
18921874
m_stringPtrType = LLVMTypes::createStringPtrType(&m_builder);
1893-
m_resumeFuncType = llvm::FunctionType::get(m_builder.getInt1Ty(), pointerType, false);
18941875
}
18951876

18961877
void LLVMCodeBuilder::createVariableMap()
@@ -2015,11 +1996,6 @@ std::string LLVMCodeBuilder::getMainFunctionName(BlockPrototype *procedureProtot
20151996
return procedurePrototype ? "proc." + procedurePrototype->procCode() : name;
20161997
}
20171998

2018-
std::string LLVMCodeBuilder::getResumeFunctionName(BlockPrototype *procedurePrototype)
2019-
{
2020-
return procedurePrototype ? "resume.proc." + procedurePrototype->procCode() : "resume.script";
2021-
}
2022-
20231999
llvm::FunctionType *LLVMCodeBuilder::getMainFunctionType(BlockPrototype *procedurePrototype)
20242000
{
20252001
// void *f(ExecutionContext *, Target *, ValueData **, List **, (warp arg), (procedure args...))

src/engine/internal/llvm/llvmcodebuilder.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ class LLVMCodeBuilder : public ICodeBuilder
130130
void popLoopScope();
131131

132132
std::string getMainFunctionName(BlockPrototype *procedurePrototype);
133-
std::string getResumeFunctionName(BlockPrototype *procedurePrototype);
134133
llvm::FunctionType *getMainFunctionType(BlockPrototype *procedurePrototype);
135134
llvm::Function *getOrCreateFunction(const std::string &name, llvm::FunctionType *type);
136135
void verifyFunction(llvm::Function *func);
@@ -230,7 +229,6 @@ class LLVMCodeBuilder : public ICodeBuilder
230229

231230
llvm::StructType *m_valueDataType = nullptr;
232231
llvm::StructType *m_stringPtrType = nullptr;
233-
llvm::FunctionType *m_resumeFuncType = nullptr;
234232

235233
LLVMInstructionList m_instructions;
236234
std::vector<std::shared_ptr<LLVMRegister>> m_regs;

src/engine/internal/llvm/llvmcompilercontext.cpp

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <iostream>
99

1010
#include "llvmcompilercontext.h"
11+
#include "llvmcoroutine.h"
1112

1213
using namespace libscratchcpp;
1314

@@ -18,6 +19,7 @@ LLVMCompilerContext::LLVMCompilerContext(IEngine *engine, Target *target) :
1819
m_llvmCtxPtr(m_llvmCtx.get()),
1920
m_modulePtr(m_module.get()),
2021
m_jit((initTarget(), llvm::orc::LLJITBuilder().create())),
22+
m_llvmCoroResumeFunction(createCoroResumeFunction()),
2123
m_llvmCoroDestroyFunction(createCoroDestroyFunction())
2224
{
2325
if (!m_jit) {
@@ -111,6 +113,11 @@ bool LLVMCompilerContext::jitInitialized() const
111113
return m_jitInitialized;
112114
}
113115

116+
llvm::Function *LLVMCompilerContext::coroutineResumeFunction() const
117+
{
118+
return m_llvmCoroResumeFunction;
119+
}
120+
114121
void LLVMCompilerContext::destroyCoroutine(void *handle)
115122
{
116123
if (!m_jitInitialized) {
@@ -129,6 +136,26 @@ void LLVMCompilerContext::initTarget()
129136
llvm::InitializeNativeTargetAsmParser();
130137
}
131138

139+
llvm::Function *LLVMCompilerContext::createCoroResumeFunction()
140+
{
141+
llvm::IRBuilder<> builder(*m_llvmCtx);
142+
143+
// bool coro_resume(void *handle)
144+
llvm::FunctionType *funcType = llvm::FunctionType::get(builder.getInt1Ty(), builder.getVoidTy()->getPointerTo(), false);
145+
llvm::Function *func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "coro_resume", m_module.get());
146+
func->setComdat(m_module->getOrInsertComdat(func->getName()));
147+
func->setDSOLocal(true);
148+
func->addFnAttr(llvm::Attribute::NoInline);
149+
func->addFnAttr(llvm::Attribute::OptimizeNone);
150+
151+
llvm::BasicBlock *entry = llvm::BasicBlock::Create(*m_llvmCtx, "entry", func);
152+
builder.SetInsertPoint(entry);
153+
builder.CreateRet(LLVMCoroutine::createResume(m_module.get(), &builder, func, func->getArg(0)));
154+
155+
verifyFunction(func);
156+
return func;
157+
}
158+
132159
llvm::Function *LLVMCompilerContext::createCoroDestroyFunction()
133160
{
134161
llvm::IRBuilder<> builder(*m_llvmCtx);
@@ -146,10 +173,14 @@ llvm::Function *LLVMCompilerContext::createCoroDestroyFunction()
146173
builder.CreateCall(llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::coro_destroy), { func->getArg(0) });
147174
builder.CreateRetVoid();
148175

149-
if (llvm::verifyFunction(*func, &llvm::errs())) {
150-
llvm::errs() << "error: coro_destroy() function verficiation failed!\n";
176+
verifyFunction(func);
177+
return func;
178+
}
179+
180+
void LLVMCompilerContext::verifyFunction(llvm::Function *function)
181+
{
182+
if (llvm::verifyFunction(*function, &llvm::errs())) {
183+
llvm::errs() << "error: " << function->getName() << "function verficiation failed!\n";
151184
llvm::errs() << "module name: " << m_module->getName() << "\n";
152185
}
153-
154-
return func;
155186
}

src/engine/internal/llvm/llvmcompilercontext.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class LLVMCompilerContext : public CompilerContext
2828
void initJit();
2929
bool jitInitialized() const;
3030

31+
llvm::Function *coroutineResumeFunction() const;
3132
void destroyCoroutine(void *handle);
3233

3334
template<typename T>
@@ -44,19 +45,26 @@ class LLVMCompilerContext : public CompilerContext
4445
}
4546

4647
private:
48+
using ResumeCoroFuncType = bool (*)(void *);
4749
using DestroyCoroFuncType = void (*)(void *);
4850

4951
void initTarget();
52+
llvm::Function *createCoroResumeFunction();
5053
llvm::Function *createCoroDestroyFunction();
5154

55+
void verifyFunction(llvm::Function *function);
56+
5257
std::unique_ptr<llvm::LLVMContext> m_llvmCtx;
5358
std::unique_ptr<llvm::Module> m_module;
5459
llvm::LLVMContext *m_llvmCtxPtr = nullptr;
5560
llvm::Module *m_modulePtr = nullptr;
5661
llvm::Expected<std::unique_ptr<llvm::orc::LLJIT>> m_jit;
62+
bool m_jitInitialized = false;
63+
64+
llvm::Function *m_llvmCoroResumeFunction = nullptr;
65+
5766
llvm::Function *m_llvmCoroDestroyFunction = nullptr;
5867
DestroyCoroFuncType m_coroDestroyFunction = nullptr;
59-
bool m_jitInitialized = false;
6068
};
6169

6270
} // namespace libscratchcpp

src/engine/internal/llvm/llvmcoroutine.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -105,32 +105,32 @@ void LLVMCoroutine::createSuspend()
105105
m_builder->SetInsertPoint(resumeBranch);
106106
}
107107

108-
llvm::Value *LLVMCoroutine::createResume(llvm::Function *function, llvm::Value *coroHandle)
108+
llvm::Value *LLVMCoroutine::createResume(llvm::Module *module, llvm::IRBuilder<> *builder, llvm::Function *function, llvm::Value *coroHandle)
109109
{
110-
llvm::LLVMContext &ctx = m_builder->getContext();
111-
llvm::Function *coroDone = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::coro_done);
110+
llvm::LLVMContext &ctx = builder->getContext();
111+
llvm::Function *coroDone = llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::coro_done);
112112

113-
llvm::Value *ret = m_builder->CreateAlloca(m_builder->getInt1Ty());
114-
llvm::Value *done = m_builder->CreateCall(coroDone, { coroHandle });
115-
done = m_builder->CreateCall(coroDone, { coroHandle });
113+
llvm::Value *ret = builder->CreateAlloca(builder->getInt1Ty());
114+
llvm::Value *done = builder->CreateCall(coroDone, { coroHandle });
115+
done = builder->CreateCall(coroDone, { coroHandle });
116116

117117
llvm::BasicBlock *destroyBranch = llvm::BasicBlock::Create(ctx, "", function);
118118
llvm::BasicBlock *resumeBranch = llvm::BasicBlock::Create(ctx, "", function);
119119
llvm::BasicBlock *nextBranch = llvm::BasicBlock::Create(ctx, "", function);
120-
m_builder->CreateCondBr(done, destroyBranch, resumeBranch);
120+
builder->CreateCondBr(done, destroyBranch, resumeBranch);
121121

122-
m_builder->SetInsertPoint(destroyBranch);
123-
m_builder->CreateCall(llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::coro_destroy), { coroHandle });
124-
m_builder->CreateBr(nextBranch);
122+
builder->SetInsertPoint(destroyBranch);
123+
builder->CreateCall(llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::coro_destroy), { coroHandle });
124+
builder->CreateBr(nextBranch);
125125

126-
m_builder->SetInsertPoint(resumeBranch);
127-
m_builder->CreateCall(llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::coro_resume), { coroHandle });
128-
done = m_builder->CreateCall(coroDone, { coroHandle });
129-
m_builder->CreateStore(done, ret);
130-
m_builder->CreateCondBr(done, destroyBranch, nextBranch);
126+
builder->SetInsertPoint(resumeBranch);
127+
builder->CreateCall(llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::coro_resume), { coroHandle });
128+
done = builder->CreateCall(coroDone, { coroHandle });
129+
builder->CreateStore(done, ret);
130+
builder->CreateCondBr(done, destroyBranch, nextBranch);
131131

132-
m_builder->SetInsertPoint(nextBranch);
133-
return m_builder->CreateLoad(m_builder->getInt1Ty(), ret);
132+
builder->SetInsertPoint(nextBranch);
133+
return builder->CreateLoad(builder->getInt1Ty(), ret);
134134
}
135135

136136
void LLVMCoroutine::end()

src/engine/internal/llvm/llvmcoroutine.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class LLVMCoroutine
2222
llvm::Value *didSuspendVar() const;
2323

2424
void createSuspend();
25-
llvm::Value *createResume(llvm::Function *function, llvm::Value *coroHandle);
25+
static llvm::Value *createResume(llvm::Module *module, llvm::IRBuilder<> *builder, llvm::Function *function, llvm::Value *coroHandle);
2626
void end();
2727

2828
private:

0 commit comments

Comments
 (0)