Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/engine/internal/llvm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ target_sources(scratchcpp
llvmtypes.cpp
llvmtypes.h
llvmfunctions.cpp
llvmloopscope.h
llvmcompilercontext.cpp
llvmcompilercontext.h
llvmexecutablecode.cpp
Expand Down
524 changes: 446 additions & 78 deletions src/engine/internal/llvm/llvmcodebuilder.cpp

Large diffs are not rendered by default.

22 changes: 19 additions & 3 deletions src/engine/internal/llvm/llvmcodebuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace libscratchcpp

class LLVMCompilerContext;
class LLVMConstantRegister;
class LLVMLoopScope;

class LLVMCodeBuilder : public ICodeBuilder
{
Expand Down Expand Up @@ -119,22 +120,24 @@ class LLVMCodeBuilder : public ICodeBuilder
void createListMap();
void pushScopeLevel();
void popScopeLevel();
void pushLoopScope(bool buildPhase);
void popLoopScope();

std::string getMainFunctionName(BlockPrototype *procedurePrototype);
std::string getResumeFunctionName(BlockPrototype *procedurePrototype);
llvm::FunctionType *getMainFunctionType(BlockPrototype *procedurePrototype);
llvm::Function *getOrCreateFunction(const std::string &name, llvm::FunctionType *type);
void verifyFunction(llvm::Function *func);

LLVMRegister *addReg(std::shared_ptr<LLVMRegister> reg);
LLVMRegister *addReg(std::shared_ptr<LLVMRegister> reg, std::shared_ptr<LLVMInstruction> ins);

llvm::Value *addAlloca(llvm::Type *type);
void freeLater(llvm::Value *value);
void freeScopeHeap();
llvm::Value *castValue(LLVMRegister *reg, Compiler::StaticType targetType);
llvm::Value *castRawValue(LLVMRegister *reg, Compiler::StaticType targetType);
llvm::Constant *castConstValue(const Value &value, Compiler::StaticType targetType);
Compiler::StaticType optimizeRegisterType(LLVMRegister *reg);
Compiler::StaticType optimizeRegisterType(LLVMRegister *reg) const;
llvm::Type *getType(Compiler::StaticType type);
Compiler::StaticType getProcedureArgType(BlockPrototype::ArgType type);
llvm::Value *isNaN(llvm::Value *num);
Expand All @@ -146,9 +149,15 @@ class LLVMCodeBuilder : public ICodeBuilder
void reloadVariables(llvm::Value *targetVariables);
void reloadLists();
void updateListDataPtr(const LLVMListPtr &listPtr);
bool isVarOrListTypeSafe(std::shared_ptr<LLVMInstruction> ins, Compiler::StaticType expectedType) const;
bool isVarOrListTypeSafe(std::shared_ptr<LLVMInstruction> ins, Compiler::StaticType expectedType, std::unordered_set<LLVMInstruction *> &log, int &c) const;
bool isVarOrListWriteResultTypeSafe(std::shared_ptr<LLVMInstruction> ins, Compiler::StaticType expectedType, bool ignoreSavedType, std::unordered_set<LLVMInstruction *> &log, int &c) const;

LLVMRegister *createOp(LLVMInstruction::Type type, Compiler::StaticType retType, Compiler::StaticType argType, const Compiler::Args &args);
LLVMRegister *createOp(LLVMInstruction::Type type, Compiler::StaticType retType, const Compiler::ArgTypes &argTypes = {}, const Compiler::Args &args = {});
LLVMRegister *createOp(const LLVMInstruction &ins, Compiler::StaticType retType, Compiler::StaticType argType, const Compiler::Args &args);
LLVMRegister *createOp(const LLVMInstruction &ins, Compiler::StaticType retType, const Compiler::ArgTypes &argTypes = {}, const Compiler::Args &args = {});
std::shared_ptr<LLVMLoopScope> currentLoopScope() const;

void createValueStore(LLVMRegister *reg, llvm::Value *targetPtr, Compiler::StaticType sourceType, Compiler::StaticType targetType);
void createReusedValueStore(LLVMRegister *reg, llvm::Value *targetPtr, Compiler::StaticType sourceType, Compiler::StaticType targetType);
Expand Down Expand Up @@ -215,14 +224,21 @@ class LLVMCodeBuilder : public ICodeBuilder
llvm::StructType *m_valueDataType = nullptr;
llvm::FunctionType *m_resumeFuncType = nullptr;

std::vector<LLVMInstruction> m_instructions;
std::vector<std::shared_ptr<LLVMInstruction>> m_instructions;
std::vector<std::shared_ptr<LLVMRegister>> m_regs;
std::vector<std::shared_ptr<CompilerLocalVariable>> m_localVars;
BlockPrototype *m_procedurePrototype = nullptr;
bool m_defaultWarp = false;
bool m_warp = false;
int m_defaultArgCount = 0;

long m_loopScope = -1; // index
std::vector<std::shared_ptr<LLVMLoopScope>> m_loopScopes;
long m_loopScopeCounter = 0; // replacement for m_loopScopes size in build phase
std::vector<long> m_loopScopeTree;
bool m_loopCondition = false; // whether we're currently compiling a loop condition
std::vector<std::shared_ptr<LLVMInstruction>> m_variableInstructions;
std::vector<std::shared_ptr<LLVMInstruction>> m_listInstructions;
std::vector<std::vector<llvm::Value *>> m_heap; // scopes

std::shared_ptr<ExecutableCode> m_output;
Expand Down
9 changes: 7 additions & 2 deletions src/engine/internal/llvm/llvminstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace libscratchcpp
{

class BlockPrototype;
class LLVMLoopScope;

struct LLVMInstruction
{
Expand Down Expand Up @@ -77,8 +78,10 @@ struct LLVMInstruction
ProcedureArg
};

LLVMInstruction(Type type) :
type(type)
LLVMInstruction(Type type, std::shared_ptr<LLVMLoopScope> loopScope, bool loopCondition) :
type(type),
loopScope(loopScope),
loopCondition(loopCondition)
{
}

Expand All @@ -92,6 +95,8 @@ struct LLVMInstruction
List *workList = nullptr; // for lists
BlockPrototype *procedurePrototype = nullptr;
size_t procedureArgIndex = 0;
std::shared_ptr<LLVMLoopScope> loopScope;
bool loopCondition = false; // whether the instruction is part of a loop condition
};

} // namespace libscratchcpp
7 changes: 7 additions & 0 deletions src/engine/internal/llvm/llvmlistptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <scratchcpp/compiler.h>
#include <unordered_map>

namespace llvm
{
Expand All @@ -14,6 +15,9 @@ class Value;
namespace libscratchcpp
{

class LLVMLoopScope;
class LLVMInstruction;

struct LLVMListPtr
{
llvm::Value *ptr = nullptr;
Expand All @@ -22,6 +26,9 @@ struct LLVMListPtr
llvm::Value *allocatedSizePtr = nullptr;
llvm::Value *dataPtrDirty = nullptr;
Compiler::StaticType type = Compiler::StaticType::Unknown;

// Used in build phase to check the type safety of lists in loops
std::unordered_map<std::shared_ptr<LLVMLoopScope>, std::vector<std::shared_ptr<LLVMInstruction>>> loopListWrites; // loop scope, write instructions
};

} // namespace libscratchcpp
18 changes: 18 additions & 0 deletions src/engine/internal/llvm/llvmloopscope.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <vector>
#include <memory>

namespace libscratchcpp
{

struct LLVMLoopScope
{
bool containsYield = false;
std::shared_ptr<LLVMLoopScope> parentScope;
std::vector<std::shared_ptr<LLVMLoopScope>> childScopes;
};

} // namespace libscratchcpp
3 changes: 3 additions & 0 deletions src/engine/internal/llvm/llvmregisterbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ class Value;
namespace libscratchcpp
{

class LLVMInstruction;

struct LLVMRegisterBase
{
virtual const Value &constValue() const = 0;

llvm::Value *value = nullptr;
bool isRawValue = false;
std::shared_ptr<LLVMInstruction> instruction;
};

} // namespace libscratchcpp
7 changes: 7 additions & 0 deletions src/engine/internal/llvm/llvmvariableptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <scratchcpp/compiler.h>
#include <unordered_map>

namespace llvm
{
Expand All @@ -14,13 +15,19 @@ class Value;
namespace libscratchcpp
{

class LLVMLoopScope;
class LLVMInstruction;

struct LLVMVariablePtr
{
llvm::Value *stackPtr = nullptr;
llvm::Value *heapPtr = nullptr;
Compiler::StaticType type = Compiler::StaticType::Unknown;
bool onStack = false;
bool changed = false;

// Used in build phase to check the type safety of variables in loops
std::unordered_map<std::shared_ptr<LLVMLoopScope>, std::vector<std::shared_ptr<LLVMInstruction>>> loopVariableWrites; // loop scope, write instructions
};

} // namespace libscratchcpp
Loading
Loading