FFI seems to work
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ffi.h>
|
||||
|
||||
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
|
||||
#define HEAP_SET(heap, idx, val) ((heap)->heap[(idx)] = (val))
|
||||
@@ -40,6 +41,17 @@ static void printValue(GroundBytecodeValue* val) {
|
||||
}
|
||||
}
|
||||
|
||||
static ffi_type* ffiTypeFromGroundType(GroundType* type) {
|
||||
switch (type->type) {
|
||||
case GroundType_Int: return &ffi_type_sint64;
|
||||
case GroundType_Double: return &ffi_type_double;
|
||||
case GroundType_Char: return &ffi_type_schar;
|
||||
case GroundType_Bool: return &ffi_type_uint8;
|
||||
case GroundType_String: return &ffi_type_pointer;
|
||||
default: return &ffi_type_pointer; // FIXME implement stuff for everything else
|
||||
}
|
||||
}
|
||||
|
||||
struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
|
||||
|
||||
static const void* jumpTable[] = {
|
||||
@@ -757,7 +769,100 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
||||
GroundBytecodeFunction* function = &HEAP_GET(heap, instruction->args.at[0])->as.Function;
|
||||
|
||||
if (function->isNativeFunction) {
|
||||
// TODO implement calling native functions
|
||||
|
||||
// Ensure we have the right amount and types of arguments first
|
||||
if (function->args.count != instruction->args.len - 2) {
|
||||
Ground.Log.Error("incorrect amount of arguments for native function in Ground.Bytecode.Instruction.execute");
|
||||
Ground.Flags.error = true;
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
ffi_type* argTypes[function->args.count];
|
||||
void* args[function->args.count];
|
||||
|
||||
for (GroundSize i = 0; i < function->args.count; i++) {
|
||||
if (function->args.at[i].as.type.type != HEAP_GET(heap, instruction->args.at[i+1])->type.type) {
|
||||
Ground.Log.Error("incorrect type of argument for native function in Ground.Bytecode.Instruction.execute");
|
||||
Ground.Flags.error = true;
|
||||
return CONTINUE;
|
||||
}
|
||||
argTypes[i] = ffiTypeFromGroundType(&function->args.at[i].as.type);
|
||||
switch (HEAP_GET(heap, instruction->args.at[i+1])->type.type) {
|
||||
case GroundType_Int: {
|
||||
args[i] = &HEAP_GET(heap, instruction->args.at[i+1])->as.Int;
|
||||
break;
|
||||
}
|
||||
case GroundType_Double: {
|
||||
args[i] = &HEAP_GET(heap, instruction->args.at[i+1])->as.Double;
|
||||
break;
|
||||
}
|
||||
case GroundType_Char: {
|
||||
args[i] = &HEAP_GET(heap, instruction->args.at[i+1])->as.Char;
|
||||
break;
|
||||
}
|
||||
case GroundType_Bool: {
|
||||
args[i] = &HEAP_GET(heap, instruction->args.at[i+1])->as.Bool;
|
||||
break;
|
||||
}
|
||||
case GroundType_String: {
|
||||
args[i] = &HEAP_GET(heap, instruction->args.at[i+1])->as.String.cstr;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// FIXME implement non-basic types
|
||||
args[i] = HEAP_GET(heap, instruction->args.at[i+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ffi_cif cif;
|
||||
ffi_status status = ffi_prep_cif(
|
||||
&cif, FFI_DEFAULT_ABI, function->args.count, ffiTypeFromGroundType(function->returnType), argTypes
|
||||
);
|
||||
|
||||
if (status != FFI_OK) {
|
||||
Ground.Log.Error("ffi CIF preperation failed in Ground.Bytecode.Instruction.execute");
|
||||
Ground.Flags.error = true;
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
union {
|
||||
GroundInt Int;
|
||||
GroundDouble Double;
|
||||
GroundChar Char;
|
||||
GroundBool Bool;
|
||||
char* String;
|
||||
// TODO more stuff
|
||||
} result;
|
||||
|
||||
ffi_call(&cif, function->program.native, &result, args);
|
||||
|
||||
// Put return value into the scope
|
||||
switch (function->returnType->type) {
|
||||
case GroundType_Int: {
|
||||
HEAP_SET(heap, instruction->args.at[instruction->args.len - 1], Ground.New.BytecodeValue(Ground.New.Value.Int(result.Int)));
|
||||
break;
|
||||
}
|
||||
case GroundType_Char: {
|
||||
HEAP_SET(heap, instruction->args.at[instruction->args.len - 1], Ground.New.BytecodeValue(Ground.New.Value.Char(result.Char)));
|
||||
break;
|
||||
}
|
||||
case GroundType_Double: {
|
||||
HEAP_SET(heap, instruction->args.at[instruction->args.len - 1], Ground.New.BytecodeValue(Ground.New.Value.Double(result.Double)));
|
||||
break;
|
||||
}
|
||||
case GroundType_Bool: {
|
||||
HEAP_SET(heap, instruction->args.at[instruction->args.len - 1], Ground.New.BytecodeValue(Ground.New.Value.Bool(result.Bool)));
|
||||
break;
|
||||
}
|
||||
case GroundType_String: {
|
||||
HEAP_SET(heap, instruction->args.at[instruction->args.len - 1], Ground.New.BytecodeValue(Ground.New.Value.String(Ground.New.String(result.String))));
|
||||
break;
|
||||
}
|
||||
default: break; // TODO more types
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
@@ -833,7 +938,7 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
||||
if (Ground.Flags.error) {
|
||||
return CONTINUE;
|
||||
}
|
||||
void* function = Ground.FFI.getFunction(handle, HEAP_GET(heap, instruction->args.at[0])->as.String.cstr);
|
||||
void* function = Ground.FFI.getFunction(handle, HEAP_GET(heap, instruction->args.at[1])->as.String.cstr);
|
||||
if (Ground.Flags.error) {
|
||||
return CONTINUE;
|
||||
}
|
||||
@@ -882,7 +987,7 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
||||
break;
|
||||
}
|
||||
case GroundType_CoreType: {
|
||||
bf.args.at[i].as.type.type = HEAP_GET(heap, instruction->args.at[3])->as.CoreType;
|
||||
bf.args.at[i].as.type.type = HEAP_GET(heap, instruction->args.at[i + 4])->as.CoreType;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -897,7 +1002,7 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
||||
.as.Function = bf
|
||||
};
|
||||
|
||||
HEAP_SET(heap, instruction->args.at[3], val);
|
||||
HEAP_SET(heap, instruction->args.at[2], val);
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user