Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dev/engine/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ std::shared_ptr<libscratchcpp::Block> Compiler::block() const
/*! Compiles the script starting with the given block. */
std::shared_ptr<ExecutableCode> Compiler::compile(std::shared_ptr<Block> startBlock)
{
impl->builder = impl->builderFactory->create(startBlock->id());
impl->builder = impl->builderFactory->create(startBlock->id(), false);
impl->substackTree.clear();
impl->substackHit = false;
impl->warp = false;
Expand Down
4 changes: 2 additions & 2 deletions src/dev/engine/internal/codebuilderfactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ std::shared_ptr<CodeBuilderFactory> CodeBuilderFactory::instance()
return m_instance;
}

std::shared_ptr<ICodeBuilder> CodeBuilderFactory::create(const std::string &id) const
std::shared_ptr<ICodeBuilder> CodeBuilderFactory::create(const std::string &id, bool warp) const
{
return std::make_shared<LLVMCodeBuilder>(id);
return std::make_shared<LLVMCodeBuilder>(id, warp);
}
2 changes: 1 addition & 1 deletion src/dev/engine/internal/codebuilderfactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CodeBuilderFactory : public ICodeBuilderFactory
{
public:
static std::shared_ptr<CodeBuilderFactory> instance();
std::shared_ptr<ICodeBuilder> create(const std::string &id) const override;
std::shared_ptr<ICodeBuilder> create(const std::string &id, bool warp) const override;

private:
static std::shared_ptr<CodeBuilderFactory> m_instance;
Expand Down
2 changes: 1 addition & 1 deletion src/dev/engine/internal/icodebuilderfactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ICodeBuilderFactory
public:
virtual ~ICodeBuilderFactory() { }

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

} // namespace libscratchcpp
210 changes: 167 additions & 43 deletions src/dev/engine/internal/llvmcodebuilder.cpp

Large diffs are not rendered by default.

23 changes: 20 additions & 3 deletions src/dev/engine/internal/llvmcodebuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Target;
class LLVMCodeBuilder : public ICodeBuilder
{
public:
LLVMCodeBuilder(const std::string &id);
LLVMCodeBuilder(const std::string &id, bool warp);

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

Expand Down Expand Up @@ -98,9 +98,24 @@ class LLVMCodeBuilder : public ICodeBuilder
llvm::BasicBlock *afterLoop = nullptr;
};

struct Coroutine
{
llvm::Value *handle = nullptr;
llvm::BasicBlock *suspend = nullptr;
llvm::BasicBlock *cleanup = nullptr;
};

struct Procedure
{
// TODO: Implement procedures
bool warp = false;
};

void initTypes();
llvm::Function *beginFunction(size_t index);
void endFunction(llvm::Function *func, size_t index);

Coroutine initCoroutine(llvm::Function *func);
void verifyFunction(llvm::Function *func);
void optimize();

void freeHeap();
llvm::Value *castValue(std::shared_ptr<Register> reg, Compiler::StaticType targetType);
Expand Down Expand Up @@ -136,6 +151,8 @@ class LLVMCodeBuilder : public ICodeBuilder
std::vector<Value> m_constValues;
std::vector<std::vector<std::shared_ptr<Register>>> m_regs;
std::vector<std::shared_ptr<Register>> m_tmpRegs;
bool m_defaultWarp = false;
bool m_warp = false;

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

Expand Down
61 changes: 41 additions & 20 deletions src/dev/engine/internal/llvmexecutablecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,53 @@ LLVMExecutableCode::LLVMExecutableCode(std::unique_ptr<llvm::Module> module) :
}

// Lookup functions
size_t i = 0;

while (true) {
auto func = m_jit->get()->lookup("f" + std::to_string(i));

if (func)
m_functions.push_back((FunctionType)(func->getValue()));
else {
// Ignore error
llvm::consumeError(func.takeError());
break;
}

i++;
}
m_mainFunction = (MainFunctionType)lookupFunction("f");
assert(m_mainFunction);
m_resumeFunction = (ResumeFunctionType)lookupFunction("resume");
assert(m_resumeFunction);
}

void LLVMExecutableCode::run(ExecutionContext *context)
{
LLVMExecutionContext *ctx = getContext(context);

if (ctx->pos() < m_functions.size())
ctx->setPos(m_functions[ctx->pos()](context->target()));
if (ctx->finished())
return;

if (ctx->coroutineHandle()) {
bool done = m_resumeFunction(ctx->coroutineHandle());

if (done)
ctx->setCoroutineHandle(nullptr);

ctx->setFinished(done);
} else {
void *handle = m_mainFunction(context->target());

if (!handle)
ctx->setFinished(true);

ctx->setCoroutineHandle(handle);
}
}

void LLVMExecutableCode::kill(ExecutionContext *context)
{
getContext(context)->setPos(m_functions.size());
LLVMExecutionContext *ctx = getContext(context);
ctx->setCoroutineHandle(nullptr);
ctx->setFinished(true);
}

void LLVMExecutableCode::reset(ExecutionContext *context)
{
getContext(context)->setPos(0);
LLVMExecutionContext *ctx = getContext(context);
ctx->setCoroutineHandle(nullptr);
ctx->setFinished(false);
}

bool LLVMExecutableCode::isFinished(ExecutionContext *context) const
{
return getContext(context)->pos() >= m_functions.size();
return getContext(context)->finished();
}

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

uint64_t LLVMExecutableCode::lookupFunction(const std::string &name)
{
auto func = m_jit->get()->lookup(name);

if (func)
return func->getValue();
else {
llvm::errs() << "error: failed to lookup LLVM function: " << toString(func.takeError()) << "\n";
return 0;
}
}

LLVMExecutionContext *LLVMExecutableCode::getContext(ExecutionContext *context)
{
assert(dynamic_cast<LLVMExecutionContext *>(context));
Expand Down
8 changes: 6 additions & 2 deletions src/dev/engine/internal/llvmexecutablecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,18 @@ class LLVMExecutableCode : public ExecutableCode
std::shared_ptr<ExecutionContext> createExecutionContext(Target *target) const override;

private:
using FunctionType = size_t (*)(Target *);
uint64_t lookupFunction(const std::string &name);

using MainFunctionType = void *(*)(Target *);
using ResumeFunctionType = bool (*)(void *);

static LLVMExecutionContext *getContext(ExecutionContext *context);

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

std::vector<FunctionType> m_functions;
MainFunctionType m_mainFunction;
ResumeFunctionType m_resumeFunction;
};

} // namespace libscratchcpp
18 changes: 14 additions & 4 deletions src/dev/engine/internal/llvmexecutioncontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,22 @@ LLVMExecutionContext::LLVMExecutionContext(Target *target) :
{
}

size_t LLVMExecutionContext::pos() const
void *LLVMExecutionContext::coroutineHandle() const
{
return m_pos;
return m_coroutineHandle;
}

void LLVMExecutionContext::setPos(size_t newPos)
void LLVMExecutionContext::setCoroutineHandle(void *newCoroutineHandle)
{
m_pos = newPos;
m_coroutineHandle = newCoroutineHandle;
}

bool LLVMExecutionContext::finished() const
{
return m_finished;
}

void LLVMExecutionContext::setFinished(bool newFinished)
{
m_finished = newFinished;
}
10 changes: 7 additions & 3 deletions src/dev/engine/internal/llvmexecutioncontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ class LLVMExecutionContext : public ExecutionContext
public:
LLVMExecutionContext(Target *target);

size_t pos() const;
void setPos(size_t newPos);
void *coroutineHandle() const;
void setCoroutineHandle(void *newCoroutineHandle);

bool finished() const;
void setFinished(bool newFinished);

private:
size_t m_pos = 0;
void *m_coroutineHandle = nullptr;
bool m_finished = false;
};

} // namespace libscratchcpp
2 changes: 1 addition & 1 deletion test/dev/compiler/compiler_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class CompilerTest : public testing::Test
{
ASSERT_EQ(compiler.block(), nullptr);
// TODO: Test warp
EXPECT_CALL(m_builderFactory, create(block->id())).WillOnce(Return(m_builder));
EXPECT_CALL(m_builderFactory, create(block->id(), false)).WillOnce(Return(m_builder));
EXPECT_CALL(*m_builder, finalize()).WillOnce(Return(m_code));
ASSERT_EQ(compiler.compile(block), m_code);
ASSERT_EQ(compiler.block(), nullptr);
Expand Down
Loading
Loading