Skip to content

Commit 59daa77

Browse files
committed
LLVMCodeBuilder: Add createStop() method
1 parent d2200b9 commit 59daa77

File tree

6 files changed

+93
-1
lines changed

6 files changed

+93
-1
lines changed

src/dev/engine/internal/icodebuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class ICodeBuilder
8181
virtual void endLoop() = 0;
8282

8383
virtual void yield() = 0;
84+
85+
virtual void createStop() = 0;
8486
};
8587

8688
} // namespace libscratchcpp

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
6868
llvm::Value *targetLists = func->getArg(3);
6969

7070
llvm::BasicBlock *entry = llvm::BasicBlock::Create(m_ctx, "entry", func);
71+
llvm::BasicBlock *endBranch = llvm::BasicBlock::Create(m_ctx, "end", func);
7172
m_builder.SetInsertPoint(entry);
7273

7374
// Init coroutine
@@ -898,9 +899,19 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
898899
popScopeLevel();
899900
break;
900901
}
902+
903+
case LLVMInstruction::Type::Stop: {
904+
m_builder.CreateBr(endBranch);
905+
llvm::BasicBlock *nextBranch = llvm::BasicBlock::Create(m_ctx, "", func);
906+
m_builder.SetInsertPoint(nextBranch);
907+
break;
908+
}
901909
}
902910
}
903911

912+
m_builder.CreateBr(endBranch);
913+
914+
m_builder.SetInsertPoint(endBranch);
904915
freeHeap();
905916
syncVariables(targetVariables);
906917

@@ -1283,6 +1294,11 @@ void LLVMCodeBuilder::yield()
12831294
m_instructions.push_back({ LLVMInstruction::Type::Yield });
12841295
}
12851296

1297+
void LLVMCodeBuilder::createStop()
1298+
{
1299+
m_instructions.push_back({ LLVMInstruction::Type::Stop });
1300+
}
1301+
12861302
void LLVMCodeBuilder::initTypes()
12871303
{
12881304
m_valueDataType = LLVMTypes::createValueDataType(&m_builder);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class LLVMCodeBuilder : public ICodeBuilder
8989

9090
void yield() override;
9191

92+
void createStop() override;
93+
9294
private:
9395
enum class Comparison
9496
{

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ struct LLVMInstruction
6161
BeginWhileLoop,
6262
BeginRepeatUntilLoop,
6363
BeginLoopCondition,
64-
EndLoop
64+
EndLoop,
65+
Stop
6566
};
6667

6768
LLVMInstruction(Type type) :

test/dev/llvm/llvmcodebuilder_test.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3568,3 +3568,72 @@ TEST_F(LLVMCodeBuilderTest, LoopLists)
35683568
code->run(ctx.get());
35693569
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
35703570
}
3571+
3572+
TEST_F(LLVMCodeBuilderTest, StopNoWarp)
3573+
{
3574+
Sprite sprite;
3575+
createBuilder(&sprite, false);
3576+
3577+
m_builder->beginLoopCondition();
3578+
CompilerValue *v = m_builder->addConstValue(true);
3579+
m_builder->beginWhileLoop(v);
3580+
m_builder->createStop();
3581+
m_builder->endLoop();
3582+
3583+
m_builder->addTargetFunctionCall("test_function_no_args", Compiler::StaticType::Void, {}, {});
3584+
3585+
std::string expected = "";
3586+
3587+
auto code = m_builder->finalize();
3588+
Script script(&sprite, nullptr, nullptr);
3589+
script.setCode(code);
3590+
Thread thread(&sprite, nullptr, &script);
3591+
auto ctx = code->createExecutionContext(&thread);
3592+
testing::internal::CaptureStdout();
3593+
code->run(ctx.get());
3594+
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
3595+
}
3596+
3597+
TEST_F(LLVMCodeBuilderTest, StopWarp)
3598+
{
3599+
Sprite sprite;
3600+
createBuilder(&sprite, true);
3601+
3602+
CompilerValue *v = m_builder->addConstValue(true);
3603+
m_builder->beginIfStatement(v);
3604+
m_builder->createStop();
3605+
m_builder->endIf();
3606+
3607+
m_builder->addTargetFunctionCall("test_function_no_args", Compiler::StaticType::Void, {}, {});
3608+
3609+
std::string expected = "";
3610+
3611+
auto code = m_builder->finalize();
3612+
Script script(&sprite, nullptr, nullptr);
3613+
script.setCode(code);
3614+
Thread thread(&sprite, nullptr, &script);
3615+
auto ctx = code->createExecutionContext(&thread);
3616+
testing::internal::CaptureStdout();
3617+
code->run(ctx.get());
3618+
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
3619+
}
3620+
3621+
TEST_F(LLVMCodeBuilderTest, StopAndReturn)
3622+
{
3623+
Sprite sprite;
3624+
createBuilder(&sprite, true);
3625+
3626+
m_builder->addTargetFunctionCall("test_function_no_args", Compiler::StaticType::Void, {}, {});
3627+
m_builder->createStop();
3628+
3629+
std::string expected = "no_args\n";
3630+
3631+
auto code = m_builder->finalize();
3632+
Script script(&sprite, nullptr, nullptr);
3633+
script.setCode(code);
3634+
Thread thread(&sprite, nullptr, &script);
3635+
auto ctx = code->createExecutionContext(&thread);
3636+
testing::internal::CaptureStdout();
3637+
code->run(ctx.get());
3638+
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
3639+
}

test/mocks/codebuildermock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,6 @@ class CodeBuilderMock : public ICodeBuilder
7171
MOCK_METHOD(void, endLoop, (), (override));
7272

7373
MOCK_METHOD(void, yield, (), (override));
74+
75+
MOCK_METHOD(void, createStop, (), (override));
7476
};

0 commit comments

Comments
 (0)