Skip to content

Commit 9978701

Browse files
committed
Add ffi to byte code
However we still need a way to put the function name strings into the byte code Also currently I just use qword for all arg types
1 parent 13cf8bc commit 9978701

4 files changed

Lines changed: 88 additions & 15 deletions

File tree

src/executer/ByteCode.cpp

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,13 @@ std::string instructionsToString(const std::vector<Instruction>& instructions, b
4141
{ Op::LTE, {"LTE", {}} },
4242
{ Op::GTE, {"GTE", {}} },
4343
{ Op::NEQ, {"NEQ", {}} },
44-
{ Op::DUB, {"DUB", {"LOOKBACK"}} }
44+
{ Op::DUB, {"DUB", {"LOOKBACK"}} },
45+
{ Op::REG_FFI, {"REG_FFI", {}} },
46+
{ Op::PUSH_FFI_WORD, {"PUSH_FFI_WORD", {}} },
47+
{ Op::PUSH_FFI_DWORD, {"PUSH_FFI_DWORD", {}} },
48+
{ Op::PUSH_FFI_QWORD, {"PUSH_FFI_QWORD", {}} },
49+
{ Op::PUSH_FFI_XWORD, {"PUSH_FFI_XWORD", {}} },
50+
{ Op::CALL_FFI, {"CALL_FFI", {}} }
4551
};
4652

4753
std::stringstream ss;
@@ -268,12 +274,42 @@ ProgramState ByteCodeVM::run(size_t maxInstructions) {
268274
case Op::TERM: {
269275
return ProgramState::Finished;
270276
}
277+
case Op::REG_FFI: {
278+
// Register FFI function
279+
// TODO: How do we get strings here?
280+
// TODO: Need to somehow embed strings into the bytecode
281+
ffiFunctions.add("library", "function");
282+
break;
283+
}
284+
case Op::PUSH_FFI_WORD:
285+
case Op::PUSH_FFI_DWORD:
286+
case Op::PUSH_FFI_QWORD:
287+
case Op::PUSH_FFI_XWORD: // TODO: Distinguish between these types
288+
{
289+
auto value = stack.pop();
290+
ffiArgs.addWord(value);
291+
break;
292+
}
293+
case Op::CALL_FFI: {
294+
auto id = stack.pop();
295+
auto result = ffiFunctions.call(id, ffiArgs);
296+
stack.push(result);
297+
ffiArgs.clear();
298+
break;
299+
}
271300
}
272301
}
273302
return ProgramState::Paused;
274303
}
275304

276-
ByteCodeVM::ByteCodeVM(const Program& program) : idx{0ull}, callstack{}, stack{}, program(program), debug{true} {}
305+
ByteCodeVM::ByteCodeVM(const Program& program) :
306+
idx{0ull},
307+
callstack{},
308+
stack{},
309+
program(program),
310+
debug{true},
311+
ffiFunctions{},
312+
ffiArgs{} {}
277313

278314
std::string ByteCodeVM::execute(size_t maxInstructions) {
279315
auto state = run(maxInstructions);

src/executer/ByteCode.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,48 @@
66
#include <map>
77
#include <sstream>
88

9+
#include "../executer/ExternalFunctions.h"
910
#include "../error/Exceptions.h"
1011
#include "Stack.h"
1112

1213
namespace executor {
1314

1415
using word_t = unsigned long;
1516

16-
enum class Op { NOP, LOCALS, LOCALL, CALL, RET, PUSH, POP, ADD, SUB, MUL, DIV, MOD, JUMP, JUMP_IF, ALLOC, PRINTS, TERM, LT, GT, EQ, LTE, GTE, NEQ, LOADW, STOREW, DUB };
17+
enum class Op {
18+
NOP,
19+
LOCALS,
20+
LOCALL,
21+
CALL,
22+
RET,
23+
PUSH,
24+
POP,
25+
ADD,
26+
SUB,
27+
MUL,
28+
DIV,
29+
MOD,
30+
JUMP,
31+
JUMP_IF,
32+
ALLOC,
33+
PRINTS,
34+
TERM,
35+
LT,
36+
GT,
37+
EQ,
38+
LTE,
39+
GTE,
40+
NEQ,
41+
LOADW,
42+
STOREW,
43+
DUB,
44+
REG_FFI,
45+
PUSH_FFI_WORD,
46+
PUSH_FFI_DWORD,
47+
PUSH_FFI_QWORD,
48+
PUSH_FFI_XWORD,
49+
CALL_FFI
50+
};
1751

1852
// TODO: ADD etc should be type specific, so IADD, FADD
1953
// TODO: Logic operator missing: AND, OR, NOT
@@ -83,6 +117,8 @@ class ByteCodeVM {
83117
std::vector<word_t> heap;
84118
Program program;
85119
bool debug;
120+
ffi::ExternalFunctions ffiFunctions;
121+
ffi::Arguments ffiArgs;
86122

87123
ProgramState run(size_t maxInstructions);
88124

src/executer/ExternalFunctions.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ size_t ExternalFunctions::add(const std::string& library, const std::string& fun
7878
ASSURE_NOT_NULL(libraryHandle);
7979
dlerror(); // Clear any existing error
8080

81-
//void (*print)() = (void (*)())dlsym(handle, "print");
8281
functionInfo.functionPtr = dlsym(libraryHandle, functionName.c_str());
8382
const char* dlsym_error = dlerror();
8483
if (dlsym_error) {
@@ -95,11 +94,21 @@ qword_t ExternalFunctions::call(size_t id, const Arguments& args) {
9594
ASSURE(id < functions.size(), "Function ID out of bounds");
9695

9796
const ExternalFunction& func = functions[id];
97+
ASSURE_NOT_NULL(func.functionPtr);
9898

99-
qword_t result;
99+
// TODO: We don't support more than 6 arguments yet (put on stack)
100+
ASSURE(args.getSize() <= 6, "Too many arguments for external function");
100101

101-
__asm__ volatile (
102+
// TODO: We don't support float/double arguments yet (xmm registers)
103+
104+
// https://github.com/tsoding/b/blob/main/src/codegen/fasm_x86_64.rs#L221
105+
// Floating point numbers are passed in xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
106+
// Integer numbers are passed in rdi, rsi, rdx, rcx, r8, r9
107+
// The result is returned in rax
108+
// If we need more than 6 arguments, the rest are passed on the stack. (?)
102109

110+
qword_t result;
111+
__asm__ volatile (
103112
"movq %[args_tag], %%R10\n" // Bring arg pointer into R10
104113

105114
"call bring_next_value_into_rax\n"
@@ -156,12 +165,6 @@ qword_t ExternalFunctions::call(size_t id, const Arguments& args) {
156165
: [fn_tag] "r"(func.functionPtr),
157166
[args_tag] "r"(args.getBuffer())) ;
158167

159-
// https://github.com/tsoding/b/blob/main/src/codegen/fasm_x86_64.rs#L221
160-
// Floating point numbers are passed in xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
161-
// Integer numbers are passed in rdi, rsi, rdx, rcx, r8, r9
162-
// The result is returned in rax
163-
// If we need more than 6 arguments, the rest are passed on the stack. (?)
164-
165168
return result;
166169
}
167170

src/executer/ExternalFunctions.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ using byte_t = unsigned char;
1313
using word_t = unsigned short;
1414
using dword_t = unsigned int;
1515
using qword_t = unsigned long long;
16-
using xmmword_t = unsigned char[16]; // Probably we don't need this
16+
using xmmword_t = unsigned char[16]; // Probably we don't need this, we might for floats
1717

1818
using ptr = void*;
1919
static_assert(sizeof(ptr) == 8);
@@ -64,8 +64,6 @@ struct ExternalFunction {
6464
std::string library;
6565
std::string name;
6666
void* functionPtr;
67-
// std::vector<Type> parameters;
68-
// Type returnType;
6967
};
7068

7169
class ExternalFunctions {

0 commit comments

Comments
 (0)