Compare commits
4 Commits
18c9d30c60
...
7058a14be0
| Author | SHA1 | Date | |
|---|---|---|---|
| 7058a14be0 | |||
| bf251dd818 | |||
| bebc67537d | |||
| e954a15d92 |
@@ -1,6 +1,64 @@
|
|||||||
BasedOnStyle: WebKit
|
BasedOnStyle: WebKit
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
---
|
---
|
||||||
|
Language: C
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Right
|
||||||
|
ColumnLimit: 80
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignConsecutiveAssignments: None
|
||||||
|
AlignConsecutiveBitFields: None
|
||||||
|
AlignConsecutiveDeclarations: None
|
||||||
|
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: AlignAfterOperator
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLambdasOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
BreakBeforeBinaryOperators: All
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakInheritanceList: BeforeComma
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
IncludeBlocks: Regroup
|
||||||
|
SortIncludes: true
|
||||||
|
IndentRequires: true
|
||||||
|
NamespaceIndentation: Inner
|
||||||
|
ReflowComments: true
|
||||||
|
SpacesBeforeTrailingComments: 3
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: AlignWithSpaces
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||||
|
PenaltyExcessCharacter: 5
|
||||||
|
PenaltyBreakOpenParenthesis: 5
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 5
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
|
AttributeMacros:
|
||||||
|
- FX_API
|
||||||
|
ForEachMacros:
|
||||||
|
- fx_btree_foreach
|
||||||
|
- fx_queue_foreach
|
||||||
|
MacroBlockBegin: "FX_(TYPE|ASSEMBLY)_.*_BEGIN"
|
||||||
|
MacroBlockEnd: "FX_(TYPE|ASSEMBLY)_.*_END"
|
||||||
|
---
|
||||||
Language: ObjC
|
Language: ObjC
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
|
|||||||
@@ -1,221 +0,0 @@
|
|||||||
.global _fx_function_invoke_i
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
# x0 = (function ptr) impl
|
|
||||||
# x1 = (fx_value[]) args
|
|
||||||
# x2 = (size_t) nr args
|
|
||||||
_fx_function_invoke_i:
|
|
||||||
# save the stack frame and link pointer
|
|
||||||
stp x29, x30, [sp, #-16]!
|
|
||||||
|
|
||||||
# store function pointer for later
|
|
||||||
str x0, [sp, #-16]!
|
|
||||||
# move arg array of of x1 and x2, so that they can be initialised for
|
|
||||||
# the function call
|
|
||||||
mov x8, x1
|
|
||||||
mov x9, x2
|
|
||||||
|
|
||||||
# arg[0]
|
|
||||||
cmp x9, #0
|
|
||||||
ble .i.done
|
|
||||||
ldr x0, [x8, #8]
|
|
||||||
|
|
||||||
# arg[1]
|
|
||||||
cmp x9, #1
|
|
||||||
ble .i.done
|
|
||||||
ldr x1, [x8, #24]
|
|
||||||
|
|
||||||
# arg[2]
|
|
||||||
cmp x9, #2
|
|
||||||
ble .i.done
|
|
||||||
ldr x2, [x8, #40]
|
|
||||||
|
|
||||||
# arg[3]
|
|
||||||
cmp x9, #3
|
|
||||||
ble .i.done
|
|
||||||
ldr x3, [x8, #56]
|
|
||||||
|
|
||||||
# arg[4]
|
|
||||||
cmp x9, #4
|
|
||||||
ble .i.done
|
|
||||||
ldr x4, [x8, #72]
|
|
||||||
|
|
||||||
# arg[5]
|
|
||||||
cmp x9, #5
|
|
||||||
ble .i.done
|
|
||||||
ldr x5, [x8, #88]
|
|
||||||
|
|
||||||
# arg[6]
|
|
||||||
cmp x9, #6
|
|
||||||
ble .i.done
|
|
||||||
ldr x6, [x8, #104]
|
|
||||||
|
|
||||||
# arg[7]
|
|
||||||
cmp x9, #7
|
|
||||||
ble .i.done
|
|
||||||
ldr x7, [x8, #120]
|
|
||||||
|
|
||||||
.i.done:
|
|
||||||
ldr x8, [sp], #16
|
|
||||||
blr x8
|
|
||||||
|
|
||||||
# restore the saved stack frame and link pointer
|
|
||||||
ldp x29,x30, [sp], #16
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.global _fx_function_invoke_d
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_fx_function_invoke_d:
|
|
||||||
mov x0, 888
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.global _fx_function_invoke_v
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_fx_function_invoke_v:
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.global _fx_function_invoke_iv
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
# x0 = (function ptr) impl
|
|
||||||
# x1 = (fx_value[]) args
|
|
||||||
# x2 = (size_t) nr fixed args
|
|
||||||
# x3 = (size_t) nr var args
|
|
||||||
_fx_function_invoke_iv:
|
|
||||||
# save the stack frame and link pointer
|
|
||||||
stp x29, x30, [sp, #-16]!
|
|
||||||
mov x29, sp
|
|
||||||
|
|
||||||
# store function pointer for later
|
|
||||||
mov x15, x0
|
|
||||||
# move arg array of of x1,x2,x3, so that they can be initialised for
|
|
||||||
# the function call
|
|
||||||
mov x9, x1
|
|
||||||
mov x10, x2
|
|
||||||
mov x11, x3
|
|
||||||
|
|
||||||
# First, set up the fixed arguments
|
|
||||||
|
|
||||||
# arg[0]
|
|
||||||
cmp x10, #0
|
|
||||||
ble .iv.done
|
|
||||||
ldr x0, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[1]
|
|
||||||
cmp x10, #1
|
|
||||||
ble .iv.done
|
|
||||||
ldr x1, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[2]
|
|
||||||
cmp x10, #2
|
|
||||||
ble .iv.done
|
|
||||||
ldr x2, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[3]
|
|
||||||
cmp x10, #3
|
|
||||||
ble .iv.done
|
|
||||||
ldr x3, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[4]
|
|
||||||
cmp x10, #4
|
|
||||||
ble .iv.done
|
|
||||||
ldr x4, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[5]
|
|
||||||
cmp x10, #5
|
|
||||||
ble .iv.done
|
|
||||||
ldr x5, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[6]
|
|
||||||
cmp x10, #6
|
|
||||||
ble .iv.done
|
|
||||||
ldr x6, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
# arg[7]
|
|
||||||
cmp x10, #7
|
|
||||||
ble .iv.done
|
|
||||||
ldr x7, [x9, #8]
|
|
||||||
add x9, x9, #16
|
|
||||||
|
|
||||||
.iv.done:
|
|
||||||
# Next, set up the variable arguments
|
|
||||||
|
|
||||||
# calculate the amount of stack space needed for the varargs
|
|
||||||
mov x10, #0x10
|
|
||||||
mul x12, x11, x10
|
|
||||||
#and x12, x12, #0x10
|
|
||||||
#mov x10, #0x10
|
|
||||||
#add x12, x12, x10
|
|
||||||
|
|
||||||
# x19 is caller-saved, and we'll need x12 later
|
|
||||||
str x19, [sp, #-16]!
|
|
||||||
mov x19, x12
|
|
||||||
|
|
||||||
# allocate the stack space
|
|
||||||
sub sp, sp, x19
|
|
||||||
mov x13, sp
|
|
||||||
|
|
||||||
# get a pointer to the end of the stack vararg buffer
|
|
||||||
#mov x14, #8
|
|
||||||
#mul x14, x14, x11
|
|
||||||
#add x13, x13, x14
|
|
||||||
|
|
||||||
# x9: arg src buffer (starts at varargs, increments with every iteration)
|
|
||||||
# x11: number of var args (decrements with every iteration)
|
|
||||||
# x13: var arg dest pointer (starts at the end, decrements with every iteration)
|
|
||||||
.iv.loop:
|
|
||||||
cmp x11, #0
|
|
||||||
beq .iv.loop.end
|
|
||||||
|
|
||||||
# read the arg value from the src pointer
|
|
||||||
ldr x14, [x9, #8]
|
|
||||||
|
|
||||||
# write it to the stack, and increment the dest pointer
|
|
||||||
str x14, [x13]
|
|
||||||
add x13, x13, #8
|
|
||||||
|
|
||||||
# increment the src pointer, decrement the arg count
|
|
||||||
sub x11, x11, #1
|
|
||||||
add x9, x9, #16
|
|
||||||
b .iv.loop
|
|
||||||
.iv.loop.end:
|
|
||||||
|
|
||||||
# call the function implementation
|
|
||||||
blr x15
|
|
||||||
|
|
||||||
# de-allocate the stack varargs buffer (the size is now stored in x19)
|
|
||||||
add sp, sp, x19
|
|
||||||
|
|
||||||
# restore the saved value of x19,
|
|
||||||
ldr x19, [sp], #16
|
|
||||||
|
|
||||||
# restore the saved stack frame and link pointer
|
|
||||||
ldp x29,x30, [sp], #16
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.global _fx_function_invoke_dv
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_fx_function_invoke_dv:
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
.global _fx_function_invoke_vv
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_fx_function_invoke_vv:
|
|
||||||
ret
|
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
.extern memcpy
|
||||||
|
.type memcpy, @function
|
||||||
|
|
||||||
|
.global callvm_invoke_i
|
||||||
|
.type callvm_invoke_i, @function
|
||||||
|
|
||||||
|
# %rdi = (function ptr) impl
|
||||||
|
# %rsi = (struct callvm) context
|
||||||
|
callvm_invoke_i:
|
||||||
|
# save the stack frame pointer
|
||||||
|
push %rbp
|
||||||
|
mov %rsp, %rbp
|
||||||
|
|
||||||
|
# store function pointer for later
|
||||||
|
push %r12
|
||||||
|
push %r13
|
||||||
|
push %r14
|
||||||
|
push %r15
|
||||||
|
|
||||||
|
# move our parameters out of the way
|
||||||
|
mov %rdi, %r11
|
||||||
|
mov %rsi, %r12
|
||||||
|
|
||||||
|
# calculate the amount of stack space needed for the varargs
|
||||||
|
movq 32(%r12), %r13
|
||||||
|
shl $3, %r13
|
||||||
|
|
||||||
|
# allocate the stack space
|
||||||
|
push %rsp
|
||||||
|
sub %r13, %rsp
|
||||||
|
andq $0xFFFFFFFFFFFFFFF0, %rsp # re-align the stack
|
||||||
|
|
||||||
|
# copy the excess args to the stack
|
||||||
|
mov %rsp, %rdi
|
||||||
|
mov 160(%r12), %rsi
|
||||||
|
mov %r13, %rdx
|
||||||
|
call memcpy
|
||||||
|
|
||||||
|
# Next, set up the fixed integer arguments
|
||||||
|
|
||||||
|
movq 48(%r12), %rdi # int arg 0
|
||||||
|
movq 56(%r12), %rsi # int arg 1
|
||||||
|
movq 64(%r12), %rdx # int arg 2
|
||||||
|
movq 72(%r12), %rcx # int arg 3
|
||||||
|
movq 80(%r12), %r8 # int arg 4
|
||||||
|
movq 88(%r12), %r9 # int arg 5
|
||||||
|
|
||||||
|
# Finally, set up the fixed double arguments
|
||||||
|
|
||||||
|
movq 96(%r12), %xmm0 # double arg 0
|
||||||
|
movq 104(%r12), %xmm1 # double arg 1
|
||||||
|
movq 112(%r12), %xmm2 # double arg 2
|
||||||
|
movq 120(%r12), %xmm3 # double arg 3
|
||||||
|
movq 128(%r12), %xmm4 # double arg 4
|
||||||
|
movq 136(%r12), %xmm5 # double arg 5
|
||||||
|
movq 144(%r12), %xmm6 # double arg 6
|
||||||
|
movq 152(%r12), %xmm7 # double arg 7
|
||||||
|
|
||||||
|
# set the number of vararg double parameters
|
||||||
|
# as required by the ABI
|
||||||
|
mov 168(%r12), %rax
|
||||||
|
|
||||||
|
# call the function implementation
|
||||||
|
call *%r11
|
||||||
|
|
||||||
|
# Restore the stack pointer (deallocating the varargs buffer)
|
||||||
|
mov -40(%rbp), %rsp
|
||||||
|
|
||||||
|
# Restore callee-saved registers
|
||||||
|
pop %r15
|
||||||
|
pop %r14
|
||||||
|
pop %r13
|
||||||
|
pop %r12
|
||||||
|
|
||||||
|
# restore the saved stack frame
|
||||||
|
pop %rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
.global callvm_invoke_d
|
||||||
|
.type callvm_invoke_d, @function
|
||||||
|
|
||||||
|
# %rdi = (function ptr) impl
|
||||||
|
# %rsi = (struct callvm *) context
|
||||||
|
callvm_invoke_d:
|
||||||
|
jmp callvm_invoke_i
|
||||||
|
|
||||||
|
|
||||||
|
.global callvm_invoke_v
|
||||||
|
.type callvm_invoke_v, @function
|
||||||
|
|
||||||
|
# %rdi = (function ptr) impl
|
||||||
|
# %rsi = (struct callvm *) context
|
||||||
|
callvm_invoke_v:
|
||||||
|
jmp callvm_invoke_i
|
||||||
@@ -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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef FX_REFLECTION_DARWIN_ARM64_CALLVM_H_
|
||||||
|
#define FX_REFLECTION_DARWIN_ARM64_CALLVM_H_
|
||||||
|
|
||||||
|
#include <fx/reflection/function.h>
|
||||||
|
#include <fx/value.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define MAX_FIXED_ARGS ((unsigned int)-1)
|
||||||
|
#define MAX_DOUBLE_ARGS 8
|
||||||
|
#define MAX_INT_ARGS 6
|
||||||
|
|
||||||
|
/* dyn-dispatch.S depends on the layout of this struct */
|
||||||
|
struct callvm {
|
||||||
|
uint64_t vm_arg_int_count;
|
||||||
|
uint64_t vm_arg_double_count;
|
||||||
|
|
||||||
|
/* any args pushed after this limit is reached will be stored in the
|
||||||
|
* excess buffer. used for calling varargs functions */
|
||||||
|
uint64_t vm_arg_count, vm_arg_fixed;
|
||||||
|
|
||||||
|
uint64_t vm_arg_excess_count;
|
||||||
|
uint64_t vm_arg_excess_max;
|
||||||
|
|
||||||
|
uintptr_t vm_arg_int[MAX_INT_ARGS];
|
||||||
|
double vm_arg_double[MAX_DOUBLE_ARGS];
|
||||||
|
uintptr_t *vm_arg_excess;
|
||||||
|
uint64_t vm_double_excess_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user