From 759347a0e442d314a52b908e14210704ab2ce939 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 25 Feb 2025 13:41:15 +0100 Subject: [PATCH 1/2] Enable sanitizer in debug builds --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd02d102..59128439 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,12 @@ option(LIBSCRATCHCPP_BUILD_UNIT_TESTS "Build unit tests" ON) option(LIBSCRATCHCPP_NETWORK_SUPPORT "Support for downloading projects" ON) option(LIBSCRATCHCPP_PRINT_LLVM_IR "Print LLVM IR of compiled Scratch scripts (for debugging)" OFF) +if (CMAKE_BUILD_TYPE MATCHES "Debug") + set(SANITIZER_FLAGS "-fsanitize=undefined -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_CFLAGS ${CMAKE_CFLAGS} ${SANITIZER_FLAGS}) + set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${SANITIZER_FLAGS}) +endif() + add_library(scratchcpp SHARED) add_subdirectory(src) include_directories(src) # TODO: Remove this line From 8869d4b9a9985628137d1dde7486d690e2e9ed38 Mon Sep 17 00:00:00 2001 From: adazem009 <68537469+adazem009@users.noreply.github.com> Date: Tue, 25 Feb 2025 20:30:13 +0100 Subject: [PATCH 2/2] Refactor CompilerValue class hierarchy --- include/scratchcpp/compilerconstant.h | 2 +- src/engine/internal/llvm/CMakeLists.txt | 1 - src/engine/internal/llvm/llvmcodebuilder.cpp | 20 ++++++------- .../internal/llvm/llvmconstantregister.h | 11 +++---- src/engine/internal/llvm/llvmregister.h | 24 +++++++-------- src/engine/internal/llvm/llvmregisterbase.h | 29 ------------------- test/llvm/llvmcodebuilder_test.cpp | 1 + 7 files changed, 30 insertions(+), 58 deletions(-) delete mode 100644 src/engine/internal/llvm/llvmregisterbase.h diff --git a/include/scratchcpp/compilerconstant.h b/include/scratchcpp/compilerconstant.h index 51d6347b..9ccb8f12 100644 --- a/include/scratchcpp/compilerconstant.h +++ b/include/scratchcpp/compilerconstant.h @@ -10,7 +10,7 @@ namespace libscratchcpp class CompilerConstantPrivate; /*! \brief The CompilerConstant class represents a constant value in compiled code. */ -class LIBSCRATCHCPP_EXPORT CompilerConstant : public CompilerValue +class LIBSCRATCHCPP_EXPORT CompilerConstant : public virtual CompilerValue { public: CompilerConstant(Compiler::StaticType type, const Value &value); diff --git a/src/engine/internal/llvm/CMakeLists.txt b/src/engine/internal/llvm/CMakeLists.txt index 38b7e4d2..01520d08 100644 --- a/src/engine/internal/llvm/CMakeLists.txt +++ b/src/engine/internal/llvm/CMakeLists.txt @@ -2,7 +2,6 @@ target_sources(scratchcpp PRIVATE llvmcodebuilder.cpp llvmcodebuilder.h - llvmregisterbase.h llvmregister.h llvmconstantregister.h llvminstruction.h diff --git a/src/engine/internal/llvm/llvmcodebuilder.cpp b/src/engine/internal/llvm/llvmcodebuilder.cpp index 91c97ef4..d676187f 100644 --- a/src/engine/internal/llvm/llvmcodebuilder.cpp +++ b/src/engine/internal/llvm/llvmcodebuilder.cpp @@ -980,7 +980,7 @@ std::shared_ptr LLVMCodeBuilder::finalize() llvm::Value *inRange = m_builder.CreateAnd(m_builder.CreateFCmpOGE(index, min), m_builder.CreateFCmpOLT(index, size)); LLVMConstantRegister nullReg(listPtr.type == Compiler::StaticType::Unknown ? Compiler::StaticType::Number : listPtr.type, Value()); - llvm::Value *null = createValue(static_cast(static_cast(&nullReg))); + llvm::Value *null = createValue(static_cast(&nullReg)); index = m_builder.CreateFPToUI(index, m_builder.getInt64Ty()); step.functionReturnReg->value = m_builder.CreateSelect(inRange, getListItem(listPtr, index), null); @@ -1378,7 +1378,7 @@ CompilerValue *LLVMCodeBuilder::addFunctionCall(const std::string &functionName, ins->functionName = functionName; for (size_t i = 0; i < args.size(); i++) - ins->args.push_back({ argTypes[i], static_cast(args[i]) }); + ins->args.push_back({ argTypes[i], dynamic_cast(args[i]) }); if (returnType != Compiler::StaticType::Void) { auto reg = std::make_shared(returnType); @@ -1409,9 +1409,9 @@ CompilerValue *LLVMCodeBuilder::addFunctionCallWithCtx(const std::string &functi CompilerConstant *LLVMCodeBuilder::addConstValue(const Value &value) { auto constReg = std::make_shared(TYPE_MAP[value.type()], value); - auto reg = std::reinterpret_pointer_cast(constReg); + auto reg = std::static_pointer_cast(constReg); m_lastConstValue = reg.get(); - return static_cast(static_cast(addReg(reg, nullptr))); + return static_cast(static_cast(addReg(reg, nullptr))); } CompilerValue *LLVMCodeBuilder::addStringChar(CompilerValue *string, CompilerValue *index) @@ -1470,7 +1470,7 @@ CompilerValue *LLVMCodeBuilder::addListItem(List *list, CompilerValue *index) if (m_listPtrs.find(list) == m_listPtrs.cend()) m_listPtrs[list] = LLVMListPtr(); - ins->args.push_back({ Compiler::StaticType::Number, static_cast(index) }); + ins->args.push_back({ Compiler::StaticType::Number, dynamic_cast(index) }); auto ret = std::make_shared(Compiler::StaticType::Unknown); ret->isRawValue = false; @@ -1807,7 +1807,7 @@ void LLVMCodeBuilder::createListReplace(List *list, CompilerValue *index, Compil void LLVMCodeBuilder::beginIfStatement(CompilerValue *cond) { auto ins = std::make_shared(LLVMInstruction::Type::BeginIf, currentLoopScope(), m_loopCondition); - ins->args.push_back({ Compiler::StaticType::Bool, static_cast(cond) }); + ins->args.push_back({ Compiler::StaticType::Bool, dynamic_cast(cond) }); m_instructions.push_back(ins); } @@ -1826,7 +1826,7 @@ void LLVMCodeBuilder::beginRepeatLoop(CompilerValue *count) assert(!m_loopCondition); auto ins = std::make_shared(LLVMInstruction::Type::BeginRepeatLoop, currentLoopScope(), m_loopCondition); - ins->args.push_back({ Compiler::StaticType::Number, static_cast(count) }); + ins->args.push_back({ Compiler::StaticType::Number, dynamic_cast(count) }); m_instructions.push_back(ins); pushLoopScope(false); } @@ -1837,7 +1837,7 @@ void LLVMCodeBuilder::beginWhileLoop(CompilerValue *cond) m_loopCondition = false; auto ins = std::make_shared(LLVMInstruction::Type::BeginWhileLoop, currentLoopScope(), m_loopCondition); - ins->args.push_back({ Compiler::StaticType::Bool, static_cast(cond) }); + ins->args.push_back({ Compiler::StaticType::Bool, dynamic_cast(cond) }); m_instructions.push_back(ins); pushLoopScope(false); } @@ -1848,7 +1848,7 @@ void LLVMCodeBuilder::beginRepeatUntilLoop(CompilerValue *cond) m_loopCondition = false; auto ins = std::make_shared(LLVMInstruction::Type::BeginRepeatUntilLoop, currentLoopScope(), m_loopCondition); - ins->args.push_back({ Compiler::StaticType::Bool, static_cast(cond) }); + ins->args.push_back({ Compiler::StaticType::Bool, dynamic_cast(cond) }); m_instructions.push_back(ins); pushLoopScope(false); } @@ -2687,7 +2687,7 @@ LLVMRegister *LLVMCodeBuilder::createOp(const LLVMInstruction &ins, Compiler::St m_instructions.push_back(createdIns); for (size_t i = 0; i < args.size(); i++) - createdIns->args.push_back({ argTypes[i], static_cast(args[i]) }); + createdIns->args.push_back({ argTypes[i], dynamic_cast(args[i]) }); if (retType != Compiler::StaticType::Void) { auto ret = std::make_shared(retType); diff --git a/src/engine/internal/llvm/llvmconstantregister.h b/src/engine/internal/llvm/llvmconstantregister.h index c2be30f1..4d7beacc 100644 --- a/src/engine/internal/llvm/llvmconstantregister.h +++ b/src/engine/internal/llvm/llvmconstantregister.h @@ -10,16 +10,17 @@ namespace libscratchcpp { struct LLVMConstantRegister - : public LLVMRegisterBase - , public CompilerConstant + : public CompilerConstant + , public LLVMRegister { LLVMConstantRegister(Compiler::StaticType type, const Value &value) : - LLVMRegisterBase(), - CompilerConstant(type, value) + CompilerValue(type), + CompilerConstant(type, value), + LLVMRegister(type) { } - const Value &constValue() const override { return CompilerConstant::value(); } + const Value &constValue() const override final { return CompilerConstant::value(); } }; } // namespace libscratchcpp diff --git a/src/engine/internal/llvm/llvmregister.h b/src/engine/internal/llvm/llvmregister.h index 2c7bc7f5..3bd90cc8 100644 --- a/src/engine/internal/llvm/llvmregister.h +++ b/src/engine/internal/llvm/llvmregister.h @@ -2,7 +2,8 @@ #pragma once -#include "llvmregisterbase.h" +#include +#include namespace llvm { @@ -14,25 +15,24 @@ class Value; namespace libscratchcpp { -struct LLVMRegister - : public LLVMRegisterBase - , public CompilerValue +class LLVMInstruction; + +struct LLVMRegister : public virtual CompilerValue { LLVMRegister(Compiler::StaticType type) : - LLVMRegisterBase(), CompilerValue(type) { } - const Value &constValue() const override + virtual const Value &constValue() const { - if (isConst()) - return static_cast(static_cast(this))->value(); - else { - static const Value null = Value(); - return null; - } + static const Value null = Value(); + return null; } + + llvm::Value *value = nullptr; + bool isRawValue = false; + std::shared_ptr instruction; }; } // namespace libscratchcpp diff --git a/src/engine/internal/llvm/llvmregisterbase.h b/src/engine/internal/llvm/llvmregisterbase.h deleted file mode 100644 index 1551442e..00000000 --- a/src/engine/internal/llvm/llvmregisterbase.h +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -namespace llvm -{ - -class Value; - -} - -namespace libscratchcpp -{ - -class LLVMInstruction; - -struct LLVMRegisterBase -{ - virtual const Value &constValue() const = 0; - - llvm::Value *value = nullptr; - bool isRawValue = false; - std::shared_ptr instruction; -}; - -} // namespace libscratchcpp diff --git a/test/llvm/llvmcodebuilder_test.cpp b/test/llvm/llvmcodebuilder_test.cpp index cca67885..b0a0418a 100644 --- a/test/llvm/llvmcodebuilder_test.cpp +++ b/test/llvm/llvmcodebuilder_test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include