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__ */
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
extern void ffi_call_SYSV (struct call_context *context, void *frame,
|
extern void ffi_call_SYSV (struct call_context *context, void *frame,
|
||||||
void (*fn)(void), void *rvalue, int flags)
|
void (*fn)(void), void *rvalue, int flags,
|
||||||
FFI_HIDDEN;
|
void *closure) FFI_HIDDEN;
|
||||||
|
|
||||||
/* Call a function with the provided arguments and capture the return
|
/* Call a function with the provided arguments and capture the return
|
||||||
value. */
|
value. */
|
||||||
void
|
static void
|
||||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, void **avalue)
|
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
{
|
{
|
||||||
struct call_context *context;
|
struct call_context *context;
|
||||||
void *stack, *frame, *rvalue;
|
void *stack, *frame, *rvalue;
|
||||||
@@ -698,12 +699,27 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, void **avalue)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ffi_call_SYSV (context, frame, fn, rvalue, flags);
|
ffi_call_SYSV (context, frame, fn, rvalue, flags, closure);
|
||||||
|
|
||||||
if (flags & AARCH64_RET_NEED_COPY)
|
if (flags & AARCH64_RET_NEED_COPY)
|
||||||
memcpy (orig_rvalue, rvalue, rtype_size);
|
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. */
|
/* Build a trampoline. */
|
||||||
|
|
||||||
extern void ffi_closure_SYSV (void) FFI_HIDDEN;
|
extern void ffi_closure_SYSV (void) FFI_HIDDEN;
|
||||||
@@ -744,6 +760,32 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|||||||
return FFI_OK;
|
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.
|
/* Primary handler to setup and invoke a function within a closure.
|
||||||
|
|
||||||
A closure when invoked enters via the assembler wrapper
|
A closure when invoked enters via the assembler wrapper
|
||||||
|
|||||||
@@ -50,6 +50,10 @@ typedef enum ffi_abi
|
|||||||
#if defined (__APPLE__)
|
#if defined (__APPLE__)
|
||||||
#define FFI_TARGET_SPECIFIC_VARIADIC
|
#define FFI_TARGET_SPECIFIC_VARIADIC
|
||||||
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
|
#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
|
#endif
|
||||||
|
|
||||||
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
#define FFI_TARGET_HAS_COMPLEX_TYPE
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||||||
|
|
||||||
/* ffi_call_SYSV
|
/* ffi_call_SYSV
|
||||||
extern void ffi_call_SYSV (void *stack, void *frame,
|
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:
|
Therefore on entry we have:
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|||||||
x2 fn
|
x2 fn
|
||||||
x3 rvalue
|
x3 rvalue
|
||||||
x4 flags
|
x4 flags
|
||||||
|
x5 closure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cfi_startproc
|
cfi_startproc
|
||||||
@@ -74,6 +76,9 @@ CNAME(ffi_call_SYSV):
|
|||||||
|
|
||||||
mov x9, x2 /* save fn */
|
mov x9, x2 /* save fn */
|
||||||
mov x8, x3 /* install structure return */
|
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 */
|
stp x3, x4, [x29, #16] /* save rvalue and flags */
|
||||||
|
|
||||||
/* Load the vector argument passing registers, if necessary. */
|
/* Load the vector argument passing registers, if necessary. */
|
||||||
@@ -245,6 +250,7 @@ CNAME(ffi_closure_SYSV):
|
|||||||
/* Load ffi_closure_inner arguments. */
|
/* Load ffi_closure_inner arguments. */
|
||||||
ldp x0, x1, [x17, #FFI_TRAMPOLINE_SIZE] /* load cif, fn */
|
ldp x0, x1, [x17, #FFI_TRAMPOLINE_SIZE] /* load cif, fn */
|
||||||
ldr x2, [x17, #FFI_TRAMPOLINE_SIZE+16] /* load user_data */
|
ldr x2, [x17, #FFI_TRAMPOLINE_SIZE+16] /* load user_data */
|
||||||
|
.Ldo_closure:
|
||||||
add x3, sp, #16 /* load context */
|
add x3, sp, #16 /* load context */
|
||||||
add x4, sp, #ffi_closure_SYSV_FS /* load stack */
|
add x4, sp, #ffi_closure_SYSV_FS /* load stack */
|
||||||
add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
|
add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */
|
||||||
@@ -336,3 +342,57 @@ CNAME(ffi_closure_SYSV):
|
|||||||
.hidden CNAME(ffi_closure_SYSV)
|
.hidden CNAME(ffi_closure_SYSV)
|
||||||
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
|
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
|
||||||
#endif
|
#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