summaryrefslogtreecommitdiff
path: root/src/aarch64
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2014-10-23 00:26:14 -0400
committerRichard Henderson <rth@twiddle.net>2014-11-12 09:29:32 +0100
commitc6352b664c31835b9527d747f8a29b4754cabb0e (patch)
tree78beb1fbde6e0cfe89727ea3a2ba53a1cadc93f3 /src/aarch64
parent0e41c73b092064e986d484270a13046479d6bda3 (diff)
downloadlibffi-c6352b664c31835b9527d747f8a29b4754cabb0e.tar.gz
aarch64: Add support for Go closures
Diffstat (limited to 'src/aarch64')
-rw-r--r--src/aarch64/ffi.c52
-rw-r--r--src/aarch64/ffitarget.h4
-rw-r--r--src/aarch64/sysv.S62
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 */