From 61182e0153ce1adf6bb3b9c47cb3d1ba73f1adc3 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sun, 17 May 2026 17:11:02 +0100 Subject: [PATCH] fx.reflection: function: update invocation to support new value-types --- fx.reflection/function.c | 50 +++++- .../include/fx/reflection/function.h | 4 +- fx.reflection/sys/apple/aarch64/callvm.c | 156 ++++++++++++++++-- .../apple/aarch64/include/platform/callvm.h | 9 +- 4 files changed, 196 insertions(+), 23 deletions(-) diff --git a/fx.reflection/function.c b/fx.reflection/function.c index 67e4881..eae7c0c 100644 --- a/fx.reflection/function.c +++ b/fx.reflection/function.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -8,8 +9,8 @@ struct fx_function_p { char *func_name; fx_function_flags func_flags; fx_function_impl func_impl; - fx_value_type func_return_type; - fx_value_type *func_arg_types; + fx_type_id func_return_type; + fx_type_id *func_arg_types; /* number of explicit arguments that the function takes. * if the FX_FUNCTION_F_VARARG flag is set, the function supports a * variable number of arguments, which may be handled differently by the @@ -61,6 +62,28 @@ static fx_status function_bind( return FX_SUCCESS; } +static void push_arg( + const fx_value *arg, + fx_type_id param_type, + struct callvm *vm) +{ + if (!param_type) { + callvm_push(vm, arg); + return; + } + + unsigned int param_value_type = __fx_type_get_value_type(param_type); + if (param_value_type == __FX_VALUE_TYPE_CSTR + && fx_value_is_type(arg, FX_TYPE_STRING)) { + fx_value cstr = FX_CSTR( + fx_string_get_cstr(fx_value_get_object_c(arg))); + callvm_push(vm, &cstr); + return; + } + + callvm_push(vm, arg); +} + static fx_status function_invoke( const struct fx_function_p *func, const fx_value *args, @@ -84,14 +107,27 @@ static fx_status function_invoke( struct callvm vm = {0}; callvm_reset(&vm, nr_fixed_args); + size_t param_index = 0; for (size_t i = 0; i < func->func_nr_bound_args; i++) { const fx_value *arg = &func->func_bound_args[i]; - callvm_push(&vm, arg); + fx_type_id param_type = NULL; + if (param_index < func->func_nr_args) { + param_type = func->func_arg_types[param_index]; + } + + push_arg(arg, param_type, &vm); + param_index++; } for (size_t i = 0; i < nr_args; i++) { const fx_value *arg = &args[i]; - callvm_push(&vm, arg); + fx_type_id param_type = NULL; + if (param_index < func->func_nr_args) { + param_type = func->func_arg_types[param_index]; + } + + push_arg(arg, param_type, &vm); + param_index++; } *return_value = callvm_invoke( @@ -109,9 +145,9 @@ fx_function *fx_function_create( const char *name, fx_function_flags flags, fx_function_impl impl, - const fx_value_type *args, + const fx_type_id *args, size_t nr_args, - fx_value_type return_type) + fx_type_id return_type) { fx_function *func = fx_object_create(FX_REFLECTION_TYPE_FUNCTION); if (!func) { @@ -122,7 +158,7 @@ fx_function *fx_function_create( func, FX_REFLECTION_TYPE_FUNCTION); - if (nr_args == 1 && args[0] == FX_VALUE_TYPE_NONE) { + if (nr_args == 1 && args[0] == NULL) { nr_args = 0; } diff --git a/fx.reflection/include/fx/reflection/function.h b/fx.reflection/include/fx/reflection/function.h index 24f19f7..59fcfaa 100644 --- a/fx.reflection/include/fx/reflection/function.h +++ b/fx.reflection/include/fx/reflection/function.h @@ -32,9 +32,9 @@ FX_API fx_function *fx_function_create( const char *name, fx_function_flags flags, fx_function_impl impl, - const fx_value_type *args, + const fx_type_id *args, size_t nr_args, - fx_value_type return_type); + fx_type_id return_type); FX_API fx_status fx_function_bind(fx_function *func, fx_value *args, size_t nr_args); FX_API fx_status fx_function_invoke( diff --git a/fx.reflection/sys/apple/aarch64/callvm.c b/fx.reflection/sys/apple/aarch64/callvm.c index 2246e93..5c6b481 100644 --- a/fx.reflection/sys/apple/aarch64/callvm.c +++ b/fx.reflection/sys/apple/aarch64/callvm.c @@ -1,3 +1,6 @@ +#include +#include +#include #include #include @@ -77,13 +80,88 @@ void callvm_push(struct callvm *vm, const fx_value *value) return; } - switch (value->v_type.t_primitive) { - case FX_VALUE_TYPE_DOUBLE: + if (!fx_type_is_value_type(value->v_type)) { + push_int(vm, (uintptr_t)value->v_object); + return; + } + + unsigned int value_type = __fx_type_get_value_type(value->v_type); + + switch (value_type) { + case __FX_VALUE_TYPE_BOOL: + push_int(vm, value->v_bool); + break; + case __FX_VALUE_TYPE_I16: + push_int(vm, value->v_i16); + break; + case __FX_VALUE_TYPE_U16: + push_int(vm, value->v_u16); + break; + case __FX_VALUE_TYPE_I32: + push_int(vm, value->v_i32); + break; + case __FX_VALUE_TYPE_U32: + push_int(vm, value->v_u32); + break; + case __FX_VALUE_TYPE_I64: + push_int(vm, value->v_i64); + break; + case __FX_VALUE_TYPE_U64: + push_int(vm, value->v_u64); + break; + case __FX_VALUE_TYPE_IPTR: + push_int(vm, value->v_iptr); + break; + case __FX_VALUE_TYPE_UPTR: + push_int(vm, value->v_uptr); + break; + case __FX_VALUE_TYPE_SBYTE: + push_int(vm, value->v_sbyte); + break; + case __FX_VALUE_TYPE_BYTE: + push_int(vm, value->v_byte); + break; + case __FX_VALUE_TYPE_SHORT: + push_int(vm, value->v_short); + break; + case __FX_VALUE_TYPE_USHORT: + push_int(vm, value->v_ushort); + break; + case __FX_VALUE_TYPE_INT: + push_int(vm, value->v_int); + break; + case __FX_VALUE_TYPE_UINT: + push_int(vm, value->v_uint); + break; + case __FX_VALUE_TYPE_LONG: + push_int(vm, value->v_long); + break; + case __FX_VALUE_TYPE_ULONG: + push_int(vm, value->v_ulong); + break; + case __FX_VALUE_TYPE_LONGLONG: + push_int(vm, value->v_longlong); + break; + case __FX_VALUE_TYPE_ULONGLONG: + push_int(vm, value->v_ulonglong); + break; + case __FX_VALUE_TYPE_SIZE: + push_int(vm, value->v_size); + break; + case __FX_VALUE_TYPE_FLOAT: + push_double(vm, value->v_float); + break; + case __FX_VALUE_TYPE_DOUBLE: push_double(vm, value->v_double); break; - default: + case __FX_VALUE_TYPE_CSTR: + push_int(vm, (uintptr_t)value->v_cstr); + break; + case __FX_VALUE_TYPE_POINTER: push_int(vm, (uintptr_t)value->v_pointer); break; + default: + break; } } @@ -94,17 +172,69 @@ extern void callvm_invoke_v(fx_function_impl impl, struct callvm *vm); fx_value callvm_invoke( struct callvm *vm, fx_function_impl impl, - fx_value_type return_type) + fx_type_id return_type) { - switch (return_type) { - case FX_VALUE_TYPE_NONE: - callvm_invoke_v(impl, vm); - break; - case FX_VALUE_TYPE_DOUBLE: - return FX_VALUE_DOUBLE(callvm_invoke_d(impl, vm)); - default: - return FX_VALUE_INT(callvm_invoke_i(impl, vm)); + if (!fx_type_is_value_type(return_type)) { + uintptr_t v = callvm_invoke_i(impl, vm); + fx_value result = { + .v_type = return_type, + .v_object = (fx_object *)v, + }; + return result; } - return FX_VALUE_EMPTY; + unsigned int value_type = __fx_type_get_value_type(return_type); + + switch (value_type) { + case __FX_VALUE_TYPE_BOOL: + return FX_BOOL(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_I16: + return FX_I16(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_U16: + return FX_U16(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_I32: + return FX_I32(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_U32: + return FX_U32(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_I64: + return FX_I64(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_U64: + return FX_U64(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_IPTR: + return FX_IPTR(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_UPTR: + return FX_UPTR(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_SBYTE: + return FX_SBYTE(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_BYTE: + return FX_BYTE(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_SHORT: + return FX_SHORT(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_USHORT: + return FX_USHORT(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_INT: + return FX_INT(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_UINT: + return FX_UINT(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_LONG: + return FX_LONG(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_ULONG: + return FX_ULONG(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_LONGLONG: + return FX_LONGLONG(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_ULONGLONG: + return FX_ULONGLONG(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_SIZE: + return FX_SIZE(callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_FLOAT: + return FX_FLOAT(callvm_invoke_d(impl, vm)); + case __FX_VALUE_TYPE_DOUBLE: + return FX_DOUBLE(callvm_invoke_d(impl, vm)); + case __FX_VALUE_TYPE_CSTR: + return FX_CSTR((const char *)callvm_invoke_i(impl, vm)); + case __FX_VALUE_TYPE_POINTER: + return FX_POINTER((void *)callvm_invoke_i(impl, vm)); + default: + return FX_VALUE_EMPTY; + } } diff --git a/fx.reflection/sys/apple/aarch64/include/platform/callvm.h b/fx.reflection/sys/apple/aarch64/include/platform/callvm.h index a75c1aa..6e0b10d 100644 --- a/fx.reflection/sys/apple/aarch64/include/platform/callvm.h +++ b/fx.reflection/sys/apple/aarch64/include/platform/callvm.h @@ -5,6 +5,11 @@ #include #include +#define CALLVM_INVOKE_PROTOTYPE(suffix) \ + fx_value callvm_invoke_##suffix( \ + struct callvm *vm, \ + fx_function_impl impl) + #define MAX_FIXED_ARGS ((unsigned int)-1) #define MAX_DOUBLE_ARGS 8 #define MAX_INT_ARGS 8 @@ -26,11 +31,13 @@ struct callvm { uintptr_t *vm_arg_excess; }; +typedef fx_value (*callvm_invoke_impl)(struct callvm *, fx_function_impl); + extern void callvm_reset(struct callvm *vm, unsigned int max_fixed_args); extern void callvm_push(struct callvm *vm, const fx_value *value); extern fx_value callvm_invoke( struct callvm *vm, fx_function_impl impl, - fx_value_type return_type); + fx_type_id return_type); #endif