Skip to content

Commit bdd078b

Browse files
committed
LLVMCodeBuilder: Initial list limplementation
1 parent d1cfb5d commit bdd078b

File tree

12 files changed

+79
-15
lines changed

12 files changed

+79
-15
lines changed

src/dev/engine/internal/llvm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ target_sources(scratchcpp
99
llvmcoroutine.cpp
1010
llvmcoroutine.h
1111
llvmvariableptr.h
12+
llvmlistptr.h
1213
llvmprocedure.h
1314
llvmtypes.cpp
1415
llvmtypes.h

src/dev/engine/internal/llvm/llvmcodebuilder.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <scratchcpp/stage.h>
99
#include <scratchcpp/iengine.h>
1010
#include <scratchcpp/variable.h>
11+
#include <scratchcpp/list.h>
1112

1213
#include "llvmcodebuilder.h"
1314
#include "llvmexecutablecode.h"
@@ -56,12 +57,13 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
5657
m_builder.setFastMathFlags(fmf);
5758

5859
// Create function
59-
// void *f(Target *, ValueData **)
60+
// void *f(Target *, ValueData **, List **)
6061
llvm::PointerType *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0);
61-
llvm::FunctionType *funcType = llvm::FunctionType::get(pointerType, { pointerType, pointerType }, false);
62+
llvm::FunctionType *funcType = llvm::FunctionType::get(pointerType, { pointerType, pointerType, pointerType }, false);
6263
llvm::Function *func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "f", m_module.get());
6364
llvm::Value *targetPtr = func->getArg(0);
6465
llvm::Value *targetVariables = func->getArg(1);
66+
llvm::Value *targetLists = func->getArg(2);
6567

6668
llvm::BasicBlock *entry = llvm::BasicBlock::Create(m_ctx, "entry", func);
6769
m_builder.SetInsertPoint(entry);
@@ -92,6 +94,10 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
9294
m_scopeVariables.clear();
9395
m_scopeVariables.push_back({});
9496

97+
// Create list pointers
98+
for (auto &[list, listPtr] : m_listPtrs)
99+
listPtr.ptr = getListPtr(targetLists, list);
100+
95101
// Execute recorded steps
96102
for (const LLVMInstruction &step : m_instructions) {
97103
switch (step.type) {
@@ -1315,6 +1321,22 @@ llvm::Value *LLVMCodeBuilder::getVariablePtr(llvm::Value *targetVariables, Varia
13151321
return m_builder.CreateIntToPtr(addr, m_valueDataType->getPointerTo());
13161322
}
13171323

1324+
llvm::Value *LLVMCodeBuilder::getListPtr(llvm::Value *targetLists, List *list)
1325+
{
1326+
if (!m_target->isStage() && list->target() == m_target) {
1327+
// If this is a local sprite list, use the list array at runtime (for clones)
1328+
assert(m_targetListMap.find(list) != m_targetListMap.cend());
1329+
const size_t index = m_targetListMap[list];
1330+
auto pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0);
1331+
llvm::Value *ptr = m_builder.CreateGEP(pointerType, targetLists, m_builder.getInt64(index));
1332+
return m_builder.CreateLoad(pointerType, ptr);
1333+
}
1334+
1335+
// Otherwise create a raw pointer at compile time
1336+
llvm::Value *addr = m_builder.getInt64((uintptr_t)list);
1337+
return m_builder.CreateIntToPtr(addr, m_valueDataType->getPointerTo());
1338+
}
1339+
13181340
void LLVMCodeBuilder::syncVariables(llvm::Value *targetVariables)
13191341
{
13201342
// Copy stack variables to the actual variables

src/dev/engine/internal/llvm/llvmcodebuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "llvminstruction.h"
1212
#include "llvmcoroutine.h"
1313
#include "llvmvariableptr.h"
14+
#include "llvmlistptr.h"
1415

1516
namespace libscratchcpp
1617
{
@@ -99,6 +100,7 @@ class LLVMCodeBuilder : public ICodeBuilder
99100
llvm::Value *removeNaN(llvm::Value *num);
100101

101102
llvm::Value *getVariablePtr(llvm::Value *targetVariables, Variable *variable);
103+
llvm::Value *getListPtr(llvm::Value *targetLists, List *list);
102104
void syncVariables(llvm::Value *targetVariables);
103105
void reloadVariables(llvm::Value *targetVariables);
104106

@@ -132,10 +134,14 @@ class LLVMCodeBuilder : public ICodeBuilder
132134
llvm::FunctionCallee resolve_strcasecmp();
133135

134136
Target *m_target = nullptr;
137+
135138
std::unordered_map<Variable *, size_t> m_targetVariableMap;
136139
std::unordered_map<Variable *, LLVMVariablePtr> m_variablePtrs;
137140
std::vector<std::unordered_map<LLVMVariablePtr *, Compiler::StaticType>> m_scopeVariables;
138141

142+
std::unordered_map<List *, size_t> m_targetListMap;
143+
std::unordered_map<List *, LLVMListPtr> m_listPtrs;
144+
139145
std::string m_id;
140146
llvm::LLVMContext m_ctx;
141147
std::unique_ptr<llvm::Module> m_module;

src/dev/engine/internal/llvm/llvmexecutablecode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void LLVMExecutableCode::run(ExecutionContext *context)
5555
ctx->setFinished(done);
5656
} else {
5757
Target *target = ctx->target();
58-
void *handle = m_mainFunction(target, target->variableData());
58+
void *handle = m_mainFunction(target, target->variableData(), target->listData());
5959

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

src/dev/engine/internal/llvm/llvmexecutablecode.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace libscratchcpp
1111
{
1212

1313
class Target;
14+
class List;
1415
class LLVMExecutionContext;
1516

1617
class LLVMExecutableCode : public ExecutableCode
@@ -32,7 +33,7 @@ class LLVMExecutableCode : public ExecutableCode
3233
private:
3334
uint64_t lookupFunction(const std::string &name);
3435

35-
using MainFunctionType = void *(*)(Target *, ValueData **);
36+
using MainFunctionType = void *(*)(Target *, ValueData **, List **);
3637
using ResumeFunctionType = bool (*)(void *);
3738

3839
static LLVMExecutionContext *getContext(ExecutionContext *context);

src/dev/engine/internal/llvm/llvminstruction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ struct LLVMInstruction
6363
std::vector<std::pair<Compiler::StaticType, LLVMRegisterPtr>> args; // target type, register
6464
LLVMRegisterPtr functionReturnReg;
6565
Variable *workVariable = nullptr; // for variables
66+
List *workList = nullptr; // for lists
6667
};
6768

6869
} // namespace libscratchcpp
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
3+
#pragma once
4+
5+
#include <scratchcpp/dev/compiler.h>
6+
7+
namespace llvm
8+
{
9+
10+
class Value;
11+
12+
}
13+
14+
namespace libscratchcpp
15+
{
16+
17+
struct LLVMListPtr
18+
{
19+
llvm::Value *ptr = nullptr;
20+
Compiler::StaticType type = Compiler::StaticType::Unknown;
21+
};
22+
23+
} // namespace libscratchcpp

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class LLVMCodeBuilderTest : public testing::Test
2020
public:
2121
void SetUp() override
2222
{
23-
test_function(nullptr, nullptr); // force dependency
23+
test_function(nullptr, nullptr, nullptr, nullptr); // force dependency
2424
}
2525

2626
void createBuilder(Target *target, bool warp) { m_builder = std::make_unique<LLVMCodeBuilder>(target, "test", warp); }

test/dev/llvm/llvmexecutablecode_test.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include <scratchcpp/target.h>
22
#include <scratchcpp/value_functions.h>
3+
#include <scratchcpp/variable.h>
4+
#include <scratchcpp/list.h>
35
#include <dev/engine/internal/llvm/llvmexecutablecode.h>
46
#include <dev/engine/internal/llvm/llvmexecutioncontext.h>
57
#include <llvm/Support/TargetSelect.h>
@@ -18,7 +20,7 @@ class LLVMExecutableCodeTest : public testing::Test
1820
{
1921
m_module = std::make_unique<llvm::Module>("test", m_ctx);
2022
m_builder = std::make_unique<llvm::IRBuilder<>>(m_ctx);
21-
test_function(nullptr, nullptr); // force dependency
23+
test_function(nullptr, nullptr, nullptr, nullptr); // force dependency
2224

2325
llvm::InitializeNativeTarget();
2426
llvm::InitializeNativeTargetAsmPrinter();
@@ -29,7 +31,7 @@ class LLVMExecutableCodeTest : public testing::Test
2931

3032
llvm::Function *beginMainFunction()
3133
{
32-
// void *f(Target *, ValueData **, ValueData **)
34+
// void *f(Target *, ValueData **, List **)
3335
llvm::Type *pointerType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0);
3436
llvm::FunctionType *funcType = llvm::FunctionType::get(pointerType, { pointerType, pointerType, pointerType }, false);
3537
llvm::Function *func = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "f", m_module.get());
@@ -55,12 +57,12 @@ class LLVMExecutableCodeTest : public testing::Test
5557
void addTestFunction(llvm::Function *mainFunc)
5658
{
5759
auto ptrType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0);
58-
auto func = m_module->getOrInsertFunction("test_function", llvm::FunctionType::get(m_builder->getVoidTy(), { ptrType, ptrType }, false));
60+
auto func = m_module->getOrInsertFunction("test_function", llvm::FunctionType::get(m_builder->getVoidTy(), { ptrType, ptrType, ptrType, ptrType }, false));
5961

6062
llvm::Constant *mockInt = llvm::ConstantInt::get(llvm::Type::getInt64Ty(m_ctx), (uintptr_t)&m_mock, false);
6163
llvm::Constant *mockPtr = llvm::ConstantExpr::getIntToPtr(mockInt, ptrType);
6264

63-
m_builder->CreateCall(func, { mockPtr, mainFunc->getArg(0) });
65+
m_builder->CreateCall(func, { mockPtr, mainFunc->getArg(0), mainFunc->getArg(1), mainFunc->getArg(2) });
6466
}
6567

6668
void addTestPrintFunction(llvm::Value *arg1, llvm::Value *arg2)
@@ -94,6 +96,9 @@ TEST_F(LLVMExecutableCodeTest, CreateExecutionContext)
9496

9597
TEST_F(LLVMExecutableCodeTest, MainFunction)
9698
{
99+
m_target.addVariable(std::make_shared<Variable>("", ""));
100+
m_target.addList(std::make_shared<List>("", ""));
101+
97102
auto f = beginMainFunction();
98103
addTestFunction(f);
99104
endFunction(nullPointer());
@@ -105,7 +110,7 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
105110
auto ctx = code.createExecutionContext(&m_target);
106111
ASSERT_FALSE(code.isFinished(ctx.get()));
107112

108-
EXPECT_CALL(m_mock, f(&m_target));
113+
EXPECT_CALL(m_mock, f(&m_target, m_target.variableData(), m_target.listData()));
109114
code.run(ctx.get());
110115
ASSERT_TRUE(code.isFinished(ctx.get()));
111116

@@ -124,11 +129,13 @@ TEST_F(LLVMExecutableCodeTest, MainFunction)
124129

125130
// Test with another context
126131
Target anotherTarget;
132+
anotherTarget.addVariable(std::make_shared<Variable>("", ""));
133+
anotherTarget.addList(std::make_shared<List>("", ""));
127134
auto anotherCtx = code.createExecutionContext(&anotherTarget);
128135
ASSERT_FALSE(code.isFinished(anotherCtx.get()));
129136
ASSERT_TRUE(code.isFinished(ctx.get()));
130137

131-
EXPECT_CALL(m_mock, f(&anotherTarget));
138+
EXPECT_CALL(m_mock, f(&anotherTarget, anotherTarget.variableData(), anotherTarget.listData()));
132139
code.run(anotherCtx.get());
133140
ASSERT_TRUE(code.isFinished(anotherCtx.get()));
134141
ASSERT_TRUE(code.isFinished(ctx.get()));

test/dev/llvm/testfunctions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ static int counter = 0;
1111

1212
extern "C"
1313
{
14-
void test_function(TestMock *mock, Target *target)
14+
void test_function(TestMock *mock, Target *target, ValueData **varData, List **listData)
1515
{
1616
if (mock)
17-
mock->f(target);
17+
mock->f(target, varData, listData);
1818
}
1919

2020
void test_print_function(ValueData *arg1, ValueData *arg2)

0 commit comments

Comments
 (0)