Skip to content

Commit 6a74cf1

Browse files
committed
Store const values in LLVMExecutableCode
1 parent 73ad410 commit 6a74cf1

File tree

5 files changed

+90
-9
lines changed

5 files changed

+90
-9
lines changed

src/dev/engine/internal/llvmexecutablecode.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// SPDX-License-Identifier: Apache-2.0
22

33
#include <scratchcpp/dev/executioncontext.h>
4+
#include <scratchcpp/value_functions.h>
45
#include <llvm/Support/Error.h>
56
#include <iostream>
67

@@ -9,7 +10,7 @@
910

1011
using namespace libscratchcpp;
1112

12-
LLVMExecutableCode::LLVMExecutableCode(std::unique_ptr<llvm::Module> module) :
13+
LLVMExecutableCode::LLVMExecutableCode(std::unique_ptr<llvm::Module> module, std::vector<std::unique_ptr<ValueData>> &constValues) :
1314
m_ctx(std::make_unique<llvm::LLVMContext>()),
1415
m_jit(llvm::orc::LLJITBuilder().create())
1516
{
@@ -45,6 +46,19 @@ LLVMExecutableCode::LLVMExecutableCode(std::unique_ptr<llvm::Module> module) :
4546

4647
i++;
4748
}
49+
50+
// Move const value pointers (transfer ownership)
51+
for (auto &v : constValues)
52+
m_constValues.push_back(std::move(v));
53+
54+
constValues.clear();
55+
}
56+
57+
LLVMExecutableCode::~LLVMExecutableCode()
58+
{
59+
// Free memory used by const values
60+
for (const auto &v : m_constValues)
61+
value_free(v.get());
4862
}
4963

5064
void LLVMExecutableCode::run(ExecutionContext *context)

src/dev/engine/internal/llvmexecutablecode.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#pragma once
44

55
#include <scratchcpp/dev/executablecode.h>
6+
#include <scratchcpp/valuedata.h>
67
#include <llvm/IR/LLVMContext.h>
78
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
89

@@ -15,7 +16,8 @@ class LLVMExecutionContext;
1516
class LLVMExecutableCode : public ExecutableCode
1617
{
1718
public:
18-
LLVMExecutableCode(std::unique_ptr<llvm::Module> module);
19+
LLVMExecutableCode(std::unique_ptr<llvm::Module> module, std::vector<std::unique_ptr<libscratchcpp::ValueData>> &constValues);
20+
~LLVMExecutableCode();
1921

2022
void run(ExecutionContext *context) override;
2123
void kill(libscratchcpp::ExecutionContext *context) override;
@@ -37,6 +39,7 @@ class LLVMExecutableCode : public ExecutableCode
3739
llvm::Expected<std::unique_ptr<llvm::orc::LLJIT>> m_jit;
3840

3941
std::vector<FunctionType> m_functions;
42+
std::vector<std::unique_ptr<ValueData>> m_constValues;
4043
};
4144

4245
} // namespace libscratchcpp

test/dev/llvm/llvmexecutablecode_test.cpp

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <scratchcpp/target.h>
2+
#include <scratchcpp/value_functions.h>
23
#include <dev/engine/internal/llvmexecutablecode.h>
34
#include <dev/engine/internal/llvmexecutioncontext.h>
45
#include <llvm/Support/TargetSelect.h>
@@ -52,6 +53,13 @@ class LLVMExecutableCodeTest : public testing::Test
5253
m_builder->CreateCall(func, { mockPtr, mainFunc->getArg(0) });
5354
}
5455

56+
void addTestPrintFunction(llvm::Value *arg1, llvm::Value *arg2)
57+
{
58+
auto ptrType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0);
59+
auto func = m_module->getOrInsertFunction("test_print_function", llvm::FunctionType::get(m_builder->getVoidTy(), { ptrType, ptrType }, false));
60+
m_builder->CreateCall(func, { arg1, arg2 });
61+
}
62+
5563
llvm::LLVMContext m_ctx;
5664
std::unique_ptr<llvm::Module> m_module;
5765
std::unique_ptr<llvm::IRBuilder<>> m_builder;
@@ -62,7 +70,8 @@ class LLVMExecutableCodeTest : public testing::Test
6270
TEST_F(LLVMExecutableCodeTest, NoFunctions)
6371
{
6472
LLVMExecutionContext ctx(&m_target);
65-
LLVMExecutableCode code(std::move(m_module));
73+
std::vector<std::unique_ptr<ValueData>> constValues;
74+
LLVMExecutableCode code(std::move(m_module), constValues);
6675
ASSERT_TRUE(code.isFinished(&ctx));
6776

6877
code.run(&ctx);
@@ -82,7 +91,8 @@ TEST_F(LLVMExecutableCodeTest, SingleFunction)
8291
endFunction(0);
8392

8493
LLVMExecutionContext ctx(&m_target);
85-
LLVMExecutableCode code(std::move(m_module));
94+
std::vector<std::unique_ptr<ValueData>> constValues;
95+
LLVMExecutableCode code(std::move(m_module), constValues);
8696
ASSERT_FALSE(code.isFinished(&ctx));
8797

8898
EXPECT_CALL(m_mock, f(&m_target));
@@ -114,7 +124,8 @@ TEST_F(LLVMExecutableCodeTest, MultipleFunctions)
114124
}
115125

116126
LLVMExecutionContext ctx(&m_target);
117-
LLVMExecutableCode code(std::move(m_module));
127+
std::vector<std::unique_ptr<ValueData>> constValues;
128+
LLVMExecutableCode code(std::move(m_module), constValues);
118129
ASSERT_FALSE(code.isFinished(&ctx));
119130

120131
for (int i = 0; i < count; i++) {
@@ -125,3 +136,36 @@ TEST_F(LLVMExecutableCodeTest, MultipleFunctions)
125136

126137
ASSERT_TRUE(code.isFinished(&ctx));
127138
}
139+
140+
TEST_F(LLVMExecutableCodeTest, ConstValues)
141+
{
142+
beginFunction(0);
143+
std::vector<std::unique_ptr<ValueData>> constValues;
144+
145+
for (int i = 0; i < 2; i++) {
146+
std::unique_ptr<ValueData> value = std::make_unique<ValueData>();
147+
value_init(value.get());
148+
value_assign_int(value.get(), i + 1);
149+
constValues.push_back(std::move(value));
150+
}
151+
152+
auto ptrType = llvm::PointerType::get(llvm::Type::getInt8Ty(m_ctx), 0);
153+
llvm::Value *intAddress = m_builder->getInt64((uintptr_t)constValues[0].get());
154+
llvm::Value *ptr1 = m_builder->CreateIntToPtr(intAddress, ptrType);
155+
156+
intAddress = m_builder->getInt64((uintptr_t)constValues[1].get());
157+
llvm::Value *ptr2 = m_builder->CreateIntToPtr(intAddress, ptrType);
158+
159+
addTestPrintFunction(ptr1, ptr2);
160+
endFunction(0);
161+
162+
LLVMExecutionContext ctx(&m_target);
163+
LLVMExecutableCode code(std::move(m_module), constValues);
164+
ASSERT_TRUE(constValues.empty());
165+
ASSERT_FALSE(code.isFinished(&ctx));
166+
167+
testing::internal::CaptureStdout();
168+
code.run(&ctx);
169+
ASSERT_EQ(testing::internal::GetCapturedStdout(), "1 2\n");
170+
ASSERT_TRUE(code.isFinished(&ctx));
171+
}

test/dev/llvm/testfunctions.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
#include <scratchcpp/value_functions.h>
2+
#include <iostream>
3+
4+
#include "testfunctions.h"
15
#include "testmock.h"
26

37
using namespace libscratchcpp;
48

5-
extern "C" void test_function(TestMock *mock, Target *target)
9+
extern "C"
610
{
7-
if (mock)
8-
mock->f(target);
11+
void test_function(TestMock *mock, Target *target)
12+
{
13+
if (mock)
14+
mock->f(target);
15+
}
16+
17+
void test_print_function(ValueData *arg1, ValueData *arg2)
18+
{
19+
std::string s1, s2;
20+
value_toString(arg1, &s1);
21+
value_toString(arg2, &s2);
22+
std::cout << s1 << " " << s2 << std::endl;
23+
}
924
}

test/dev/llvm/testfunctions.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ namespace libscratchcpp
55

66
class TestMock;
77
class Target;
8+
class ValueData;
89

9-
extern "C" void test_function(TestMock *mock, Target *target);
10+
extern "C"
11+
{
12+
void test_function(TestMock *mock, Target *target);
13+
void test_print_function(ValueData *arg1, ValueData *arg2);
14+
}
1015

1116
} // namespace libscratchcpp

0 commit comments

Comments
 (0)