Skip to content

Commit feef685

Browse files
committed
Add support for pointer parameters and return values
1 parent 2bca87a commit feef685

File tree

5 files changed

+109
-19
lines changed

5 files changed

+109
-19
lines changed

include/scratchcpp/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class LIBSCRATCHCPP_EXPORT Compiler
3535
Number,
3636
Bool,
3737
String,
38+
Pointer,
3839
Unknown
3940
};
4041

src/engine/internal/llvm/llvmcodebuilder.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020

2121
using namespace libscratchcpp;
2222

23-
static std::unordered_map<ValueType, Compiler::StaticType>
24-
TYPE_MAP = { { ValueType::Number, Compiler::StaticType::Number }, { ValueType::Bool, Compiler::StaticType::Bool }, { ValueType::String, Compiler::StaticType::String } };
23+
static std::unordered_map<ValueType, Compiler::StaticType> TYPE_MAP = {
24+
{ ValueType::Number, Compiler::StaticType::Number },
25+
{ ValueType::Bool, Compiler::StaticType::Bool },
26+
{ ValueType::String, Compiler::StaticType::String },
27+
{ ValueType::Pointer, Compiler::StaticType::Pointer }
28+
};
2529

2630
static const std::unordered_set<LLVMInstruction::Type>
2731
VAR_LIST_READ_INSTRUCTIONS = { LLVMInstruction::Type::ReadVariable, LLVMInstruction::Type::GetListItem, LLVMInstruction::Type::GetListItemIndex, LLVMInstruction::Type::ListContainsItem };
@@ -683,6 +687,10 @@ std::shared_ptr<ExecutableCode> LLVMCodeBuilder::finalize()
683687
std::cerr << "error: local variables do not support string type" << std::endl;
684688
break;
685689

690+
case Compiler::StaticType::Pointer:
691+
std::cerr << "error: local variables do not support pointer type" << std::endl;
692+
break;
693+
686694
default:
687695
assert(false);
688696
break;
@@ -2343,6 +2351,11 @@ llvm::Constant *LLVMCodeBuilder::castConstValue(const Value &value, Compiler::St
23432351
return new llvm::GlobalVariable(*m_module, m_stringPtrType, true, llvm::GlobalValue::PrivateLinkage, stringStruct, "stringPtr");
23442352
}
23452353

2354+
case Compiler::StaticType::Pointer: {
2355+
llvm::Constant *addr = m_builder.getInt64((uintptr_t)value.toPointer());
2356+
return llvm::ConstantExpr::getIntToPtr(addr, m_builder.getVoidTy()->getPointerTo());
2357+
}
2358+
23462359
default:
23472360
assert(false);
23482361
return nullptr;
@@ -2375,6 +2388,9 @@ llvm::Type *LLVMCodeBuilder::getType(Compiler::StaticType type)
23752388
case Compiler::StaticType::String:
23762389
return m_stringPtrType->getPointerTo();
23772390

2391+
case Compiler::StaticType::Pointer:
2392+
return m_builder.getVoidTy()->getPointerTo();
2393+
23782394
default:
23792395
assert(false);
23802396
return nullptr;
@@ -2883,6 +2899,7 @@ llvm::Value *LLVMCodeBuilder::createValue(LLVMRegister *reg)
28832899
break;
28842900

28852901
case ValueType::String:
2902+
case ValueType::Pointer:
28862903
value = llvm::ConstantExpr::getPtrToInt(value, m_valueDataType->getElementType(0));
28872904
break;
28882905

test/llvm/llvmcodebuilder_test.cpp

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,35 @@ TEST_F(LLVMCodeBuilderTest, FunctionCalls)
507507
}
508508
}
509509

510+
TEST_F(LLVMCodeBuilderTest, FunctionCallsWithPointers)
511+
{
512+
createBuilder(true);
513+
514+
int var = 12;
515+
CompilerValue *v = m_builder->addConstValue(&var);
516+
v = m_builder->addTargetFunctionCall("test_function_1_ptr_arg_ret", Compiler::StaticType::Pointer, { Compiler::StaticType::Pointer }, { v });
517+
518+
m_builder->addFunctionCall("test_print_pointer", Compiler::StaticType::Void, { Compiler::StaticType::Pointer }, { v });
519+
520+
auto code = m_builder->finalize();
521+
Script script(&m_target, nullptr, nullptr);
522+
script.setCode(code);
523+
Thread thread(&m_target, nullptr, &script);
524+
auto ctx = code->createExecutionContext(&thread);
525+
526+
std::stringstream s;
527+
s << &m_target;
528+
std::string ptr = s.str();
529+
530+
const std::string expected = "1_arg_ret 12\n" + ptr + "\n";
531+
532+
EXPECT_CALL(m_target, isStage());
533+
testing::internal::CaptureStdout();
534+
code->run(ctx.get());
535+
ASSERT_EQ(testing::internal::GetCapturedStdout(), expected);
536+
ASSERT_TRUE(code->isFinished(ctx.get()));
537+
}
538+
510539
TEST_F(LLVMCodeBuilderTest, ConstCasting)
511540
{
512541
createBuilder(true);
@@ -6093,32 +6122,54 @@ TEST_F(LLVMCodeBuilderTest, Reporters)
60936122

60946123
auto code3 = m_builder->finalize();
60956124

6096-
Script script1(&sprite, nullptr, nullptr);
6097-
script1.setCode(code1);
6098-
Thread thread1(&sprite, nullptr, &script1);
6099-
auto ctx = code1->createExecutionContext(&thread1);
6125+
// Reporter 4
6126+
createReporterBuilder(&sprite);
6127+
int pointee;
6128+
m_builder->addConstValue(&pointee);
6129+
6130+
auto code4 = m_builder->finalize();
6131+
6132+
// Reporter 5
6133+
createReporterBuilder(&sprite);
6134+
v = m_builder->addConstValue(&pointee);
6135+
m_builder->addFunctionCall("test_const_pointer", Compiler::StaticType::Pointer, { Compiler::StaticType::Pointer }, { v });
6136+
6137+
auto code5 = m_builder->finalize();
6138+
6139+
auto runReporter = [&sprite](std::shared_ptr<ExecutableCode> code) {
6140+
Script script(&sprite, nullptr, nullptr);
6141+
script.setCode(code);
6142+
Thread thread1(&sprite, nullptr, &script);
6143+
auto ctx = code->createExecutionContext(&thread1);
6144+
return code->runReporter(ctx.get());
6145+
};
61006146

6101-
ValueData ret = code1->runReporter(ctx.get());
6147+
// 1
6148+
ValueData ret = runReporter(code1);
61026149
ASSERT_TRUE(value_isNumber(&ret));
61036150
ASSERT_EQ(value_toDouble(&ret), -45.23);
61046151
value_free(&ret);
61056152

6106-
Script script2(&sprite, nullptr, nullptr);
6107-
script2.setCode(code2);
6108-
Thread thread2(&sprite, nullptr, &script2);
6109-
ctx = code2->createExecutionContext(&thread2);
6110-
6111-
ret = code2->runReporter(ctx.get());
6153+
// 2
6154+
ret = runReporter(code2);
61126155
ASSERT_EQ(Value(ret).toString(), "test");
61136156
value_free(&ret);
61146157

6115-
Script script3(&sprite, nullptr, nullptr);
6116-
script3.setCode(code3);
6117-
Thread thread3(&sprite, nullptr, &script3);
6118-
ctx = code3->createExecutionContext(&thread3);
6119-
6120-
ret = code3->runReporter(ctx.get());
6158+
// 3
6159+
ret = runReporter(code3);
61216160
var->setValue("abc"); // the string should be copied
61226161
ASSERT_EQ(Value(ret).toString(), "Hello world!");
61236162
value_free(&ret);
6163+
6164+
// 4
6165+
ret = runReporter(code4);
6166+
ASSERT_TRUE(value_isPointer(&ret));
6167+
ASSERT_EQ(value_toPointer(&ret), &pointee);
6168+
value_free(&ret);
6169+
6170+
// 5
6171+
ret = runReporter(code5);
6172+
ASSERT_TRUE(value_isPointer(&ret));
6173+
ASSERT_EQ(value_toPointer(&ret), &pointee);
6174+
value_free(&ret);
61246175
}

test/llvm/testfunctions.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ extern "C"
9898
return value_toStringPtr(&v.data());
9999
}
100100

101+
const void *test_function_1_ptr_arg_ret(Target *target, const int *arg1)
102+
{
103+
target->isStage();
104+
std::cout << "1_arg_ret " << *arg1 << std::endl;
105+
return target;
106+
}
107+
101108
bool test_equals(const StringPtr *a, const StringPtr *b)
102109
{
103110
return string_compare_case_sensitive(a, b) == 0;
@@ -131,6 +138,11 @@ extern "C"
131138
return ret;
132139
}
133140

141+
const void *test_const_pointer(const void *v)
142+
{
143+
return v;
144+
}
145+
134146
bool test_not(bool arg)
135147
{
136148
return !arg;
@@ -165,4 +177,9 @@ extern "C"
165177
{
166178
std::cout << utf8::utf16to8(std::u16string(v->data)) << std::endl;
167179
}
180+
181+
void test_print_pointer(const void *v)
182+
{
183+
std::cout << v << std::endl;
184+
}
168185
}

test/llvm/testfunctions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ extern "C"
2727
void test_function_3_args(Target *target, const StringPtr *arg1, const StringPtr *arg2, const StringPtr *arg3);
2828
StringPtr *test_function_3_args_ret(Target *target, const StringPtr *arg1, const StringPtr *arg2, const StringPtr *arg3);
2929

30+
const void *test_function_1_ptr_arg_ret(Target *target, const int *arg1);
31+
3032
bool test_equals(const StringPtr *a, const StringPtr *b);
3133
bool test_lower_than(double a, double b);
3234
bool test_not(bool arg);
3335
double test_const_number(double v);
3436
bool test_const_bool(bool v);
3537
StringPtr *test_const_string(const StringPtr *v);
38+
const void *test_const_pointer(const void *v);
3639

3740
void test_unreachable();
3841

@@ -43,6 +46,7 @@ extern "C"
4346
void test_print_number(double v);
4447
void test_print_bool(bool v);
4548
void test_print_string(const StringPtr *v);
49+
void test_print_pointer(const void *v);
4650
}
4751

4852
} // namespace libscratchcpp

0 commit comments

Comments
 (0)