Skip to content

Commit 408404f

Browse files
committed
LLVMCodeBuilder: Implement local variables
1 parent ab25091 commit 408404f

File tree

6 files changed

+150
-0
lines changed

6 files changed

+150
-0
lines changed

src/dev/engine/internal/icodebuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ICodeBuilder
2424
virtual CompilerValue *addFunctionCallWithCtx(const std::string &functionName, Compiler::StaticType returnType, const Compiler::ArgTypes &argTypes, const Compiler::Args &args) = 0;
2525
virtual CompilerConstant *addConstValue(const Value &value) = 0;
2626
virtual CompilerValue *addLoopIndex() = 0;
27+
virtual CompilerValue *addLocalVariableValue(CompilerLocalVariable *variable) = 0;
2728
virtual CompilerValue *addVariableValue(Variable *variable) = 0;
2829
virtual CompilerValue *addListContents(List *list) = 0;
2930
virtual CompilerValue *addListItem(List *list, CompilerValue *index) = 0;
@@ -66,6 +67,9 @@ class ICodeBuilder
6667

6768
virtual CompilerValue *createSelect(CompilerValue *cond, CompilerValue *trueValue, CompilerValue *falseValue, Compiler::StaticType valueType) = 0;
6869

70+
virtual CompilerLocalVariable *createLocalVariable(Compiler::StaticType type) = 0;
71+
virtual void createLocalVariableWrite(CompilerLocalVariable *variable, CompilerValue *value) = 0;
72+
6973
virtual void createVariableWrite(Variable *variable, CompilerValue *value) = 0;
7074

7175
virtual void createListClear(List *list) = 0;

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

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <scratchcpp/variable.h>
1111
#include <scratchcpp/list.h>
1212
#include <scratchcpp/dev/compilerconstant.h>
13+
#include <scratchcpp/dev/compilerlocalvariable.h>
1314

1415
#include "llvmcodebuilder.h"
1516
#include "llvmexecutablecode.h"
@@ -511,6 +512,64 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
511512
break;
512513
}
513514

515+
case LLVMInstruction::Type::CreateLocalVariable: {
516+
assert(step.args.empty());
517+
llvm::Type *type = nullptr;
518+
519+
switch (step.functionReturnReg->type()) {
520+
case Compiler::StaticType::Number:
521+
type = m_builder.getDoubleTy();
522+
break;
523+
524+
case Compiler::StaticType::Bool:
525+
type = m_builder.getInt1Ty();
526+
break;
527+
528+
case Compiler::StaticType::String:
529+
std::cerr << "error: local variables do not support string type" << std::endl;
530+
break;
531+
532+
default:
533+
assert(false);
534+
break;
535+
}
536+
537+
step.functionReturnReg->value = m_builder.CreateAlloca(type);
538+
break;
539+
}
540+
541+
case LLVMInstruction::Type::WriteLocalVariable: {
542+
assert(step.args.size() == 2);
543+
const auto &arg1 = step.args[0];
544+
const auto &arg2 = step.args[1];
545+
llvm::Value *converted = castValue(arg2.second, arg2.first);
546+
m_builder.CreateStore(converted, arg1.second->value);
547+
break;
548+
}
549+
550+
case LLVMInstruction::Type::ReadLocalVariable: {
551+
assert(step.args.size() == 1);
552+
const auto &arg = step.args[0];
553+
llvm::Type *type = nullptr;
554+
555+
switch (step.functionReturnReg->type()) {
556+
case Compiler::StaticType::Number:
557+
type = m_builder.getDoubleTy();
558+
break;
559+
560+
case Compiler::StaticType::Bool:
561+
type = m_builder.getInt1Ty();
562+
break;
563+
564+
default:
565+
assert(false);
566+
break;
567+
}
568+
569+
step.functionReturnReg->value = m_builder.CreateLoad(type, arg.second->value);
570+
break;
571+
}
572+
514573
case LLVMInstruction::Type::WriteVariable: {
515574
assert(step.args.size() == 1);
516575
assert(m_variablePtrs.find(step.workVariable) != m_variablePtrs.cend());
@@ -1049,6 +1108,11 @@ CompilerValue *LLVMCodeBuilder::addLoopIndex()
10491108
return createOp(LLVMInstruction::Type::LoopIndex, Compiler::StaticType::Number, {}, {});
10501109
}
10511110

1111+
CompilerValue *LLVMCodeBuilder::addLocalVariableValue(CompilerLocalVariable *variable)
1112+
{
1113+
return createOp(LLVMInstruction::Type::ReadLocalVariable, variable->type(), variable->type(), { variable->ptr() });
1114+
}
1115+
10521116
CompilerValue *LLVMCodeBuilder::addVariableValue(Variable *variable)
10531117
{
10541118
LLVMInstruction ins(LLVMInstruction::Type::ReadVariable);
@@ -1256,6 +1320,19 @@ CompilerValue *LLVMCodeBuilder::createSelect(CompilerValue *cond, CompilerValue
12561320
return createOp(LLVMInstruction::Type::Select, valueType, { Compiler::StaticType::Bool, valueType, valueType }, { cond, trueValue, falseValue });
12571321
}
12581322

1323+
CompilerLocalVariable *LLVMCodeBuilder::createLocalVariable(Compiler::StaticType type)
1324+
{
1325+
CompilerValue *ptr = createOp(LLVMInstruction::Type::CreateLocalVariable, type);
1326+
auto var = std::make_shared<CompilerLocalVariable>(ptr);
1327+
m_localVars.push_back(var);
1328+
return var.get();
1329+
}
1330+
1331+
void LLVMCodeBuilder::createLocalVariableWrite(CompilerLocalVariable *variable, CompilerValue *value)
1332+
{
1333+
createOp(LLVMInstruction::Type::WriteLocalVariable, Compiler::StaticType::Void, variable->type(), { variable->ptr(), value });
1334+
}
1335+
12591336
void LLVMCodeBuilder::createVariableWrite(Variable *variable, CompilerValue *value)
12601337
{
12611338
LLVMInstruction ins(LLVMInstruction::Type::WriteVariable);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class LLVMCodeBuilder : public ICodeBuilder
3131
CompilerValue *addFunctionCallWithCtx(const std::string &functionName, Compiler::StaticType returnType, const Compiler::ArgTypes &argTypes, const Compiler::Args &args) override;
3232
CompilerConstant *addConstValue(const Value &value) override;
3333
CompilerValue *addLoopIndex() override;
34+
CompilerValue *addLocalVariableValue(CompilerLocalVariable *variable) override;
3435
CompilerValue *addVariableValue(Variable *variable) override;
3536
CompilerValue *addListContents(List *list) override;
3637
CompilerValue *addListItem(List *list, CompilerValue *index) override;
@@ -73,6 +74,9 @@ class LLVMCodeBuilder : public ICodeBuilder
7374

7475
CompilerValue *createSelect(CompilerValue *cond, CompilerValue *trueValue, CompilerValue *falseValue, Compiler::StaticType valueType) override;
7576

77+
CompilerLocalVariable *createLocalVariable(Compiler::StaticType type) override;
78+
void createLocalVariableWrite(CompilerLocalVariable *variable, CompilerValue *value) override;
79+
7680
void createVariableWrite(Variable *variable, CompilerValue *value) override;
7781

7882
void createListClear(List *list) override;
@@ -194,6 +198,7 @@ class LLVMCodeBuilder : public ICodeBuilder
194198

195199
std::vector<LLVMInstruction> m_instructions;
196200
std::vector<std::shared_ptr<LLVMRegister>> m_regs;
201+
std::vector<std::shared_ptr<CompilerLocalVariable>> m_localVars;
197202
bool m_defaultWarp = false;
198203
bool m_warp = false;
199204

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ struct LLVMInstruction
4343
Exp,
4444
Exp10,
4545
Select,
46+
CreateLocalVariable,
47+
WriteLocalVariable,
48+
ReadLocalVariable,
4649
WriteVariable,
4750
ReadVariable,
4851
ClearList,

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,63 @@ TEST_F(LLVMCodeBuilderTest, Exp10)
15191519
runUnaryNumOpTest(OpType::Exp10, nan, 1.0);
15201520
}
15211521

1522+
TEST_F(LLVMCodeBuilderTest, LocalVariables)
1523+
{
1524+
EngineMock engine;
1525+
Stage stage;
1526+
Sprite sprite;
1527+
sprite.setEngine(&engine);
1528+
EXPECT_CALL(engine, stage()).WillRepeatedly(Return(&stage));
1529+
1530+
createBuilder(&sprite, true);
1531+
1532+
CompilerLocalVariable *var1 = m_builder->createLocalVariable(Compiler::StaticType::Number);
1533+
CompilerLocalVariable *var2 = m_builder->createLocalVariable(Compiler::StaticType::Number);
1534+
CompilerLocalVariable *var3 = m_builder->createLocalVariable(Compiler::StaticType::Bool);
1535+
CompilerLocalVariable *var4 = m_builder->createLocalVariable(Compiler::StaticType::Bool);
1536+
1537+
CompilerValue *v = m_builder->addConstValue(5);
1538+
m_builder->createLocalVariableWrite(var1, v);
1539+
1540+
v = m_builder->addConstValue(-23.5);
1541+
v = callConstFuncForType(ValueType::Number, v);
1542+
m_builder->createLocalVariableWrite(var2, v);
1543+
1544+
v = m_builder->addConstValue(5.2);
1545+
v = callConstFuncForType(ValueType::Number, v);
1546+
m_builder->createLocalVariableWrite(var2, v);
1547+
1548+
v = m_builder->addConstValue(false);
1549+
m_builder->createLocalVariableWrite(var3, v);
1550+
1551+
v = m_builder->addConstValue(true);
1552+
m_builder->createLocalVariableWrite(var3, v);
1553+
1554+
v = m_builder->addConstValue(false);
1555+
v = callConstFuncForType(ValueType::Bool, v);
1556+
m_builder->createLocalVariableWrite(var4, v);
1557+
1558+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }, { m_builder->addLocalVariableValue(var1) });
1559+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }, { m_builder->addLocalVariableValue(var2) });
1560+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }, { m_builder->addLocalVariableValue(var3) });
1561+
m_builder->addFunctionCall("test_print_string", Compiler::StaticType::Void, { Compiler::StaticType::String }, { m_builder->addLocalVariableValue(var4) });
1562+
1563+
static const std::string expected =
1564+
"5\n"
1565+
"5.2\n"
1566+
"true\n"
1567+
"false\n";
1568+
1569+
auto code = m_builder->finalize();
1570+
Script script(&sprite, nullptr, nullptr);
1571+
script.setCode(code);
1572+
Thread thread(&sprite, nullptr, &script);
1573+
auto ctx = code->createExecutionContext(&thread);
1574+
testing::internal::CaptureStdout();
1575+
code->run(ctx.get());
1576+
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
1577+
}
1578+
15221579
TEST_F(LLVMCodeBuilderTest, WriteVariable)
15231580
{
15241581
EngineMock engine;

test/mocks/codebuildermock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class CodeBuilderMock : public ICodeBuilder
1414
MOCK_METHOD(CompilerValue *, addFunctionCallWithCtx, (const std::string &, Compiler::StaticType, const Compiler::ArgTypes &, const Compiler::Args &), (override));
1515
MOCK_METHOD(CompilerConstant *, addConstValue, (const Value &), (override));
1616
MOCK_METHOD(CompilerValue *, addLoopIndex, (), (override));
17+
MOCK_METHOD(CompilerValue *, addLocalVariableValue, (CompilerLocalVariable *), (override));
1718
MOCK_METHOD(CompilerValue *, addVariableValue, (Variable *), (override));
1819
MOCK_METHOD(CompilerValue *, addListContents, (List *), (override));
1920
MOCK_METHOD(CompilerValue *, addListItem, (List *, CompilerValue *), (override));
@@ -56,6 +57,9 @@ class CodeBuilderMock : public ICodeBuilder
5657

5758
MOCK_METHOD(CompilerValue *, createSelect, (CompilerValue *, CompilerValue *, CompilerValue *, Compiler::StaticType), (override));
5859

60+
MOCK_METHOD(CompilerLocalVariable *, createLocalVariable, (Compiler::StaticType), (override));
61+
MOCK_METHOD(void, createLocalVariableWrite, (CompilerLocalVariable *, CompilerValue *), (override));
62+
5963
MOCK_METHOD(void, createVariableWrite, (Variable *, CompilerValue *), (override));
6064

6165
MOCK_METHOD(void, createListClear, (List *), (override));

0 commit comments

Comments
 (0)