From 9567a0418fc348c675c467e7de6a55d35934b3be Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Mon, 30 Dec 2024 14:50:43 +0100 Subject: [PATCH] Refactor compiler to use shared context for each target --- include/scratchcpp/dev/compiler.h | 4 + src/dev/engine/compiler.cpp | 22 +- src/dev/engine/compiler_p.cpp | 17 +- src/dev/engine/compiler_p.h | 8 +- .../engine/internal/codebuilderfactory.cpp | 12 +- src/dev/engine/internal/codebuilderfactory.h | 3 +- src/dev/engine/internal/icodebuilderfactory.h | 5 +- src/dev/engine/internal/llvm/CMakeLists.txt | 2 + .../engine/internal/llvm/llvmcodebuilder.cpp | 251 +++++++++-------- .../engine/internal/llvm/llvmcodebuilder.h | 10 +- .../internal/llvm/llvmcompilercontext.cpp | 65 +++++ .../internal/llvm/llvmcompilercontext.h | 53 ++++ .../engine/internal/llvm/llvmcoroutine.cpp | 4 +- .../internal/llvm/llvmexecutablecode.cpp | 53 ++-- .../engine/internal/llvm/llvmexecutablecode.h | 19 +- src/engine/internal/engine.cpp | 8 +- src/engine/internal/engine.h | 6 + test/dev/compiler/compiler_test.cpp | 262 +++++++++--------- test/dev/llvm/llvmcodebuilder_test.cpp | 111 ++++---- test/dev/llvm/llvmexecutablecode_test.cpp | 61 ++-- test/mocks/codebuilderfactorymock.h | 3 +- test/scratch_classes/inputvalue_test.cpp | 2 +- 22 files changed, 568 insertions(+), 413 deletions(-) create mode 100644 src/dev/engine/internal/llvm/llvmcompilercontext.cpp create mode 100644 src/dev/engine/internal/llvm/llvmcompilercontext.h diff --git a/include/scratchcpp/dev/compiler.h b/include/scratchcpp/dev/compiler.h index 4486099e..0ac77bbc 100644 --- a/include/scratchcpp/dev/compiler.h +++ b/include/scratchcpp/dev/compiler.h @@ -11,6 +11,7 @@ namespace libscratchcpp { +class CompilerContext; class IEngine; class Target; class ExecutableCode; @@ -39,6 +40,7 @@ class LIBSCRATCHCPP_EXPORT Compiler using ArgTypes = std::vector; using Args = std::vector; + Compiler(CompilerContext *ctx); Compiler(IEngine *engine, Target *target); Compiler(const Compiler &) = delete; @@ -132,6 +134,8 @@ class LIBSCRATCHCPP_EXPORT Compiler const std::unordered_set &unsupportedBlocks() const; + static std::shared_ptr createContext(IEngine *engine, Target *target); + private: CompilerValue *addInput(Input *input); diff --git a/src/dev/engine/compiler.cpp b/src/dev/engine/compiler.cpp index bcbc8a35..b8e0ff82 100644 --- a/src/dev/engine/compiler.cpp +++ b/src/dev/engine/compiler.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include +#include #include #include #include @@ -12,7 +13,13 @@ using namespace libscratchcpp; -/*! Constructs Compiler. */ +/*! Constructs Compiler using the given context. */ +Compiler::Compiler(CompilerContext *ctx) : + impl(spimpl::make_unique_impl(ctx)) +{ +} + +/*! Constructs Compiler using a new context for the given target. */ Compiler::Compiler(IEngine *engine, Target *target) : impl(spimpl::make_unique_impl(engine, target)) { @@ -21,13 +28,13 @@ Compiler::Compiler(IEngine *engine, Target *target) : /*! Returns the Engine of the project. */ IEngine *Compiler::engine() const { - return impl->engine; + return impl->ctx->engine(); } /*! Returns the Target of this compiler. */ Target *Compiler::target() const { - return impl->target; + return impl->ctx->target(); } /*! Returns currently compiled block. */ @@ -39,7 +46,7 @@ std::shared_ptr Compiler::block() const /*! Compiles the script starting with the given block. */ std::shared_ptr Compiler::compile(std::shared_ptr startBlock) { - impl->builder = impl->builderFactory->create(impl->target, startBlock->id(), false); + impl->builder = impl->builderFactory->create(impl->ctx, false); impl->substackTree.clear(); impl->substackHit = false; impl->emptySubstack = false; @@ -570,6 +577,13 @@ const std::unordered_set &Compiler::unsupportedBlocks() const return impl->unsupportedBlocks; } +/*! Creates a compiler context for the given target. */ +std::shared_ptr Compiler::createContext(IEngine *engine, Target *target) +{ + CompilerPrivate::initBuilderFactory(); + return CompilerPrivate::builderFactory->createCtx(engine, target); +} + CompilerValue *Compiler::addInput(Input *input) { if (!input) diff --git a/src/dev/engine/compiler_p.cpp b/src/dev/engine/compiler_p.cpp index cff14fe9..963c0d3e 100644 --- a/src/dev/engine/compiler_p.cpp +++ b/src/dev/engine/compiler_p.cpp @@ -1,5 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 +#include #include #include "compiler_p.h" @@ -9,9 +10,21 @@ using namespace libscratchcpp; +CompilerPrivate::CompilerPrivate(CompilerContext *ctx) : + ctx(ctx) +{ + assert(ctx); + initBuilderFactory(); +} + CompilerPrivate::CompilerPrivate(IEngine *engine, Target *target) : - engine(engine), - target(target) + ctxPtr(Compiler::createContext(engine, target)), + ctx(ctxPtr.get()) +{ + initBuilderFactory(); +} + +void CompilerPrivate::initBuilderFactory() { if (!builderFactory) builderFactory = CodeBuilderFactory::instance().get(); diff --git a/src/dev/engine/compiler_p.h b/src/dev/engine/compiler_p.h index add1021c..593accbf 100644 --- a/src/dev/engine/compiler_p.h +++ b/src/dev/engine/compiler_p.h @@ -9,6 +9,7 @@ namespace libscratchcpp { +class CompilerContext; class IEngine; class Target; class Block; @@ -24,12 +25,15 @@ struct CompilerPrivate IfStatement }; + CompilerPrivate(CompilerContext *ctx); CompilerPrivate(IEngine *engine, Target *target); + static void initBuilderFactory(); + void substackEnd(); - IEngine *engine = nullptr; - Target *target = nullptr; + std::shared_ptr ctxPtr; // for self-managed contexts + CompilerContext *ctx = nullptr; std::shared_ptr block; int customIfStatementCount = 0; diff --git a/src/dev/engine/internal/codebuilderfactory.cpp b/src/dev/engine/internal/codebuilderfactory.cpp index 999a740a..1623c67b 100644 --- a/src/dev/engine/internal/codebuilderfactory.cpp +++ b/src/dev/engine/internal/codebuilderfactory.cpp @@ -2,6 +2,7 @@ #include "codebuilderfactory.h" #include "llvm/llvmcodebuilder.h" +#include "llvm/llvmcompilercontext.h" using namespace libscratchcpp; @@ -12,7 +13,14 @@ std::shared_ptr CodeBuilderFactory::instance() return m_instance; } -std::shared_ptr CodeBuilderFactory::create(Target *target, const std::string &id, bool warp) const +std::shared_ptr CodeBuilderFactory::create(CompilerContext *ctx, bool warp) const { - return std::make_shared(target, id, warp); + assert(dynamic_cast(ctx)); + return std::make_shared(static_cast(ctx), warp); +} + +std::shared_ptr CodeBuilderFactory::createCtx(IEngine *engine, Target *target) const +{ + auto ptr = std::make_shared(engine, target); + return ptr; } diff --git a/src/dev/engine/internal/codebuilderfactory.h b/src/dev/engine/internal/codebuilderfactory.h index 9a498717..e8eea9c9 100644 --- a/src/dev/engine/internal/codebuilderfactory.h +++ b/src/dev/engine/internal/codebuilderfactory.h @@ -11,7 +11,8 @@ class CodeBuilderFactory : public ICodeBuilderFactory { public: static std::shared_ptr instance(); - std::shared_ptr create(Target *target, const std::string &id, bool warp) const override; + std::shared_ptr create(CompilerContext *ctx, bool warp) const override; + std::shared_ptr createCtx(IEngine *engine, Target *target) const override; private: static std::shared_ptr m_instance; diff --git a/src/dev/engine/internal/icodebuilderfactory.h b/src/dev/engine/internal/icodebuilderfactory.h index 07265463..75b485c2 100644 --- a/src/dev/engine/internal/icodebuilderfactory.h +++ b/src/dev/engine/internal/icodebuilderfactory.h @@ -8,14 +8,17 @@ namespace libscratchcpp { class ICodeBuilder; +class CompilerContext; class Target; +class IEngine; class ICodeBuilderFactory { public: virtual ~ICodeBuilderFactory() { } - virtual std::shared_ptr create(Target *target, const std::string &id, bool warp) const = 0; + virtual std::shared_ptr create(CompilerContext *ctx, bool warp) const = 0; + virtual std::shared_ptr createCtx(IEngine *engine, Target *target) const = 0; }; } // namespace libscratchcpp diff --git a/src/dev/engine/internal/llvm/CMakeLists.txt b/src/dev/engine/internal/llvm/CMakeLists.txt index 315be55a..e1bb3ef5 100644 --- a/src/dev/engine/internal/llvm/CMakeLists.txt +++ b/src/dev/engine/internal/llvm/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(scratchcpp llvmtypes.cpp llvmtypes.h llvmfunctions.cpp + llvmcompilercontext.cpp + llvmcompilercontext.h llvmexecutablecode.cpp llvmexecutablecode.h llvmexecutioncontext.cpp diff --git a/src/dev/engine/internal/llvm/llvmcodebuilder.cpp b/src/dev/engine/internal/llvm/llvmcodebuilder.cpp index 98d4190b..a4e2eec4 100644 --- a/src/dev/engine/internal/llvm/llvmcodebuilder.cpp +++ b/src/dev/engine/internal/llvm/llvmcodebuilder.cpp @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -#include #include #include #include @@ -13,6 +12,7 @@ #include #include "llvmcodebuilder.h" +#include "llvmcompilercontext.h" #include "llvmexecutablecode.h" #include "llvmconstantregister.h" #include "llvmifstatement.h" @@ -24,18 +24,15 @@ using namespace libscratchcpp; static std::unordered_map TYPE_MAP = { { ValueType::Number, Compiler::StaticType::Number }, { ValueType::Bool, Compiler::StaticType::Bool }, { ValueType::String, Compiler::StaticType::String } }; -LLVMCodeBuilder::LLVMCodeBuilder(Target *target, const std::string &id, bool warp) : - m_target(target), - m_id(id), - m_module(std::make_unique(id, m_ctx)), - m_builder(m_ctx), +LLVMCodeBuilder::LLVMCodeBuilder(LLVMCompilerContext *ctx, bool warp) : + m_ctx(ctx), + m_target(ctx->target()), + m_llvmCtx(*ctx->llvmCtx()), + m_module(ctx->module()), + m_builder(m_llvmCtx), m_defaultWarp(warp), m_warp(warp) { - llvm::InitializeNativeTarget(); - llvm::InitializeNativeTargetAsmPrinter(); - llvm::InitializeNativeTargetAsmParser(); - initTypes(); createVariableMap(); createListMap(); @@ -61,23 +58,23 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Create function // void *f(ExecutionContext *, Target *, ValueData **, List **) - llvm::PointerType *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::PointerType *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); llvm::FunctionType *funcType = llvm::FunctionType::get(pointerType, { pointerType, pointerType, pointerType, pointerType }, false); - llvm::Function *func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "f", m_module.get()); + llvm::Function *func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "f", m_module); llvm::Value *executionContextPtr = func->getArg(0); llvm::Value *targetPtr = func->getArg(1); llvm::Value *targetVariables = func->getArg(2); llvm::Value *targetLists = func->getArg(3); - llvm::BasicBlock *entry = llvm::BasicBlock::Create(m_ctx, "entry", func); - llvm::BasicBlock *endBranch = llvm::BasicBlock::Create(m_ctx, "end", func); + llvm::BasicBlock *entry = llvm::BasicBlock::Create(m_llvmCtx, "entry", func); + llvm::BasicBlock *endBranch = llvm::BasicBlock::Create(m_llvmCtx, "end", func); m_builder.SetInsertPoint(entry); // Init coroutine std::unique_ptr coro; if (!m_warp) - coro = std::make_unique(m_module.get(), &m_builder, func); + coro = std::make_unique(m_module, &m_builder, func); std::vector ifStatements; std::vector loops; @@ -123,13 +120,13 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Add execution context arg if (step.functionCtxArg) { - types.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0)); + types.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0)); args.push_back(executionContextPtr); } // Add target pointer arg if (step.functionTargetArg) { - types.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0)); + types.push_back(llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0)); args.push_back(targetPtr); } @@ -291,7 +288,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() const auto &arg1 = step.args[0]; const auto &arg2 = step.args[1]; // rem(a, b) / b < 0.0 ? rem(a, b) + b : rem(a, b) - llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); + llvm::Constant *zero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)); llvm::Value *num1 = removeNaN(castValue(arg1.second, arg1.first)); llvm::Value *num2 = removeNaN(castValue(arg2.second, arg2.first)); llvm::Value *value = m_builder.CreateFRem(num1, num2); // rem(a, b) @@ -304,15 +301,15 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // x >= 0.0 ? round(x) : (x >= -0.5 ? -0.0 : floor(x + 0.5)) - llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); - llvm::Constant *negativeZero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-0.0)); - llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); - llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::floor, m_builder.getDoubleTy()); + llvm::Constant *zero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)); + llvm::Constant *negativeZero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(-0.0)); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::floor, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); - llvm::Value *notNegative = m_builder.CreateFCmpOGE(num, zero); // num >= 0.0 - llvm::Value *roundNum = m_builder.CreateCall(roundFunc, num); // round(num) - llvm::Value *negativeCond = m_builder.CreateFCmpOGE(num, llvm::ConstantFP::get(m_ctx, llvm::APFloat(-0.5))); // num >= -0.5 - llvm::Value *negativeRound = m_builder.CreateCall(floorFunc, m_builder.CreateFAdd(num, llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.5)))); // floor(x + 0.5) + llvm::Value *notNegative = m_builder.CreateFCmpOGE(num, zero); // num >= 0.0 + llvm::Value *roundNum = m_builder.CreateCall(roundFunc, num); // round(num) + llvm::Value *negativeCond = m_builder.CreateFCmpOGE(num, llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(-0.5))); // num >= -0.5 + llvm::Value *negativeRound = m_builder.CreateCall(floorFunc, m_builder.CreateFAdd(num, llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.5)))); // floor(x + 0.5) step.functionReturnReg->value = m_builder.CreateSelect(notNegative, roundNum, m_builder.CreateSelect(negativeCond, negativeZero, negativeRound)); break; } @@ -320,7 +317,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() case LLVMInstruction::Type::Abs: { assert(step.args.size() == 1); const auto &arg = step.args[0]; - llvm::Function *absFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::fabs, m_builder.getDoubleTy()); + llvm::Function *absFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::fabs, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(absFunc, num); break; @@ -329,7 +326,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() case LLVMInstruction::Type::Floor: { assert(step.args.size() == 1); const auto &arg = step.args[0]; - llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::floor, m_builder.getDoubleTy()); + llvm::Function *floorFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::floor, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(floorFunc, num); break; @@ -338,7 +335,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() case LLVMInstruction::Type::Ceil: { assert(step.args.size() == 1); const auto &arg = step.args[0]; - llvm::Function *ceilFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::ceil, m_builder.getDoubleTy()); + llvm::Function *ceilFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::ceil, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(ceilFunc, num); break; @@ -349,8 +346,8 @@ std::shared_ptr LLVMCodeBuilder::finalize() const auto &arg = step.args[0]; // sqrt(x) + 0.0 // This avoids negative zero - llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); - llvm::Function *sqrtFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::sqrt, m_builder.getDoubleTy()); + llvm::Constant *zero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)); + llvm::Function *sqrtFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::sqrt, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateFAdd(m_builder.CreateCall(sqrtFunc, num), zero); break; @@ -361,12 +358,12 @@ std::shared_ptr LLVMCodeBuilder::finalize() const auto &arg = step.args[0]; // round(sin(x * pi / 180.0) * 1e10) / 1e10 + 0.0 // +0.0 to avoid -0.0 - llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); - llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); - llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); - llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10)); - llvm::Function *sinFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::sin, m_builder.getDoubleTy()); - llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Constant *zero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)); + llvm::Constant *pi = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(180.0)); + llvm::Constant *factor = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(1e10)); + llvm::Function *sinFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::sin, m_builder.getDoubleTy()); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::round, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); llvm::Value *sinResult = m_builder.CreateCall(sinFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // sin(x * pi / 180) llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(sinResult, factor)); // round(sin(x * 180) * 1e10) @@ -378,11 +375,11 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // round(cos(x * pi / 180.0) * 1e10) / 1e10 - llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); - llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); - llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10)); - llvm::Function *cosFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::cos, m_builder.getDoubleTy()); - llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Constant *pi = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(180.0)); + llvm::Constant *factor = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(1e10)); + llvm::Function *cosFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::cos, m_builder.getDoubleTy()); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::round, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); llvm::Value *cosResult = m_builder.CreateCall(cosFunc, m_builder.CreateFDiv(m_builder.CreateFMul(num, pi), piDeg)); // cos(x * pi / 180) llvm::Value *rounded = m_builder.CreateCall(roundFunc, m_builder.CreateFMul(cosResult, factor)); // round(cos(x * 180) * 1e10) @@ -395,19 +392,19 @@ std::shared_ptr LLVMCodeBuilder::finalize() const auto &arg = step.args[0]; // ((mod = rem(x, 360.0)) == -270.0 || mod == 90.0) ? inf : ((mod == -90.0 || mod == 270.0) ? -inf : round(tan(x * pi / 180.0) * 1e10) / 1e10 + 0.0) // +0.0 to avoid -0.0 - llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); - llvm::Constant *full = llvm::ConstantFP::get(m_ctx, llvm::APFloat(360.0)); + llvm::Constant *zero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)); + llvm::Constant *full = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(360.0)); llvm::Constant *posInf = llvm::ConstantFP::getInfinity(m_builder.getDoubleTy(), false); llvm::Constant *negInf = llvm::ConstantFP::getInfinity(m_builder.getDoubleTy(), true); - llvm::Constant *undefined1 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-270.0)); - llvm::Constant *undefined2 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(90.0)); - llvm::Constant *undefined3 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(-90.0)); - llvm::Constant *undefined4 = llvm::ConstantFP::get(m_ctx, llvm::APFloat(270.0)); - llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); - llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); - llvm::Constant *factor = llvm::ConstantFP::get(m_ctx, llvm::APFloat(1e10)); - llvm::Function *tanFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::tan, m_builder.getDoubleTy()); - llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, m_builder.getDoubleTy()); + llvm::Constant *undefined1 = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(-270.0)); + llvm::Constant *undefined2 = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(90.0)); + llvm::Constant *undefined3 = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(-90.0)); + llvm::Constant *undefined4 = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(270.0)); + llvm::Constant *pi = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(180.0)); + llvm::Constant *factor = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(1e10)); + llvm::Function *tanFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::tan, m_builder.getDoubleTy()); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::round, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); llvm::Value *mod = m_builder.CreateFRem(num, full); llvm::Value *isUndefined1 = m_builder.CreateFCmpOEQ(mod, undefined1); // rem(x, 360.0) == -270.0 @@ -427,10 +424,10 @@ std::shared_ptr LLVMCodeBuilder::finalize() const auto &arg = step.args[0]; // asin(x) * 180.0 / pi + 0.0 // +0.0 to avoid -0.0 - llvm::Constant *zero = llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)); - llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); - llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); - llvm::Function *asinFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::asin, m_builder.getDoubleTy()); + llvm::Constant *zero = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)); + llvm::Constant *pi = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(180.0)); + llvm::Function *asinFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::asin, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateFAdd(m_builder.CreateFDiv(m_builder.CreateFMul(m_builder.CreateCall(asinFunc, num), piDeg), pi), zero); break; @@ -440,9 +437,9 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // acos(x) * 180.0 / pi - llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); - llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); - llvm::Function *acosFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::acos, m_builder.getDoubleTy()); + llvm::Constant *pi = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(180.0)); + llvm::Function *acosFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::acos, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateFDiv(m_builder.CreateFMul(m_builder.CreateCall(acosFunc, num), piDeg), pi); break; @@ -452,9 +449,9 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // atan(x) * 180.0 / pi - llvm::Constant *pi = llvm::ConstantFP::get(m_ctx, llvm::APFloat(std::acos(-1.0))); - llvm::Constant *piDeg = llvm::ConstantFP::get(m_ctx, llvm::APFloat(180.0)); - llvm::Function *atanFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::atan, m_builder.getDoubleTy()); + llvm::Constant *pi = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(std::acos(-1.0))); + llvm::Constant *piDeg = llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(180.0)); + llvm::Function *atanFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::atan, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateFDiv(m_builder.CreateFMul(m_builder.CreateCall(atanFunc, num), piDeg), pi); break; @@ -464,7 +461,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // log(x) - llvm::Function *logFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::log, m_builder.getDoubleTy()); + llvm::Function *logFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::log, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(logFunc, num); break; @@ -474,7 +471,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // log10(x) - llvm::Function *log10Func = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::log10, m_builder.getDoubleTy()); + llvm::Function *log10Func = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::log10, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(log10Func, num); break; @@ -484,7 +481,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // exp(x) - llvm::Function *expFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::exp, m_builder.getDoubleTy()); + llvm::Function *expFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::exp, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(expFunc, num); break; @@ -494,7 +491,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() assert(step.args.size() == 1); const auto &arg = step.args[0]; // exp10(x) - llvm::Function *expFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::exp10, m_builder.getDoubleTy()); + llvm::Function *expFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::exp10, m_builder.getDoubleTy()); llvm::Value *num = removeNaN(castValue(arg.second, arg.first)); step.functionReturnReg->value = m_builder.CreateCall(expFunc, num); break; @@ -658,9 +655,9 @@ std::shared_ptr LLVMCodeBuilder::finalize() llvm::Value *allocatedSize = m_builder.CreateLoad(m_builder.getInt64Ty(), listPtr.allocatedSizePtr); llvm::Value *size = m_builder.CreateLoad(m_builder.getInt64Ty(), listPtr.sizePtr); llvm::Value *isAllocated = m_builder.CreateICmpUGT(allocatedSize, size); - llvm::BasicBlock *ifBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *elseBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *nextBlock = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *ifBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *elseBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *nextBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); m_builder.CreateCondBr(isAllocated, ifBlock, elseBlock); // If there's enough space, use the allocated memory @@ -804,7 +801,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() case LLVMInstruction::Type::BeginIf: { LLVMIfStatement statement; statement.beforeIf = m_builder.GetInsertBlock(); - statement.body = llvm::BasicBlock::Create(m_ctx, "", func); + statement.body = llvm::BasicBlock::Create(m_llvmCtx, "", func); // Use last reg assert(step.args.size() == 1); @@ -835,13 +832,13 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Jump to the branch after the if statement assert(!statement.afterIf); - statement.afterIf = llvm::BasicBlock::Create(m_ctx, "", func); + statement.afterIf = llvm::BasicBlock::Create(m_llvmCtx, "", func); freeScopeHeap(); m_builder.CreateBr(statement.afterIf); // Create else branch assert(!statement.elseBranch); - statement.elseBranch = llvm::BasicBlock::Create(m_ctx, "", func); + statement.elseBranch = llvm::BasicBlock::Create(m_llvmCtx, "", func); // Since there's an else branch, the conditional instruction should jump to it m_builder.SetInsertPoint(statement.beforeIf); @@ -859,7 +856,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Jump to the branch after the if statement if (!statement.afterIf) - statement.afterIf = llvm::BasicBlock::Create(m_ctx, "", func); + statement.afterIf = llvm::BasicBlock::Create(m_llvmCtx, "", func); m_builder.CreateBr(statement.afterIf); @@ -888,9 +885,9 @@ std::shared_ptr LLVMCodeBuilder::finalize() m_builder.CreateStore(zero, loop.index); // Create branches - llvm::BasicBlock *roundBranch = llvm::BasicBlock::Create(m_ctx, "", func); - loop.conditionBranch = llvm::BasicBlock::Create(m_ctx, "", func); - loop.afterLoop = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *roundBranch = llvm::BasicBlock::Create(m_llvmCtx, "", func); + loop.conditionBranch = llvm::BasicBlock::Create(m_llvmCtx, "", func); + loop.afterLoop = llvm::BasicBlock::Create(m_llvmCtx, "", func); // Use last reg for count assert(step.args.size() == 1); @@ -900,12 +897,12 @@ std::shared_ptr LLVMCodeBuilder::finalize() llvm::Value *isInf = m_builder.CreateFCmpOEQ(count, llvm::ConstantFP::getInfinity(m_builder.getDoubleTy(), false)); // Clamp count if <= 0 (we can skip the loop if count is not positive) - llvm::Value *comparison = m_builder.CreateFCmpULE(count, llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0))); + llvm::Value *comparison = m_builder.CreateFCmpULE(count, llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0))); m_builder.CreateCondBr(comparison, loop.afterLoop, roundBranch); // Round (Scratch-specific behavior) m_builder.SetInsertPoint(roundBranch); - llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module.get(), llvm::Intrinsic::round, { count->getType() }); + llvm::Function *roundFunc = llvm::Intrinsic::getDeclaration(m_module, llvm::Intrinsic::round, { count->getType() }); count = m_builder.CreateCall(roundFunc, { count }); count = m_builder.CreateFPToUI(count, m_builder.getInt64Ty()); // cast to unsigned integer count = m_builder.CreateSelect(isInf, zero, count); @@ -916,10 +913,10 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Check index m_builder.SetInsertPoint(loop.conditionBranch); - llvm::BasicBlock *body = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *body = llvm::BasicBlock::Create(m_llvmCtx, "", func); if (!loop.afterLoop) - loop.afterLoop = llvm::BasicBlock::Create(m_ctx, "", func); + loop.afterLoop = llvm::BasicBlock::Create(m_llvmCtx, "", func); llvm::Value *currentIndex = m_builder.CreateLoad(m_builder.getInt64Ty(), loop.index); comparison = m_builder.CreateOr(isInf, m_builder.CreateICmpULT(currentIndex, count)); @@ -946,8 +943,8 @@ std::shared_ptr LLVMCodeBuilder::finalize() LLVMLoop &loop = loops.back(); // Create branches - llvm::BasicBlock *body = llvm::BasicBlock::Create(m_ctx, "", func); - loop.afterLoop = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *body = llvm::BasicBlock::Create(m_llvmCtx, "", func); + loop.afterLoop = llvm::BasicBlock::Create(m_llvmCtx, "", func); // Use last reg assert(step.args.size() == 1); @@ -967,8 +964,8 @@ std::shared_ptr LLVMCodeBuilder::finalize() LLVMLoop &loop = loops.back(); // Create branches - llvm::BasicBlock *body = llvm::BasicBlock::Create(m_ctx, "", func); - loop.afterLoop = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *body = llvm::BasicBlock::Create(m_llvmCtx, "", func); + loop.afterLoop = llvm::BasicBlock::Create(m_llvmCtx, "", func); // Use last reg assert(step.args.size() == 1); @@ -986,7 +983,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() case LLVMInstruction::Type::BeginLoopCondition: { LLVMLoop loop; loop.isRepeatLoop = false; - loop.conditionBranch = llvm::BasicBlock::Create(m_ctx, "", func); + loop.conditionBranch = llvm::BasicBlock::Create(m_llvmCtx, "", func); m_builder.CreateBr(loop.conditionBranch); m_builder.SetInsertPoint(loop.conditionBranch); loops.push_back(loop); @@ -1018,7 +1015,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() case LLVMInstruction::Type::Stop: { m_builder.CreateBr(endBranch); - llvm::BasicBlock *nextBranch = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *nextBranch = llvm::BasicBlock::Create(m_llvmCtx, "", func); m_builder.SetInsertPoint(nextBranch); break; } @@ -1043,17 +1040,17 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Create resume function // bool resume(void *) funcType = llvm::FunctionType::get(m_builder.getInt1Ty(), pointerType, false); - func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "resume", m_module.get()); + llvm::Function *resumeFunc = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "resume", m_module); - entry = llvm::BasicBlock::Create(m_ctx, "entry", func); + entry = llvm::BasicBlock::Create(m_llvmCtx, "entry", resumeFunc); m_builder.SetInsertPoint(entry); if (m_warp) m_builder.CreateRet(m_builder.getInt1(true)); else - m_builder.CreateRet(coro->createResume(func->getArg(0))); + m_builder.CreateRet(coro->createResume(resumeFunc->getArg(0))); - verifyFunction(func); + verifyFunction(resumeFunc); #ifdef PRINT_LLVM_IR std::cout << std::endl << "=== LLVM IR (" << m_module->getName().str() << ") ===" << std::endl; @@ -1064,7 +1061,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() // Optimize optimize(); - return std::make_shared(std::move(m_module)); + return std::make_shared(m_ctx, func->getName().str(), resumeFunc->getName().str()); } CompilerValue *LLVMCodeBuilder::addFunctionCall(const std::string &functionName, Compiler::StaticType returnType, const Compiler::ArgTypes &argTypes, const Compiler::Args &args) @@ -1564,7 +1561,7 @@ void LLVMCodeBuilder::verifyFunction(llvm::Function *func) { if (llvm::verifyFunction(*func, &llvm::errs())) { llvm::errs() << "error: LLVM function verficiation failed!\n"; - llvm::errs() << "script hat ID: " << m_id << "\n"; + llvm::errs() << "module name: " << m_module->getName() << "\n"; } } @@ -1659,7 +1656,7 @@ llvm::Value *LLVMCodeBuilder::castValue(LLVMRegister *reg, Compiler::StaticType // True if != 0 llvm::Value *ptr = m_builder.CreateStructGEP(m_valueDataType, reg->value, 0); llvm::Value *numberValue = m_builder.CreateLoad(m_builder.getDoubleTy(), ptr); - return m_builder.CreateFCmpONE(numberValue, llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0))); + return m_builder.CreateFCmpONE(numberValue, llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0))); } case Compiler::StaticType::Bool: { @@ -1692,7 +1689,7 @@ llvm::Value *LLVMCodeBuilder::castValue(LLVMRegister *reg, Compiler::StaticType case Compiler::StaticType::String: { // Read string pointer directly llvm::Value *ptr = m_builder.CreateStructGEP(m_valueDataType, reg->value, 0); - return m_builder.CreateLoad(llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0), ptr); + return m_builder.CreateLoad(llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0), ptr); } default: @@ -1732,7 +1729,7 @@ llvm::Value *LLVMCodeBuilder::castRawValue(LLVMRegister *reg, Compiler::StaticTy switch (reg->type()) { case Compiler::StaticType::Number: // Cast double to bool (true if != 0) - return m_builder.CreateFCmpONE(reg->value, llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0))); + return m_builder.CreateFCmpONE(reg->value, llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0))); case Compiler::StaticType::String: // Convert string to bool @@ -1775,7 +1772,7 @@ llvm::Constant *LLVMCodeBuilder::castConstValue(const Value &value, Compiler::St switch (targetType) { case Compiler::StaticType::Number: { const double nan = std::numeric_limits::quiet_NaN(); - return llvm::ConstantFP::get(m_ctx, llvm::APFloat(value.isNaN() ? nan : value.toDouble())); + return llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(value.isNaN() ? nan : value.toDouble())); } case Compiler::StaticType::Bool: @@ -1814,7 +1811,7 @@ llvm::Type *LLVMCodeBuilder::getType(Compiler::StaticType type) return m_builder.getInt1Ty(); case Compiler::StaticType::String: - return llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + return llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); default: assert(false); @@ -1830,7 +1827,7 @@ llvm::Value *LLVMCodeBuilder::isNaN(llvm::Value *num) llvm::Value *LLVMCodeBuilder::removeNaN(llvm::Value *num) { // Replace NaN with zero - return m_builder.CreateSelect(isNaN(num), llvm::ConstantFP::get(m_ctx, llvm::APFloat(0.0)), num); + return m_builder.CreateSelect(isNaN(num), llvm::ConstantFP::get(m_llvmCtx, llvm::APFloat(0.0)), num); } llvm::Value *LLVMCodeBuilder::getVariablePtr(llvm::Value *targetVariables, Variable *variable) @@ -1854,7 +1851,7 @@ llvm::Value *LLVMCodeBuilder::getListPtr(llvm::Value *targetLists, List *list) // If this is a local sprite list, use the list array at runtime (for clones) assert(m_targetListMap.find(list) != m_targetListMap.cend()); const size_t index = m_targetListMap[list]; - auto pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + auto pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); llvm::Value *ptr = m_builder.CreateGEP(pointerType, targetLists, m_builder.getInt64(index)); return m_builder.CreateLoad(pointerType, ptr); } @@ -2067,12 +2064,12 @@ llvm::Value *LLVMCodeBuilder::getListItem(const LLVMListPtr &listPtr, llvm::Valu llvm::Value *LLVMCodeBuilder::getListItemIndex(const LLVMListPtr &listPtr, LLVMRegister *item, llvm::Function *func) { llvm::Value *size = m_builder.CreateLoad(m_builder.getInt64Ty(), listPtr.sizePtr); - llvm::BasicBlock *condBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *bodyBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *cmpIfBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *cmpElseBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *notFoundBlock = llvm::BasicBlock::Create(m_ctx, "", func); - llvm::BasicBlock *nextBlock = llvm::BasicBlock::Create(m_ctx, "", func); + llvm::BasicBlock *condBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *bodyBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *cmpIfBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *cmpElseBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *notFoundBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); + llvm::BasicBlock *nextBlock = llvm::BasicBlock::Create(m_llvmCtx, "", func); // index = 0 llvm::Value *index = m_builder.CreateAlloca(m_builder.getInt64Ty()); @@ -2105,7 +2102,7 @@ llvm::Value *LLVMCodeBuilder::getListItemIndex(const LLVMListPtr &listPtr, LLVMR // index = -1 // goto nextBlock m_builder.SetInsertPoint(notFoundBlock); - m_builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(m_ctx), -1, true), index); + m_builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt64Ty(m_llvmCtx), -1, true), index); m_builder.CreateBr(nextBlock); // nextBlock: @@ -2381,7 +2378,9 @@ llvm::FunctionCallee LLVMCodeBuilder::resolve_value_assign_bool() llvm::FunctionCallee LLVMCodeBuilder::resolve_value_assign_cstring() { - return resolveFunction("value_assign_cstring", llvm::FunctionType::get(m_builder.getVoidTy(), { m_valueDataType->getPointerTo(), llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0) }, false)); + return resolveFunction( + "value_assign_cstring", + llvm::FunctionType::get(m_builder.getVoidTy(), { m_valueDataType->getPointerTo(), llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0) }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_value_assign_special() @@ -2406,27 +2405,27 @@ llvm::FunctionCallee LLVMCodeBuilder::resolve_value_toBool() llvm::FunctionCallee LLVMCodeBuilder::resolve_value_toCString() { - return resolveFunction("value_toCString", llvm::FunctionType::get(llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0), m_valueDataType->getPointerTo(), false)); + return resolveFunction("value_toCString", llvm::FunctionType::get(llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0), m_valueDataType->getPointerTo(), false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_value_doubleToCString() { - return resolveFunction("value_doubleToCString", llvm::FunctionType::get(llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0), m_builder.getDoubleTy(), false)); + return resolveFunction("value_doubleToCString", llvm::FunctionType::get(llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0), m_builder.getDoubleTy(), false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_value_boolToCString() { - return resolveFunction("value_boolToCString", llvm::FunctionType::get(llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0), m_builder.getInt1Ty(), false)); + return resolveFunction("value_boolToCString", llvm::FunctionType::get(llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0), m_builder.getInt1Ty(), false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_value_stringToDouble() { - return resolveFunction("value_stringToDouble", llvm::FunctionType::get(m_builder.getDoubleTy(), llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0), false)); + return resolveFunction("value_stringToDouble", llvm::FunctionType::get(m_builder.getDoubleTy(), llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0), false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_value_stringToBool() { - return resolveFunction("value_stringToBool", llvm::FunctionType::get(m_builder.getInt1Ty(), llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0), false)); + return resolveFunction("value_stringToBool", llvm::FunctionType::get(m_builder.getInt1Ty(), llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0), false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_value_equals() @@ -2449,79 +2448,79 @@ llvm::FunctionCallee LLVMCodeBuilder::resolve_value_lower() llvm::FunctionCallee LLVMCodeBuilder::resolve_list_clear() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_clear", llvm::FunctionType::get(m_builder.getVoidTy(), { listPtr }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_remove() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_remove", llvm::FunctionType::get(m_builder.getVoidTy(), { listPtr, m_builder.getInt64Ty() }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_append_empty() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_append_empty", llvm::FunctionType::get(m_valueDataType->getPointerTo(), { listPtr }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_insert_empty() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_insert_empty", llvm::FunctionType::get(m_valueDataType->getPointerTo(), { listPtr, m_builder.getInt64Ty() }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_data() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_data", llvm::FunctionType::get(m_valueDataType->getPointerTo(), { listPtr }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_size_ptr() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_size_ptr", llvm::FunctionType::get(m_builder.getInt64Ty()->getPointerTo()->getPointerTo(), { listPtr }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_alloc_size_ptr() { - llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *listPtr = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_alloc_size_ptr", llvm::FunctionType::get(m_builder.getInt64Ty()->getPointerTo()->getPointerTo(), { listPtr }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_list_to_string() { - llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("list_to_string", llvm::FunctionType::get(pointerType, { pointerType }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_llvm_random() { - llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); llvm::Type *valuePtr = m_valueDataType->getPointerTo(); return resolveFunction("llvm_random", llvm::FunctionType::get(m_builder.getDoubleTy(), { pointerType, valuePtr, valuePtr }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_llvm_random_double() { - llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("llvm_random_double", llvm::FunctionType::get(m_builder.getDoubleTy(), { pointerType, m_builder.getDoubleTy(), m_builder.getDoubleTy() }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_llvm_random_long() { - llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("llvm_random_long", llvm::FunctionType::get(m_builder.getDoubleTy(), { pointerType, m_builder.getInt64Ty(), m_builder.getInt64Ty() }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_llvm_random_bool() { - llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("llvm_random_bool", llvm::FunctionType::get(m_builder.getDoubleTy(), { pointerType, m_builder.getInt1Ty(), m_builder.getInt1Ty() }, false)); } llvm::FunctionCallee LLVMCodeBuilder::resolve_strcasecmp() { - llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0); + llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_llvmCtx), 0); return resolveFunction("strcasecmp", llvm::FunctionType::get(m_builder.getInt32Ty(), { pointerType, pointerType }, false)); } diff --git a/src/dev/engine/internal/llvm/llvmcodebuilder.h b/src/dev/engine/internal/llvm/llvmcodebuilder.h index 91f42e80..f504050a 100644 --- a/src/dev/engine/internal/llvm/llvmcodebuilder.h +++ b/src/dev/engine/internal/llvm/llvmcodebuilder.h @@ -16,13 +16,13 @@ namespace libscratchcpp { -class Target; +class LLVMCompilerContext; class LLVMConstantRegister; class LLVMCodeBuilder : public ICodeBuilder { public: - LLVMCodeBuilder(Target *target, const std::string &id, bool warp); + LLVMCodeBuilder(LLVMCompilerContext *ctx, bool warp); std::shared_ptr finalize() override; @@ -190,9 +190,9 @@ class LLVMCodeBuilder : public ICodeBuilder std::unordered_map m_listPtrs; std::vector> m_scopeLists; - std::string m_id; - llvm::LLVMContext m_ctx; - std::unique_ptr m_module; + LLVMCompilerContext *m_ctx; + llvm::LLVMContext &m_llvmCtx; + llvm::Module *m_module = nullptr; llvm::IRBuilder<> m_builder; llvm::StructType *m_valueDataType = nullptr; diff --git a/src/dev/engine/internal/llvm/llvmcompilercontext.cpp b/src/dev/engine/internal/llvm/llvmcompilercontext.cpp new file mode 100644 index 00000000..0341bc79 --- /dev/null +++ b/src/dev/engine/internal/llvm/llvmcompilercontext.cpp @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include +#include + +#include "llvmcompilercontext.h" + +using namespace libscratchcpp; + +LLVMCompilerContext::LLVMCompilerContext(IEngine *engine, Target *target) : + CompilerContext(engine, target), + m_llvmCtx(std::make_unique()), + m_module(std::make_unique(target ? target->name() : "", *m_llvmCtx)), + m_llvmCtxPtr(m_llvmCtx.get()), + m_modulePtr(m_module.get()), + m_jit((initTarget(), llvm::orc::LLJITBuilder().create())) +{ + if (!m_jit) { + llvm::errs() << "error: failed to create JIT: " << toString(m_jit.takeError()) << "\n"; + return; + } +} + +llvm::LLVMContext *LLVMCompilerContext::llvmCtx() +{ + return m_llvmCtxPtr; +} + +llvm::Module *LLVMCompilerContext::module() +{ + return m_modulePtr; +} + +void LLVMCompilerContext::initJit() +{ + if (m_jitInitialized) { + std::cout << "warning: JIT compiler is already initialized" << std::endl; + return; + } + + m_jitInitialized = true; + assert(m_llvmCtx); + assert(m_module); + std::string name = m_module->getName().str(); + auto err = m_jit->get()->addIRModule(llvm::orc::ThreadSafeModule(std::move(m_module), std::move(m_llvmCtx))); + + if (err) { + llvm::errs() << "error: failed to add module '" << name << "' to JIT: " << toString(std::move(err)) << "\n"; + return; + } +} + +bool LLVMCompilerContext::jitInitialized() const +{ + return m_jitInitialized; +} + +void LLVMCompilerContext::initTarget() +{ + llvm::InitializeNativeTarget(); + llvm::InitializeNativeTargetAsmPrinter(); + llvm::InitializeNativeTargetAsmParser(); +} diff --git a/src/dev/engine/internal/llvm/llvmcompilercontext.h b/src/dev/engine/internal/llvm/llvmcompilercontext.h new file mode 100644 index 00000000..f549ff46 --- /dev/null +++ b/src/dev/engine/internal/llvm/llvmcompilercontext.h @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +#include + +namespace libscratchcpp +{ + +class ExecutionContext; +class ValueData; +class List; +class LLVMExecutableCode; + +class LLVMCompilerContext : public CompilerContext +{ + public: + LLVMCompilerContext(IEngine *engine, Target *target); + + llvm::LLVMContext *llvmCtx(); + llvm::Module *module(); + + void initJit(); + bool jitInitialized() const; + + template + T lookupFunction(const std::string &name) + { + auto func = m_jit->get()->lookup(name); + + if (func) + return (T)func->getValue(); + else { + llvm::errs() << "error: failed to lookup LLVM function: " << toString(func.takeError()) << "\n"; + return nullptr; + } + } + + private: + void initTarget(); + + std::unique_ptr m_llvmCtx; + std::unique_ptr m_module; + llvm::LLVMContext *m_llvmCtxPtr = nullptr; + llvm::Module *m_modulePtr = nullptr; + llvm::Expected> m_jit; + bool m_jitInitialized = false; +}; + +} // namespace libscratchcpp diff --git a/src/dev/engine/internal/llvm/llvmcoroutine.cpp b/src/dev/engine/internal/llvm/llvmcoroutine.cpp index 6a4ad6e1..17b834d9 100644 --- a/src/dev/engine/internal/llvm/llvmcoroutine.cpp +++ b/src/dev/engine/internal/llvm/llvmcoroutine.cpp @@ -1,5 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 +#include + #include "llvmcoroutine.h" using namespace libscratchcpp; @@ -28,7 +30,7 @@ LLVMCoroutine::LLVMCoroutine(llvm::Module *module, llvm::IRBuilder<> *builder, l // Allocate memory llvm::Value *coroSizeRet = builder->CreateCall(coroSize, std::nullopt, "size"); - llvm::Function *mallocFunc = llvm::Function::Create(llvm::FunctionType::get(pointerType, { builder->getInt64Ty() }, false), llvm::Function::ExternalLinkage, "malloc", module); + llvm::FunctionCallee mallocFunc = module->getOrInsertFunction("malloc", llvm::FunctionType::get(pointerType, { builder->getInt64Ty() }, false)); llvm::Value *alloc = builder->CreateCall(mallocFunc, coroSizeRet, "mem"); // Begin diff --git a/src/dev/engine/internal/llvm/llvmexecutablecode.cpp b/src/dev/engine/internal/llvm/llvmexecutablecode.cpp index 20aa9dfc..ed88ac60 100644 --- a/src/dev/engine/internal/llvm/llvmexecutablecode.cpp +++ b/src/dev/engine/internal/llvm/llvmexecutablecode.cpp @@ -6,43 +6,33 @@ #include #include #include -#include #include +#include + #include "llvmexecutablecode.h" +#include "llvmcompilercontext.h" #include "llvmexecutioncontext.h" using namespace libscratchcpp; -LLVMExecutableCode::LLVMExecutableCode(std::unique_ptr module) : - m_ctx(std::make_unique()), - m_jit(llvm::orc::LLJITBuilder().create()) +LLVMExecutableCode::LLVMExecutableCode(LLVMCompilerContext *ctx, const std::string &mainFunctionName, const std::string &resumeFunctionName) : + m_ctx(ctx), + m_mainFunctionName(mainFunctionName), + m_resumeFunctionName(resumeFunctionName) { - if (!m_jit) { - llvm::errs() << "error: failed to create JIT: " << toString(m_jit.takeError()) << "\n"; - return; - } + assert(m_ctx); - if (!module) - return; - - std::string name = module->getName().str(); - auto err = m_jit->get()->addIRModule(llvm::orc::ThreadSafeModule(std::move(module), std::move(m_ctx))); - - if (err) { - llvm::errs() << "error: failed to add module '" << name << "' to JIT: " << toString(std::move(err)) << "\n"; - return; + if (m_ctx->jitInitialized()) { + std::cerr << "error: cannot create LLVM code after JIT compiler had been initialized" << std::endl; + assert(false); } - - // Lookup functions - m_mainFunction = (MainFunctionType)lookupFunction("f"); - assert(m_mainFunction); - m_resumeFunction = (ResumeFunctionType)lookupFunction("resume"); - assert(m_resumeFunction); } void LLVMExecutableCode::run(ExecutionContext *context) { + assert(m_mainFunction); + assert(m_resumeFunction); LLVMExecutionContext *ctx = getContext(context); if (ctx->finished()) @@ -98,19 +88,12 @@ bool LLVMExecutableCode::isFinished(ExecutionContext *context) const std::shared_ptr LLVMExecutableCode::createExecutionContext(Thread *thread) const { - return std::make_shared(thread); -} - -uint64_t LLVMExecutableCode::lookupFunction(const std::string &name) -{ - auto func = m_jit->get()->lookup(name); + if (!m_ctx->jitInitialized()) + m_ctx->initJit(); - if (func) - return func->getValue(); - else { - llvm::errs() << "error: failed to lookup LLVM function: " << toString(func.takeError()) << "\n"; - return 0; - } + m_mainFunction = m_ctx->lookupFunction(m_mainFunctionName); + m_resumeFunction = m_ctx->lookupFunction(m_resumeFunctionName); + return std::make_shared(thread); } LLVMExecutionContext *LLVMExecutableCode::getContext(ExecutionContext *context) diff --git a/src/dev/engine/internal/llvm/llvmexecutablecode.h b/src/dev/engine/internal/llvm/llvmexecutablecode.h index 6d293b3d..aaa9c9c1 100644 --- a/src/dev/engine/internal/llvm/llvmexecutablecode.h +++ b/src/dev/engine/internal/llvm/llvmexecutablecode.h @@ -5,19 +5,18 @@ #include #include #include -#include + +#include "llvmcompilercontext.h" namespace libscratchcpp { -class Target; -class List; class LLVMExecutionContext; class LLVMExecutableCode : public ExecutableCode { public: - LLVMExecutableCode(std::unique_ptr module); + LLVMExecutableCode(LLVMCompilerContext *ctx, const std::string &mainFunctionName, const std::string &resumeFunctionName); void run(ExecutionContext *context) override; void kill(libscratchcpp::ExecutionContext *context) override; @@ -28,18 +27,16 @@ class LLVMExecutableCode : public ExecutableCode std::shared_ptr createExecutionContext(Thread *thread) const override; private: - uint64_t lookupFunction(const std::string &name); - using MainFunctionType = void *(*)(ExecutionContext *, Target *, ValueData **, List **); using ResumeFunctionType = bool (*)(void *); static LLVMExecutionContext *getContext(ExecutionContext *context); - std::unique_ptr m_ctx; - llvm::Expected> m_jit; - - MainFunctionType m_mainFunction; - ResumeFunctionType m_resumeFunction; + LLVMCompilerContext *m_ctx = nullptr; + std::string m_mainFunctionName; + std::string m_resumeFunctionName; + mutable MainFunctionType m_mainFunction = nullptr; + mutable ResumeFunctionType m_resumeFunction = nullptr; }; } // namespace libscratchcpp diff --git a/src/engine/internal/engine.cpp b/src/engine/internal/engine.cpp index 1be628aa..ee9708a8 100644 --- a/src/engine/internal/engine.cpp +++ b/src/engine/internal/engine.cpp @@ -271,10 +271,14 @@ void Engine::compile() // Compile scripts to bytecode for (auto target : m_targets) { std::cout << "Compiling scripts in target " << target->name() << "..." << std::endl; -#ifndef USE_LLVM +#ifdef USE_LLVM + auto ctx = Compiler::createContext(this, target.get()); + m_compilerContexts[target.get()] = ctx; + Compiler compiler(ctx.get()); +#else std::unordered_map procedureBytecodeMap; -#endif Compiler compiler(this, target.get()); +#endif const auto &blocks = target->blocks(); for (auto block : blocks) { if (block->topLevel() && !block->isTopLevelReporter() && !block->shadow()) { diff --git a/src/engine/internal/engine.h b/src/engine/internal/engine.h index 69d64835..ed4b562d 100644 --- a/src/engine/internal/engine.h +++ b/src/engine/internal/engine.h @@ -19,6 +19,9 @@ class Entity; class IClock; class IAudioEngine; class Thread; +#ifdef USE_LLVM +class CompilerContext; +#endif class Engine : public IEngine { @@ -238,6 +241,9 @@ class Engine : public IEngine static const std::unordered_map m_hatEdgeActivated; // used to check whether a hat is edge-activated (runs when a predicate becomes true) std::vector> m_targets; +#ifdef USE_LLVM + std::unordered_map> m_compilerContexts; +#endif std::vector> m_broadcasts; std::unordered_map> m_broadcastMap; std::unordered_map> m_backdropBroadcastMap; diff --git a/test/dev/compiler/compiler_test.cpp b/test/dev/compiler/compiler_test.cpp index 945e2d0d..22241e08 100644 --- a/test/dev/compiler/compiler_test.cpp +++ b/test/dev/compiler/compiler_test.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -26,7 +27,12 @@ class CompilerTest : public testing::Test public: void SetUp() override { + m_ctx = std::make_shared(&m_engine, &m_target); CompilerPrivate::builderFactory = &m_builderFactory; + + EXPECT_CALL(m_builderFactory, createCtx(&m_engine, &m_target)).WillOnce(Return(m_ctx)); + m_compiler = std::make_unique(&m_engine, &m_target); + m_builder = std::make_shared(); m_code = std::make_shared(); } @@ -39,18 +45,20 @@ class CompilerTest : public testing::Test m_testVar.reset(); } - void compile(Compiler &compiler, std::shared_ptr block) + void compile(Compiler *compiler, std::shared_ptr block) { - ASSERT_EQ(compiler.block(), nullptr); + ASSERT_EQ(compiler->block(), nullptr); // TODO: Test warp - EXPECT_CALL(m_builderFactory, create(compiler.target(), block->id(), false)).WillOnce(Return(m_builder)); + EXPECT_CALL(m_builderFactory, create(m_ctx.get(), 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); + ASSERT_EQ(compiler->compile(block), m_code); + ASSERT_EQ(compiler->block(), nullptr); } EngineMock m_engine; TargetMock m_target; + std::unique_ptr m_compiler; + std::shared_ptr m_ctx; CodeBuilderFactoryMock m_builderFactory; static inline std::shared_ptr m_builder; std::shared_ptr m_code; @@ -58,16 +66,19 @@ class CompilerTest : public testing::Test static inline std::shared_ptr m_testVar; }; -TEST_F(CompilerTest, Constructors) +TEST_F(CompilerTest, Engine) +{ + ASSERT_EQ(m_compiler->engine(), &m_engine); +} + +TEST_F(CompilerTest, Target) { - Compiler compiler(&m_engine, &m_target); - ASSERT_EQ(compiler.engine(), &m_engine); - ASSERT_EQ(compiler.target(), &m_target); + ASSERT_EQ(m_compiler->target(), &m_target); } TEST_F(CompilerTest, AddFunctionCall) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); m_compareBlock = block; block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -87,12 +98,12 @@ TEST_F(CompilerTest, AddFunctionCall) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddTargetFunctionCall) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); m_compareBlock = block; block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -112,12 +123,12 @@ TEST_F(CompilerTest, AddTargetFunctionCall) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddFunctionCallWithCtx) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); m_compareBlock = block; block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -137,12 +148,12 @@ TEST_F(CompilerTest, AddFunctionCallWithCtx) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddConstValue) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerConstant ret(Compiler::StaticType::Unknown, Value()); @@ -159,12 +170,12 @@ TEST_F(CompilerTest, AddConstValue) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddLoopIndex) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -178,12 +189,12 @@ TEST_F(CompilerTest, AddLoopIndex) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddLocalVariableValue) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Number); @@ -201,12 +212,12 @@ TEST_F(CompilerTest, AddLocalVariableValue) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddVariableValue) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -221,12 +232,12 @@ TEST_F(CompilerTest, AddVariableValue) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddListContents) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -241,12 +252,12 @@ TEST_F(CompilerTest, AddListContents) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddListItem) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -262,12 +273,12 @@ TEST_F(CompilerTest, AddListItem) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddListItemIndex) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -283,12 +294,12 @@ TEST_F(CompilerTest, AddListItemIndex) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddListSize) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -303,12 +314,12 @@ TEST_F(CompilerTest, AddListSize) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddListContains) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { CompilerValue ret(Compiler::StaticType::Unknown); @@ -324,12 +335,12 @@ TEST_F(CompilerTest, AddListContains) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, AddInput) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); auto valueBlock = std::make_shared("b", ""); m_compareBlock = valueBlock; @@ -415,12 +426,12 @@ TEST_F(CompilerTest, AddInput) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateAdd) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -433,12 +444,12 @@ TEST_F(CompilerTest, CreateAdd) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateSub) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -451,12 +462,12 @@ TEST_F(CompilerTest, CreateSub) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateMul) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -469,12 +480,12 @@ TEST_F(CompilerTest, CreateMul) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateDiv) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -487,12 +498,12 @@ TEST_F(CompilerTest, CreateDiv) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateRandom) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -505,12 +516,12 @@ TEST_F(CompilerTest, CreateRandom) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateRandomInt) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -523,12 +534,12 @@ TEST_F(CompilerTest, CreateRandomInt) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateCmpEQ) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -541,12 +552,12 @@ TEST_F(CompilerTest, CreateCmpEQ) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateCmpGT) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -559,12 +570,12 @@ TEST_F(CompilerTest, CreateCmpGT) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateCmpLT) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -577,12 +588,12 @@ TEST_F(CompilerTest, CreateCmpLT) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateAnd) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -595,12 +606,12 @@ TEST_F(CompilerTest, CreateAnd) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateOr) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -613,12 +624,12 @@ TEST_F(CompilerTest, CreateOr) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateNot) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -630,12 +641,12 @@ TEST_F(CompilerTest, CreateNot) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateMod) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -648,12 +659,12 @@ TEST_F(CompilerTest, CreateMod) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateRound) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -665,12 +676,12 @@ TEST_F(CompilerTest, CreateRound) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateAbs) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -682,12 +693,12 @@ TEST_F(CompilerTest, CreateAbs) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateFloor) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -699,12 +710,12 @@ TEST_F(CompilerTest, CreateFloor) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateCeil) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -716,12 +727,12 @@ TEST_F(CompilerTest, CreateCeil) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateSqrt) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -733,12 +744,12 @@ TEST_F(CompilerTest, CreateSqrt) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateSin) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -750,12 +761,12 @@ TEST_F(CompilerTest, CreateSin) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateCos) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -767,12 +778,12 @@ TEST_F(CompilerTest, CreateCos) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateTan) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -784,12 +795,12 @@ TEST_F(CompilerTest, CreateTan) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateAsin) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -801,12 +812,12 @@ TEST_F(CompilerTest, CreateAsin) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateAcos) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -818,12 +829,12 @@ TEST_F(CompilerTest, CreateAcos) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateAtan) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -835,12 +846,12 @@ TEST_F(CompilerTest, CreateAtan) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateLn) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -852,12 +863,12 @@ TEST_F(CompilerTest, CreateLn) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateLog10) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -869,12 +880,12 @@ TEST_F(CompilerTest, CreateLog10) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateExp) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -886,12 +897,12 @@ TEST_F(CompilerTest, CreateExp) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateExp10) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -903,12 +914,12 @@ TEST_F(CompilerTest, CreateExp10) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateSelect) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -926,12 +937,12 @@ TEST_F(CompilerTest, CreateSelect) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateLocalVariable) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -948,12 +959,12 @@ TEST_F(CompilerTest, CreateLocalVariable) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateLocalVariableWrite) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -966,12 +977,12 @@ TEST_F(CompilerTest, CreateLocalVariableWrite) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateVariableWrite) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -983,12 +994,12 @@ TEST_F(CompilerTest, CreateVariableWrite) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CustomIfStatement) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1008,12 +1019,12 @@ TEST_F(CompilerTest, CustomIfStatement) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CustomWhileLoop) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1026,12 +1037,12 @@ TEST_F(CompilerTest, CustomWhileLoop) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CustomRepeatUntilLoop) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1044,12 +1055,12 @@ TEST_F(CompilerTest, CustomRepeatUntilLoop) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, BeginLoopCondition) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { EXPECT_CALL(*m_builder, beginLoopCondition()); @@ -1057,12 +1068,12 @@ TEST_F(CompilerTest, BeginLoopCondition) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, MoveToIf) { - Compiler compiler(&m_engine, &m_target); + EXPECT_CALL(*m_builder, beginElseBranch).Times(0); auto if1 = std::make_shared("", "if"); @@ -1094,12 +1105,11 @@ TEST_F(CompilerTest, MoveToIf) input->setValueBlock(substack1); if2->addInput(input); - compile(compiler, if1); + compile(m_compiler.get(), if1); } TEST_F(CompilerTest, MoveToIfElse) { - Compiler compiler(&m_engine, &m_target); auto if1 = std::make_shared("", "if"); if1->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1264,12 +1274,11 @@ TEST_F(CompilerTest, MoveToIfElse) block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue("after"); }); EXPECT_CALL(*m_builder, addConstValue(Value("after"))); - compile(compiler, if1); + compile(m_compiler.get(), if1); } TEST_F(CompilerTest, MoveToRepeatLoop) { - Compiler compiler(&m_engine, &m_target); auto l1 = std::make_shared("", "loop"); l1->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1354,12 +1363,11 @@ TEST_F(CompilerTest, MoveToRepeatLoop) block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue("after"); }); EXPECT_CALL(*m_builder, addConstValue(Value("after"))); - compile(compiler, l1); + compile(m_compiler.get(), l1); } TEST_F(CompilerTest, MoveToWhileLoop) { - Compiler compiler(&m_engine, &m_target); auto l1 = std::make_shared("", "loop"); l1->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1444,12 +1452,11 @@ TEST_F(CompilerTest, MoveToWhileLoop) block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue("after"); }); EXPECT_CALL(*m_builder, addConstValue(Value("after"))); - compile(compiler, l1); + compile(m_compiler.get(), l1); } TEST_F(CompilerTest, MoveToRepeatUntilLoop) { - Compiler compiler(&m_engine, &m_target); auto l1 = std::make_shared("", "loop"); l1->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1534,12 +1541,12 @@ TEST_F(CompilerTest, MoveToRepeatUntilLoop) block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { return compiler->addConstValue("after"); }); EXPECT_CALL(*m_builder, addConstValue(Value("after"))); - compile(compiler, l1); + compile(m_compiler.get(), l1); } TEST_F(CompilerTest, CreateYield) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1548,12 +1555,12 @@ TEST_F(CompilerTest, CreateYield) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, CreateStop) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("", ""); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1562,12 +1569,12 @@ TEST_F(CompilerTest, CreateStop) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, Input) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->addInput(std::make_shared("TEST", Input::Type::Shadow)); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1576,12 +1583,12 @@ TEST_F(CompilerTest, Input) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, Field) { - Compiler compiler(&m_engine, &m_target); + auto block = std::make_shared("a", ""); block->addField(std::make_shared("TEST", "test")); block->setCompileFunction([](Compiler *compiler) -> CompilerValue * { @@ -1590,7 +1597,7 @@ TEST_F(CompilerTest, Field) return nullptr; }); - compile(compiler, block); + compile(m_compiler.get(), block); } TEST_F(CompilerTest, UnsupportedBlocks) @@ -1648,9 +1655,8 @@ TEST_F(CompilerTest, UnsupportedBlocks) block4->setParent(block3); block3->setNext(block4); - Compiler compiler(&m_engine, &m_target); EXPECT_CALL(*m_builder, addConstValue).WillRepeatedly(Return(nullptr)); - compile(compiler, block1); + compile(m_compiler.get(), block1); - ASSERT_EQ(compiler.unsupportedBlocks(), std::unordered_set({ "block1", "block2", "value_block1", "value_block3", "value_block5", "block4" })); + ASSERT_EQ(m_compiler->unsupportedBlocks(), std::unordered_set({ "block1", "block2", "value_block1", "value_block3", "value_block5", "block4" })); } diff --git a/test/dev/llvm/llvmcodebuilder_test.cpp b/test/dev/llvm/llvmcodebuilder_test.cpp index 9a7f2f1c..2cc1141d 100644 --- a/test/dev/llvm/llvmcodebuilder_test.cpp +++ b/test/dev/llvm/llvmcodebuilder_test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +61,12 @@ class LLVMCodeBuilderTest : public testing::Test test_function(nullptr, nullptr, nullptr, nullptr, nullptr); // force dependency } - void createBuilder(Target *target, bool warp) { m_builder = std::make_unique(target, "test", warp); } + void createBuilder(Target *target, bool warp) + { + m_ctx = std::make_unique(&m_engine, target); + m_builder = std::make_unique(m_ctx.get(), warp); + } + void createBuilder(bool warp) { createBuilder(nullptr, warp); } CompilerValue *callConstFuncForType(ValueType type, CompilerValue *arg) @@ -353,7 +359,9 @@ class LLVMCodeBuilderTest : public testing::Test ASSERT_THAT(testing::internal::GetCapturedStdout(), Eq(expected)) << quotes << v.toString() << quotes; }; + std::unique_ptr m_ctx; std::unique_ptr m_builder; + EngineMock m_engine; TargetMock m_target; // NOTE: isStage() is used for call expectations RandomGeneratorMock m_rng; }; @@ -1521,11 +1529,10 @@ TEST_F(LLVMCodeBuilderTest, Exp10) TEST_F(LLVMCodeBuilderTest, LocalVariables) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); createBuilder(&sprite, true); @@ -1578,11 +1585,10 @@ TEST_F(LLVMCodeBuilderTest, LocalVariables) TEST_F(LLVMCodeBuilderTest, WriteVariable) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalVar1 = std::make_shared("", ""); auto globalVar2 = std::make_shared("", ""); @@ -1642,11 +1648,10 @@ TEST_F(LLVMCodeBuilderTest, WriteVariable) TEST_F(LLVMCodeBuilderTest, Select) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); createBuilder(&sprite, true); @@ -1730,11 +1735,10 @@ TEST_F(LLVMCodeBuilderTest, Select) TEST_F(LLVMCodeBuilderTest, ReadVariable) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalVar1 = std::make_shared("", "", 87); auto globalVar2 = std::make_shared("", "", 6.4); @@ -1791,11 +1795,10 @@ TEST_F(LLVMCodeBuilderTest, ReadVariable) TEST_F(LLVMCodeBuilderTest, ClearList) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -1869,11 +1872,10 @@ TEST_F(LLVMCodeBuilderTest, ClearList) TEST_F(LLVMCodeBuilderTest, RemoveFromList) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -1915,11 +1917,10 @@ TEST_F(LLVMCodeBuilderTest, RemoveFromList) TEST_F(LLVMCodeBuilderTest, AppendToList) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -1975,11 +1976,10 @@ TEST_F(LLVMCodeBuilderTest, AppendToList) TEST_F(LLVMCodeBuilderTest, InsertToList) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -2041,11 +2041,10 @@ TEST_F(LLVMCodeBuilderTest, InsertToList) TEST_F(LLVMCodeBuilderTest, ListReplace) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -2101,11 +2100,10 @@ TEST_F(LLVMCodeBuilderTest, ListReplace) TEST_F(LLVMCodeBuilderTest, GetListContents) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -2153,11 +2151,10 @@ TEST_F(LLVMCodeBuilderTest, GetListContents) TEST_F(LLVMCodeBuilderTest, GetListItem) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); std::unordered_map strings; @@ -2226,11 +2223,10 @@ TEST_F(LLVMCodeBuilderTest, GetListItem) TEST_F(LLVMCodeBuilderTest, GetListSize) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalList = std::make_shared("", ""); stage.addList(globalList); @@ -2275,11 +2271,10 @@ TEST_F(LLVMCodeBuilderTest, GetListSize) TEST_F(LLVMCodeBuilderTest, GetListItemIndex) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalList = std::make_shared("", ""); stage.addList(globalList); @@ -2370,11 +2365,10 @@ TEST_F(LLVMCodeBuilderTest, GetListItemIndex) TEST_F(LLVMCodeBuilderTest, ListContainsItem) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalList = std::make_shared("", ""); stage.addList(globalList); @@ -2547,11 +2541,10 @@ TEST_F(LLVMCodeBuilderTest, Yield) TEST_F(LLVMCodeBuilderTest, VariablesAfterSuspend) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalVar = std::make_shared("", "", 87); stage.addVariable(globalVar); @@ -2598,11 +2591,11 @@ TEST_F(LLVMCodeBuilderTest, VariablesAfterSuspend) TEST_F(LLVMCodeBuilderTest, ListsAfterSuspend) { - EngineMock engine; + Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalList1 = std::make_shared("", ""); stage.addList(globalList1); @@ -2885,11 +2878,10 @@ TEST_F(LLVMCodeBuilderTest, IfStatement) TEST_F(LLVMCodeBuilderTest, IfStatementVariables) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalVar = std::make_shared("", "", "test"); stage.addVariable(globalVar); @@ -2983,11 +2975,10 @@ TEST_F(LLVMCodeBuilderTest, IfStatementVariables) TEST_F(LLVMCodeBuilderTest, IfStatementLists) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalList1 = std::make_shared("", ""); stage.addList(globalList1); @@ -3507,11 +3498,10 @@ TEST_F(LLVMCodeBuilderTest, RepeatUntilLoop) TEST_F(LLVMCodeBuilderTest, LoopVariables) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalVar = std::make_shared("", "", "test"); stage.addVariable(globalVar); @@ -3641,11 +3631,10 @@ TEST_F(LLVMCodeBuilderTest, LoopVariables) TEST_F(LLVMCodeBuilderTest, LoopLists) { - EngineMock engine; Stage stage; Sprite sprite; - sprite.setEngine(&engine); - EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage)); + sprite.setEngine(&m_engine); + EXPECT_CALL(m_engine, stage()).WillRepeatedly(Return(&stage)); auto globalList1 = std::make_shared("", ""); stage.addList(globalList1); diff --git a/test/dev/llvm/llvmexecutablecode_test.cpp b/test/dev/llvm/llvmexecutablecode_test.cpp index 581a3a58..08427a32 100644 --- a/test/dev/llvm/llvmexecutablecode_test.cpp +++ b/test/dev/llvm/llvmexecutablecode_test.cpp @@ -6,8 +6,9 @@ #include #include #include +#include #include -#include +#include #include #include @@ -21,27 +22,26 @@ class LLVMExecutableCodeTest : public testing::Test public: void SetUp() override { - m_module = std::make_unique("test", m_ctx); - m_builder = std::make_unique>(m_ctx); + m_target.setName("test"); + m_ctx = std::make_unique(&m_engine, &m_target); + m_module = m_ctx->module(); + m_llvmCtx = m_ctx->llvmCtx(); + m_builder = std::make_unique>(*m_llvmCtx); test_function(nullptr, nullptr, nullptr, nullptr, nullptr); // force dependency m_script = std::make_unique