Skip to content

Commit 46ed993

Browse files
committed
Passing strings to ffi
1 parent 1a7c52c commit 46ed993

File tree

7 files changed

+48
-21
lines changed

7 files changed

+48
-21
lines changed

lib/libtest.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
// To avoid renaming the function in the exported symbols
55
extern "C" {
6-
void print();
6+
void printNoArgs();
7+
void print(const char*);
78
int mul(int a, int b);
89
void test_v();
910
int test_ii_i(int a, int b);
@@ -16,7 +17,11 @@ extern "C" {
1617
const char* test_pp_p(char* a, char* b);
1718
}
1819

19-
void print() { printf("It's working!\n"); }
20+
void printNoArgs() { printf("It's working!\n"); }
21+
22+
void print(const char* str) {
23+
printf("%s\n", str);
24+
}
2025

2126
int mul(int a, int b){
2227
int r = a * b;

mfiles/TODO_str.m

Lines changed: 0 additions & 7 deletions
This file was deleted.

mfiles/str.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# expect_result=void
2+
3+
let s = "Hello, World!";
4+
let str = s;
5+
6+
let print = extern test::print(s: Str): Void;
7+
print(str);

src/emitter/ByteCodeEmitter.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,17 +275,23 @@ void ByteCodeEmitter::process(const std::shared_ptr<AST::Node>& node, bool hasCo
275275
} else {
276276
loadIdentifier(call->getIdentifier()); // Bring the function addr on the stack
277277

278+
const auto& returnType = fnDataType.getReturn();
279+
ASSURE_NOT_NULL(returnType);
280+
281+
// CALL consumes the arguments from the stack, so we don't need to pop them
282+
// If we don't have a consumer, we have to pop the result. We assume only one result.
283+
// Only if the function is not void, of course.
278284
if (functionType.isExtern) {
279285
code().push_back(executor::Instruction(executor::Op::CALL_FFI));
286+
287+
// CALL_FFI always pushes a result, so we need to get rid of it
288+
// if we don't have a consumer or the return type is None.
289+
if(!hasConsumer || *returnType == DataType::Primitive::None) {
290+
code().push_back(executor::Instruction(executor::Op::POP));
291+
}
280292
} else {
281293
code().push_back(executor::Instruction(executor::Op::CALL, call->getArguments().size()));
282294

283-
// CALL consumes the arguments from the stack, so we don't need to pop them
284-
// If we don't have a consumer, we have to pop the result. We assume only one result.
285-
// Only if the function is not void, of course.
286-
287-
const auto& returnType = fnDataType.getReturn();
288-
ASSURE_NOT_NULL(returnType);
289295
if(!hasConsumer && *returnType != DataType::Primitive::None) {
290296
code().push_back(executor::Instruction(executor::Op::POP));
291297
}
@@ -299,7 +305,7 @@ void ByteCodeEmitter::process(const std::shared_ptr<AST::Node>& node, bool hasCo
299305
auto literal = std::dynamic_pointer_cast<AST::Literal>(node);
300306
if (literal->getDataType() == DataType::Primitive::String) {
301307
auto strIdx = program.data.addString(literal->getStringValue());
302-
code().push_back(executor::Instruction(executor::Op::PUSH, strIdx));
308+
code().push_back(executor::Instruction(executor::Op::DATA_ADDR, strIdx));
303309
} else if (literal->getDataType() == DataType::Primitive::Bool) {
304310
code().push_back(executor::Instruction(
305311
executor::Op::PUSH, literal->getBoolValue() ? 1 : 0));

src/executer/ByteCode.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ std::string instructionsToString(const std::vector<Instruction>& instructions, b
4747
{ Op::PUSH_FFI_DWORD, {"PUSH_FFI_DWORD", {}} },
4848
{ Op::PUSH_FFI_QWORD, {"PUSH_FFI_QWORD", {}} },
4949
{ Op::PUSH_FFI_XWORD, {"PUSH_FFI_XWORD", {}} },
50-
{ Op::CALL_FFI, {"CALL_FFI", {}} }
50+
{ Op::CALL_FFI, {"CALL_FFI", {}} },
51+
{ Op::DATA_ADDR, {"DATA_ADDR", {"DATA_IDX"}} }
5152
};
5253

5354
std::stringstream ss;
@@ -288,7 +289,7 @@ ProgramState ByteCodeVM::run(size_t maxInstructions) {
288289
case Op::PUSH_FFI_XWORD: // TODO: Distinguish between these types
289290
{
290291
auto value = stack.pop();
291-
ffiArgs.addWord(value);
292+
ffiArgs.addQWord(value);
292293
break;
293294
}
294295
case Op::CALL_FFI: {
@@ -298,6 +299,14 @@ ProgramState ByteCodeVM::run(size_t maxInstructions) {
298299
ffiArgs.clear();
299300
break;
300301
}
302+
case Op::DATA_ADDR: {
303+
// DATA_ADDR DATA_IDX
304+
auto dataIdx = inst.arg1;
305+
void* addr = program.data.getAddr(dataIdx);
306+
static_assert(sizeof(word_t) == sizeof(void*));
307+
stack.push(reinterpret_cast<word_t>(addr));
308+
break;
309+
}
301310
}
302311
}
303312
return ProgramState::Paused;

src/executer/ByteCode.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ enum class Op {
4747
PUSH_FFI_DWORD,
4848
PUSH_FFI_QWORD,
4949
PUSH_FFI_XWORD,
50-
CALL_FFI
50+
CALL_FFI,
51+
DATA_ADDR
5152
};
5253

5354
// TODO: ADD etc should be type specific, so IADD, FADD
@@ -96,6 +97,13 @@ class Data {
9697
data[startIdx + str.size()] = 0; // Null terminator
9798
return startIdx;
9899
}
100+
101+
void* getAddr(size_t idx) {
102+
if (idx >= data.size()) {
103+
throwConstraintViolated("Data: Index out of bounds");
104+
}
105+
return reinterpret_cast<void*>(&data[idx]);
106+
}
99107
};
100108

101109
struct Program {

src/mains/Tests.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ void suiteTestfiles(){
281281
testFile("mfiles/struct.m");
282282
testFile("mfiles/struct_nested.m");
283283
testFile("mfiles/extern.m");
284-
285-
testFile("mfiles/TODO_str.m");
284+
testFile("mfiles/str.m");
286285

287286
// TODO: blob type (alloc8(size), get(blob, idx), set(blob, idx)):
288287
// synatx sugar for get, set with []

0 commit comments

Comments
 (0)