diff options
author | Richard Henderson <rth@redhat.com> | 2014-10-23 00:26:14 -0400 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2014-11-12 09:29:32 +0100 |
commit | c6352b664c31835b9527d747f8a29b4754cabb0e (patch) | |
tree | 78beb1fbde6e0cfe89727ea3a2ba53a1cadc93f3 /src/aarch64 | |
parent | 0e41c73b092064e986d484270a13046479d6bda3 (diff) | |
download | libffi-c6352b664c31835b9527d747f8a29b4754cabb0e.tar.gz |
aarch64: Add support for Go closures
Diffstat (limited to 'src/aarch64')
-rw-r--r-- | src/aarch64/ffi.c | 52 | ||||
-rw-r--r-- | src/aarch64/ffitarget.h | 4 | ||||
-rw-r--r-- | src/aarch64/sysv.S | 62 |
3 files changed, 112 insertions, 6 deletions
diff --git a/src/aarch64/ffi.c b/src/aarch64/ffi.c index f546ab2..0cace9d 100644 --- a/src/aarch64/ffi.c +++ b/src/aarch64/ffi.c @@ -539,13 +539,14 @@ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, #endif /* __APPLE__ */ extern void ffi_call_SYSV (struct call_context *context, void *frame, - void (*fn)(void), void *rvalue, int flags) - FFI_HIDDEN; + void (*fn)(void), void *rvalue, int flags, + void *closure) FFI_HIDDEN; /* Call a function with the provided arguments and capture the return value. */ -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, void **avalue) +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, + void **avalue, void *closure) { struct call_context *context; void *stack, *frame, *rvalue; @@ -698,12 +699,27 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, void **avalue) #endif } - ffi_call_SYSV (context, frame, fn, rvalue, flags); + ffi_call_SYSV (context, frame, fn, rvalue, flags, closure); if (flags & AARCH64_RET_NEED_COPY) memcpy (orig_rvalue, rvalue, rtype_size); } +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +#ifdef FFI_GO_CLOSURES +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} +#endif /* FFI_GO_CLOSURES */ + /* Build a trampoline. */ extern void ffi_closure_SYSV (void) FFI_HIDDEN; @@ -744,6 +760,32 @@ ffi_prep_closure_loc (ffi_closure *closure, return FFI_OK; } +#ifdef FFI_GO_CLOSURES +extern void ffi_go_closure_SYSV (void) FFI_HIDDEN; +extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN; + +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + void (*start)(void); + + if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; + + if (cif->flags & AARCH64_FLAG_ARG_V) + start = ffi_go_closure_SYSV_V; + else + start = ffi_go_closure_SYSV; + + closure->tramp = start; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} +#endif /* FFI_GO_CLOSURES */ + /* Primary handler to setup and invoke a function within a closure. A closure when invoked enters via the assembler wrapper diff --git a/src/aarch64/ffitarget.h b/src/aarch64/ffitarget.h index 7461386..80d09af 100644 --- a/src/aarch64/ffitarget.h +++ b/src/aarch64/ffitarget.h @@ -50,6 +50,10 @@ typedef enum ffi_abi #if defined (__APPLE__) #define FFI_TARGET_SPECIFIC_VARIADIC #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs +#else +/* iOS reserves x18 for the system. Disable Go closures until + a new static chain is chosen. */ +#define FFI_GO_CLOSURES 1 #endif #define FFI_TARGET_HAS_COMPLEX_TYPE diff --git a/src/aarch64/sysv.S b/src/aarch64/sysv.S index 7f00a3f..1fb68f2 100644 --- a/src/aarch64/sysv.S +++ b/src/aarch64/sysv.S @@ -50,7 +50,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* ffi_call_SYSV extern void ffi_call_SYSV (void *stack, void *frame, - void (*fn)(void), void *rvalue, int flags); + void (*fn)(void), void *rvalue, + int flags, void *closure); Therefore on entry we have: @@ -59,6 +60,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ x2 fn x3 rvalue x4 flags + x5 closure */ cfi_startproc @@ -74,6 +76,9 @@ CNAME(ffi_call_SYSV): mov x9, x2 /* save fn */ mov x8, x3 /* install structure return */ +#ifdef FFI_GO_CLOSURES + mov x18, x5 /* install static chain */ +#endif stp x3, x4, [x29, #16] /* save rvalue and flags */ /* Load the vector argument passing registers, if necessary. */ @@ -245,6 +250,7 @@ CNAME(ffi_closure_SYSV): /* Load ffi_closure_inner arguments. */ ldp x0, x1, [x17, #FFI_TRAMPOLINE_SIZE] /* load cif, fn */ ldr x2, [x17, #FFI_TRAMPOLINE_SIZE+16] /* load user_data */ +.Ldo_closure: add x3, sp, #16 /* load context */ add x4, sp, #ffi_closure_SYSV_FS /* load stack */ add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */ @@ -336,3 +342,57 @@ CNAME(ffi_closure_SYSV): .hidden CNAME(ffi_closure_SYSV) .size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV) #endif + +#ifdef FFI_GO_CLOSURES + .align 4 +CNAME(ffi_go_closure_SYSV_V): + cfi_startproc + stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + b 0f + cfi_endproc + + .globl CNAME(ffi_go_closure_SYSV_V) +#ifdef __ELF__ + .type CNAME(ffi_go_closure_SYSV_V), #function + .hidden CNAME(ffi_go_closure_SYSV_V) + .size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V) +#endif + + .align 4 + cfi_startproc +CNAME(ffi_go_closure_SYSV): + stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) +0: + mov x29, sp + + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp x0, x1, [x18, #8] /* load cif, fn */ + mov x2, x18 /* load user_data */ + b .Ldo_closure + cfi_endproc + + .globl CNAME(ffi_go_closure_SYSV) +#ifdef __ELF__ + .type CNAME(ffi_go_closure_SYSV), #function + .hidden CNAME(ffi_go_closure_SYSV) + .size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV) +#endif +#endif /* FFI_GO_CLOSURES */ |