Skip to content

Commit 7e04a52

Browse files
committed
Add print instruction
1 parent 3fe02f5 commit 7e04a52

10 files changed

Lines changed: 65 additions & 1 deletion

File tree

src/engine/internal/icodebuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ class ICodeBuilder
104104
virtual void invalidateTarget() = 0;
105105

106106
virtual void createProcedureCall(BlockPrototype *prototype, const Compiler::Args &args) = 0;
107+
108+
virtual void createPrint(CompilerValue *string) = 0;
107109
};
108110

109111
} // namespace libscratchcpp

src/engine/internal/llvm/instructions/control.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ ProcessResult Control::process(LLVMInstruction *ins)
6868
ret.next = buildInvalidateTarget(ins);
6969
break;
7070

71+
case LLVMInstruction::Type::Print:
72+
ret.next = buildPrint(ins);
73+
break;
74+
7175
default:
7276
ret.match = false;
7377
break;
@@ -365,3 +369,14 @@ LLVMInstruction *Control::buildInvalidateTarget(LLVMInstruction *ins)
365369
m_utils.invalidateTarget();
366370
return ins->next;
367371
}
372+
373+
LLVMInstruction *Control::buildPrint(LLVMInstruction *ins)
374+
{
375+
assert(ins->args.size() == 1);
376+
377+
const auto &arg = ins->args[0];
378+
llvm::Value *str = m_utils.castValue(arg.second, arg.first);
379+
380+
m_builder.CreateCall(m_utils.functions().resolve_llvm_print(), str);
381+
return ins->next;
382+
}

src/engine/internal/llvm/instructions/control.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Control : public InstructionGroup
2929
LLVMInstruction *buildStop(LLVMInstruction *ins);
3030
LLVMInstruction *buildThreadStop(LLVMInstruction *ins);
3131
LLVMInstruction *buildInvalidateTarget(LLVMInstruction *ins);
32+
LLVMInstruction *buildPrint(LLVMInstruction *ins);
3233
};
3334

3435
} // namespace libscratchcpp::llvmins

src/engine/internal/llvm/llvmcodebuilder.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,11 @@ void LLVMCodeBuilder::createProcedureCall(BlockPrototype *prototype, const Compi
594594
createOp(ins, Compiler::StaticType::Void, types, args);
595595
}
596596

597+
void LLVMCodeBuilder::createPrint(CompilerValue *string)
598+
{
599+
createOp(LLVMInstruction::Type::Print, Compiler::StaticType::Void, Compiler::StaticType::String, { string });
600+
}
601+
597602
void LLVMCodeBuilder::initTypes()
598603
{
599604
m_valueDataType = m_ctx->valueDataType();

src/engine/internal/llvm/llvmcodebuilder.h

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

120120
void createProcedureCall(BlockPrototype *prototype, const Compiler::Args &args) override;
121121

122+
void createPrint(CompilerValue *string) override;
123+
122124
private:
123125
void initTypes();
124126

src/engine/internal/llvm/llvmfunctions.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
#include <scratchcpp/value_functions.h>
44
#include <scratchcpp/irandomgenerator.h>
5+
#include <scratchcpp/stringptr.h>
6+
#include <utf8.h>
7+
#include <iostream>
58

69
#include "llvmfunctions.h"
710
#include "llvmcompilercontext.h"
@@ -45,6 +48,12 @@ extern "C"
4548
{
4649
return static_cast<LLVMExecutionContext *>(ctx)->finished();
4750
}
51+
52+
LIBSCRATCHCPP_EXPORT void llvm_print(const StringPtr *string)
53+
{
54+
// TODO: Using a string function would be better
55+
std::cout << utf8::utf16to8(std::u16string(string->data));
56+
}
4857
}
4958

5059
LLVMFunctions::LLVMFunctions(LLVMCompilerContext *ctx, llvm::IRBuilder<> *builder) :
@@ -304,6 +313,11 @@ llvm::FunctionCallee LLVMFunctions::resolve_llvm_is_thread_finished()
304313
return resolveFunction("llvm_is_thread_finished", llvm::FunctionType::get(m_builder->getInt1Ty(), { pointerType }, false));
305314
}
306315

316+
llvm::FunctionCallee LLVMFunctions::resolve_llvm_print()
317+
{
318+
return resolveFunction("llvm_print", llvm::FunctionType::get(m_builder->getVoidTy(), { m_stringPtrType->getPointerTo() }, false));
319+
}
320+
307321
llvm::FunctionCallee LLVMFunctions::resolve_string_pool_new()
308322
{
309323
return resolveFunction("string_pool_new", llvm::FunctionType::get(m_stringPtrType->getPointerTo(), false));

src/engine/internal/llvm/llvmfunctions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class LLVMFunctions
5050
llvm::FunctionCallee resolve_llvm_get_string_array();
5151
llvm::FunctionCallee resolve_llvm_mark_thread_as_finished();
5252
llvm::FunctionCallee resolve_llvm_is_thread_finished();
53+
llvm::FunctionCallee resolve_llvm_print();
5354
llvm::FunctionCallee resolve_string_pool_new();
5455
llvm::FunctionCallee resolve_string_pool_free();
5556
llvm::FunctionCallee resolve_string_alloc();

src/engine/internal/llvm/llvminstruction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ struct LLVMInstruction
8080
ThreadStop,
8181
InvalidateTarget,
8282
CallProcedure,
83-
ProcedureArg
83+
ProcedureArg,
84+
Print
8485
};
8586

8687
LLVMInstruction(Type type, bool loopCondition) :

test/llvm/llvmcodebuilder_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3779,6 +3779,27 @@ TEST_F(LLVMCodeBuilderTest, ProcedureThreadStop_NonWarp_AfterYield)
37793779
ASSERT_TRUE(code->isFinished(ctx.get()));
37803780
}
37813781

3782+
TEST_F(LLVMCodeBuilderTest, Print)
3783+
{
3784+
Sprite sprite;
3785+
LLVMCodeBuilder *builder = m_utils.createBuilder(&sprite, true);
3786+
3787+
CompilerValue *ret = builder->addTargetFunctionCall("test_function_no_args_ret", Compiler::StaticType::String, {}, {});
3788+
builder->createPrint(ret);
3789+
builder->createPrint(builder->addConstValue("\n"));
3790+
3791+
std::string expected = "no_args_ret\nno_args_output\n";
3792+
3793+
auto code = builder->build();
3794+
Script script(&sprite, nullptr, nullptr);
3795+
script.setCode(code);
3796+
Thread thread(&sprite, nullptr, &script);
3797+
auto ctx = code->createExecutionContext(&thread);
3798+
testing::internal::CaptureStdout();
3799+
code->run(ctx.get());
3800+
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
3801+
}
3802+
37823803
TEST_F(LLVMCodeBuilderTest, HatPredicates)
37833804
{
37843805
Sprite sprite;

test/mocks/codebuildermock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,6 @@ class CodeBuilderMock : public ICodeBuilder
9393
MOCK_METHOD(void, invalidateTarget, (), (override));
9494

9595
MOCK_METHOD(void, createProcedureCall, (BlockPrototype *, const Compiler::Args &), (override));
96+
97+
MOCK_METHOD(void, createPrint, (CompilerValue *), (override));
9698
};

0 commit comments

Comments
 (0)