FFI seems to work

This commit is contained in:
2026-07-05 07:51:15 +10:00
parent a913b3b24a
commit 7cc1eed787

View File

@@ -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;
} }