aarch64: Add support for Go closures
This commit is contained in:
committed by
Richard Henderson
parent
0e41c73b09
commit
c6352b664c
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user