Skip to content

Commit a33681e

Browse files
authored
Merge pull request #594 from scratchcpp/llvm_yield
LLVM: Implement yielding
2 parents 4c1db3f + 2b031c7 commit a33681e

16 files changed

+454
-187
lines changed

src/dev/engine/compiler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ std::shared_ptr<libscratchcpp::Block> Compiler::block() const
3838
/*! Compiles the script starting with the given block. */
3939
std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBlock)
4040
{
41-
impl->builder = impl->builderFactory->create(startBlock->id());
41+
impl->builder = impl->builderFactory->create(startBlock->id(), false);
4242
impl->substackTree.clear();
4343
impl->substackHit = false;
4444
impl->warp = false;

src/dev/engine/internal/codebuilderfactory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ std::shared_ptr<CodeBuilderFactory> CodeBuilderFactory::instance()
1212
return m_instance;
1313
}
1414

15-
std::shared_ptr<ICodeBuilder> CodeBuilderFactory::create(const std::string &id) const
15+
std::shared_ptr<ICodeBuilder> CodeBuilderFactory::create(const std::string &id, bool warp) const
1616
{
17-
return std::make_shared<LLVMCodeBuilder>(id);
17+
return std::make_shared<LLVMCodeBuilder>(id, warp);
1818
}

src/dev/engine/internal/codebuilderfactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class CodeBuilderFactory : public ICodeBuilderFactory
1111
{
1212
public:
1313
static std::shared_ptr<CodeBuilderFactory> instance();
14-
std::shared_ptr<ICodeBuilder> create(const std::string &id) const override;
14+
std::shared_ptr<ICodeBuilder> create(const std::string &id, bool warp) const override;
1515

1616
private:
1717
static std::shared_ptr<CodeBuilderFactory> m_instance;

src/dev/engine/internal/icodebuilderfactory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class ICodeBuilderFactory
1414
public:
1515
virtual ~ICodeBuilderFactory() { }
1616

17-
virtual std::shared_ptr<ICodeBuilder> create(const std::string &id) const = 0;
17+
virtual std::shared_ptr<ICodeBuilder> create(const std::string &id, bool warp) const = 0;
1818
};
1919

2020
} // namespace libscratchcpp

src/dev/engine/internal/llvmcodebuilder.cpp

Lines changed: 167 additions & 43 deletions
Large diffs are not rendered by default.

src/dev/engine/internal/llvmcodebuilder.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Target;
1717
class LLVMCodeBuilder : public ICodeBuilder
1818
{
1919
public:
20-
LLVMCodeBuilder(const std::string &id);
20+
LLVMCodeBuilder(const std::string &id, bool warp);
2121

2222
std::shared_ptr<ExecutableCode> finalize() override;
2323

@@ -98,9 +98,24 @@ class LLVMCodeBuilder : public ICodeBuilder
9898
llvm::BasicBlock *afterLoop = nullptr;
9999
};
100100

101+
struct Coroutine
102+
{
103+
llvm::Value *handle = nullptr;
104+
llvm::BasicBlock *suspend = nullptr;
105+
llvm::BasicBlock *cleanup = nullptr;
106+
};
107+
108+
struct Procedure
109+
{
110+
// TODO: Implement procedures
111+
bool warp = false;
112+
};
113+
101114
void initTypes();
102-
llvm::Function *beginFunction(size_t index);
103-
void endFunction(llvm::Function *func, size_t index);
115+
116+
Coroutine initCoroutine(llvm::Function *func);
117+
void verifyFunction(llvm::Function *func);
118+
void optimize();
104119

105120
void freeHeap();
106121
llvm::Value *castValue(std::shared_ptr<Register> reg, Compiler::StaticType targetType);
@@ -136,6 +151,8 @@ class LLVMCodeBuilder : public ICodeBuilder
136151
std::vector<Value> m_constValues;
137152
std::vector<std::vector<std::shared_ptr<Register>>> m_regs;
138153
std::vector<std::shared_ptr<Register>> m_tmpRegs;
154+
bool m_defaultWarp = false;
155+
bool m_warp = false;
139156

140157
std::vector<llvm::Value *> m_heap;
141158

src/dev/engine/internal/llvmexecutablecode.cpp

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,44 +31,53 @@ LLVMExecutableCode::LLVMExecutableCode(std::unique_ptr<llvm::Module> module) :
3131
}
3232

3333
// Lookup functions
34-
size_t i = 0;
35-
36-
while (true) {
37-
auto func = m_jit->get()->lookup("f" + std::to_string(i));
38-
39-
if (func)
40-
m_functions.push_back((FunctionType)(func->getValue()));
41-
else {
42-
// Ignore error
43-
llvm::consumeError(func.takeError());
44-
break;
45-
}
46-
47-
i++;
48-
}
34+
m_mainFunction = (MainFunctionType)lookupFunction("f");
35+
assert(m_mainFunction);
36+
m_resumeFunction = (ResumeFunctionType)lookupFunction("resume");
37+
assert(m_resumeFunction);
4938
}
5039

5140
void LLVMExecutableCode::run(ExecutionContext *context)
5241
{
5342
LLVMExecutionContext *ctx = getContext(context);
5443

55-
if (ctx->pos() < m_functions.size())
56-
ctx->setPos(m_functions[ctx->pos()](context->target()));
44+
if (ctx->finished())
45+
return;
46+
47+
if (ctx->coroutineHandle()) {
48+
bool done = m_resumeFunction(ctx->coroutineHandle());
49+
50+
if (done)
51+
ctx->setCoroutineHandle(nullptr);
52+
53+
ctx->setFinished(done);
54+
} else {
55+
void *handle = m_mainFunction(context->target());
56+
57+
if (!handle)
58+
ctx->setFinished(true);
59+
60+
ctx->setCoroutineHandle(handle);
61+
}
5762
}
5863

5964
void LLVMExecutableCode::kill(ExecutionContext *context)
6065
{
61-
getContext(context)->setPos(m_functions.size());
66+
LLVMExecutionContext *ctx = getContext(context);
67+
ctx->setCoroutineHandle(nullptr);
68+
ctx->setFinished(true);
6269
}
6370

6471
void LLVMExecutableCode::reset(ExecutionContext *context)
6572
{
66-
getContext(context)->setPos(0);
73+
LLVMExecutionContext *ctx = getContext(context);
74+
ctx->setCoroutineHandle(nullptr);
75+
ctx->setFinished(false);
6776
}
6877

6978
bool LLVMExecutableCode::isFinished(ExecutionContext *context) const
7079
{
71-
return getContext(context)->pos() >= m_functions.size();
80+
return getContext(context)->finished();
7281
}
7382

7483
void LLVMExecutableCode::promise()
@@ -84,6 +93,18 @@ std::shared_ptr<ExecutionContext> LLVMExecutableCode::createExecutionContext(Tar
8493
return std::make_shared<LLVMExecutionContext>(target);
8594
}
8695

96+
uint64_t LLVMExecutableCode::lookupFunction(const std::string &name)
97+
{
98+
auto func = m_jit->get()->lookup(name);
99+
100+
if (func)
101+
return func->getValue();
102+
else {
103+
llvm::errs() << "error: failed to lookup LLVM function: " << toString(func.takeError()) << "\n";
104+
return 0;
105+
}
106+
}
107+
87108
LLVMExecutionContext *LLVMExecutableCode::getContext(ExecutionContext *context)
88109
{
89110
assert(dynamic_cast<LLVMExecutionContext *>(context));

src/dev/engine/internal/llvmexecutablecode.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ class LLVMExecutableCode : public ExecutableCode
3030
std::shared_ptr<ExecutionContext> createExecutionContext(Target *target) const override;
3131

3232
private:
33-
using FunctionType = size_t (*)(Target *);
33+
uint64_t lookupFunction(const std::string &name);
34+
35+
using MainFunctionType = void *(*)(Target *);
36+
using ResumeFunctionType = bool (*)(void *);
3437

3538
static LLVMExecutionContext *getContext(ExecutionContext *context);
3639

3740
std::unique_ptr<llvm::LLVMContext> m_ctx;
3841
llvm::Expected<std::unique_ptr<llvm::orc::LLJIT>> m_jit;
3942

40-
std::vector<FunctionType> m_functions;
43+
MainFunctionType m_mainFunction;
44+
ResumeFunctionType m_resumeFunction;
4145
};
4246

4347
} // namespace libscratchcpp

src/dev/engine/internal/llvmexecutioncontext.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,22 @@ LLVMExecutionContext::LLVMExecutionContext(Target *target) :
99
{
1010
}
1111

12-
size_t LLVMExecutionContext::pos() const
12+
void *LLVMExecutionContext::coroutineHandle() const
1313
{
14-
return m_pos;
14+
return m_coroutineHandle;
1515
}
1616

17-
void LLVMExecutionContext::setPos(size_t newPos)
17+
void LLVMExecutionContext::setCoroutineHandle(void *newCoroutineHandle)
1818
{
19-
m_pos = newPos;
19+
m_coroutineHandle = newCoroutineHandle;
20+
}
21+
22+
bool LLVMExecutionContext::finished() const
23+
{
24+
return m_finished;
25+
}
26+
27+
void LLVMExecutionContext::setFinished(bool newFinished)
28+
{
29+
m_finished = newFinished;
2030
}

src/dev/engine/internal/llvmexecutioncontext.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ class LLVMExecutionContext : public ExecutionContext
1212
public:
1313
LLVMExecutionContext(Target *target);
1414

15-
size_t pos() const;
16-
void setPos(size_t newPos);
15+
void *coroutineHandle() const;
16+
void setCoroutineHandle(void *newCoroutineHandle);
17+
18+
bool finished() const;
19+
void setFinished(bool newFinished);
1720

1821
private:
19-
size_t m_pos = 0;
22+
void *m_coroutineHandle = nullptr;
23+
bool m_finished = false;
2024
};
2125

2226
} // namespace libscratchcpp

0 commit comments

Comments
 (0)