#include #include #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; vm->vm_double_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++; if (vm->vm_arg_count > vm->vm_arg_fixed) { vm->vm_double_excess_count++; } } void callvm_push(struct callvm* vm, const fx_value* value) { 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; }