build: add module to handle querying platform details
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
#include <platform/callvm.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if 0
|
||||
switch (arg->v_type.t_primitive) {
|
||||
case FX_VALUE_TYPE_DOUBLE:
|
||||
break;
|
||||
default:
|
||||
callvm_push_int(&vm, (uintptr_t)arg->v_pointer);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
void callvm_reset(struct callvm *vm, unsigned int max_fixed_args)
|
||||
{
|
||||
vm->vm_arg_int_count = 0;
|
||||
vm->vm_arg_double_count = 0;
|
||||
vm->vm_arg_fixed = max_fixed_args;
|
||||
vm->vm_arg_excess_count = 0;
|
||||
}
|
||||
|
||||
static void expand_excess(struct callvm *vm)
|
||||
{
|
||||
size_t new_capacity = vm->vm_arg_excess_max * 2;
|
||||
if (!new_capacity) {
|
||||
new_capacity = 4;
|
||||
}
|
||||
|
||||
void *buf = realloc(
|
||||
vm->vm_arg_excess,
|
||||
new_capacity * sizeof *vm->vm_arg_excess);
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
vm->vm_arg_excess = buf;
|
||||
vm->vm_arg_excess_max = new_capacity;
|
||||
}
|
||||
|
||||
static void push_excess(struct callvm *vm, uintptr_t value)
|
||||
{
|
||||
if (vm->vm_arg_excess_count + 1 > vm->vm_arg_excess_max) {
|
||||
expand_excess(vm);
|
||||
}
|
||||
|
||||
vm->vm_arg_excess[vm->vm_arg_excess_count++] = value;
|
||||
vm->vm_arg_count++;
|
||||
}
|
||||
|
||||
static void push_int(struct callvm *vm, uintptr_t value)
|
||||
{
|
||||
if (vm->vm_arg_int_count >= MAX_INT_ARGS) {
|
||||
push_excess(vm, value);
|
||||
return;
|
||||
}
|
||||
|
||||
vm->vm_arg_int[vm->vm_arg_int_count++] = value;
|
||||
vm->vm_arg_count++;
|
||||
}
|
||||
|
||||
static void push_double(struct callvm *vm, double value)
|
||||
{
|
||||
if (vm->vm_arg_double_count >= MAX_DOUBLE_ARGS) {
|
||||
push_excess(vm, *(uintptr_t *)&value);
|
||||
return;
|
||||
}
|
||||
|
||||
vm->vm_arg_double[vm->vm_arg_double_count++] = value;
|
||||
vm->vm_arg_count++;
|
||||
}
|
||||
|
||||
void callvm_push(struct callvm *vm, const fx_value *value)
|
||||
{
|
||||
if (vm->vm_arg_count >= vm->vm_arg_fixed) {
|
||||
push_excess(vm, (uintptr_t)value->v_pointer);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (value->v_type.t_primitive) {
|
||||
case FX_VALUE_TYPE_DOUBLE:
|
||||
push_double(vm, value->v_double);
|
||||
break;
|
||||
default:
|
||||
push_int(vm, (uintptr_t)value->v_pointer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extern uintptr_t callvm_invoke_i(fx_function_impl impl, struct callvm *vm);
|
||||
extern double callvm_invoke_d(fx_function_impl impl, struct callvm *vm);
|
||||
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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
return FX_VALUE_EMPTY;
|
||||
}
|
||||
Reference in New Issue
Block a user