FFI seems to work
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ffi.h>
|
||||||
|
|
||||||
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
|
#define HEAP_GET(heap, idx) (&(heap)->heap[(idx)])
|
||||||
#define HEAP_SET(heap, idx, val) ((heap)->heap[(idx)] = (val))
|
#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) {
|
struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeInstruction* instruction, GroundBytecodeHeap* heap) {
|
||||||
|
|
||||||
static const void* jumpTable[] = {
|
static const void* jumpTable[] = {
|
||||||
@@ -757,7 +769,100 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
GroundBytecodeFunction* function = &HEAP_GET(heap, instruction->args.at[0])->as.Function;
|
GroundBytecodeFunction* function = &HEAP_GET(heap, instruction->args.at[0])->as.Function;
|
||||||
|
|
||||||
if (function->isNativeFunction) {
|
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;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,7 +938,7 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
if (Ground.Flags.error) {
|
if (Ground.Flags.error) {
|
||||||
return CONTINUE;
|
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) {
|
if (Ground.Flags.error) {
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
@@ -882,7 +987,7 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GroundType_CoreType: {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@@ -897,7 +1002,7 @@ struct GroundExecutionResult _GroundBytecodeInstructionExecute(GroundBytecodeIns
|
|||||||
.as.Function = bf
|
.as.Function = bf
|
||||||
};
|
};
|
||||||
|
|
||||||
HEAP_SET(heap, instruction->args.at[3], val);
|
HEAP_SET(heap, instruction->args.at[2], val);
|
||||||
|
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user