sparc: Add support for Go closures
This commit is contained in:
@@ -176,7 +176,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void ffi_call_v8(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
extern void ffi_call_v8(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
void **avalue, size_t bytes) FFI_HIDDEN;
|
void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
|
||||||
|
|
||||||
int FFI_HIDDEN
|
int FFI_HIDDEN
|
||||||
ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
|
ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
|
||||||
@@ -280,8 +280,9 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
{
|
{
|
||||||
size_t bytes = cif->bytes;
|
size_t bytes = cif->bytes;
|
||||||
|
|
||||||
@@ -292,7 +293,20 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
if (rvalue == NULL && cif->flags == SPARC_RET_STRUCT)
|
if (rvalue == NULL && cif->flags == SPARC_RET_STRUCT)
|
||||||
bytes += ALIGN (cif->rtype->size, 8);
|
bytes += ALIGN (cif->rtype->size, 8);
|
||||||
|
|
||||||
ffi_call_v8(cif, fn, rvalue, avalue, -bytes);
|
ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
|
{
|
||||||
|
ffi_call_int (cif, fn, rvalue, avalue, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
|
{
|
||||||
|
ffi_call_int (cif, fn, rvalue, avalue, closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
@@ -308,6 +322,7 @@ extern void ffi_flush_icache (void *) FFI_HIDDEN;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void ffi_closure_v8(void) FFI_HIDDEN;
|
extern void ffi_closure_v8(void) FFI_HIDDEN;
|
||||||
|
extern void ffi_go_closure_v8(void) FFI_HIDDEN;
|
||||||
|
|
||||||
ffi_status
|
ffi_status
|
||||||
ffi_prep_closure_loc (ffi_closure *closure,
|
ffi_prep_closure_loc (ffi_closure *closure,
|
||||||
@@ -337,16 +352,30 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|||||||
return FFI_OK;
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffi_status
|
||||||
|
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
|
||||||
|
void (*fun)(ffi_cif*, void*, void**, void*))
|
||||||
|
{
|
||||||
|
if (cif->abi != FFI_V8)
|
||||||
|
return FFI_BAD_ABI;
|
||||||
|
|
||||||
|
closure->tramp = ffi_go_closure_v8;
|
||||||
|
closure->cif = cif;
|
||||||
|
closure->fun = fun;
|
||||||
|
|
||||||
|
return FFI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int FFI_HIDDEN
|
int FFI_HIDDEN
|
||||||
ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
|
ffi_closure_sparc_inner_v8(ffi_cif *cif,
|
||||||
|
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||||
|
void *user_data, void *rvalue,
|
||||||
unsigned long *argp)
|
unsigned long *argp)
|
||||||
{
|
{
|
||||||
ffi_cif *cif;
|
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
void **avalue;
|
void **avalue;
|
||||||
int i, nargs, flags;
|
int i, nargs, flags;
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
arg_types = cif->arg_types;
|
arg_types = cif->arg_types;
|
||||||
nargs = cif->nargs;
|
nargs = cif->nargs;
|
||||||
flags = cif->flags;
|
flags = cif->flags;
|
||||||
@@ -424,7 +453,7 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke the closure. */
|
/* Invoke the closure. */
|
||||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
fun (cif, rvalue, avalue, user_data);
|
||||||
|
|
||||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||||
return flags;
|
return flags;
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
void **avalue, size_t bytes) FFI_HIDDEN;
|
void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
|
||||||
|
|
||||||
/* ffi_prep_args is called by the assembly routine once stack space
|
/* ffi_prep_args is called by the assembly routine once stack space
|
||||||
has been allocated for the function's arguments */
|
has been allocated for the function's arguments */
|
||||||
@@ -402,8 +402,9 @@ ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
{
|
{
|
||||||
size_t bytes = cif->bytes;
|
size_t bytes = cif->bytes;
|
||||||
|
|
||||||
@@ -412,7 +413,20 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
|
if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
|
||||||
bytes += ALIGN (cif->rtype->size, 16);
|
bytes += ALIGN (cif->rtype->size, 16);
|
||||||
|
|
||||||
ffi_call_v9(cif, fn, rvalue, avalue, -bytes);
|
ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
|
{
|
||||||
|
ffi_call_int(cif, fn, rvalue, avalue, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
|
{
|
||||||
|
ffi_call_int(cif, fn, rvalue, avalue, closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
@@ -426,6 +440,7 @@ extern void ffi_flush_icache (void *) FFI_HIDDEN;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void ffi_closure_v9(void) FFI_HIDDEN;
|
extern void ffi_closure_v9(void) FFI_HIDDEN;
|
||||||
|
extern void ffi_go_closure_v9(void) FFI_HIDDEN;
|
||||||
|
|
||||||
ffi_status
|
ffi_status
|
||||||
ffi_prep_closure_loc (ffi_closure* closure,
|
ffi_prep_closure_loc (ffi_closure* closure,
|
||||||
@@ -458,16 +473,30 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||||||
return FFI_OK;
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffi_status
|
||||||
|
ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
|
||||||
|
void (*fun)(ffi_cif*, void*, void**, void*))
|
||||||
|
{
|
||||||
|
if (cif->abi != FFI_V9)
|
||||||
|
return FFI_BAD_ABI;
|
||||||
|
|
||||||
|
closure->tramp = ffi_go_closure_v9;
|
||||||
|
closure->cif = cif;
|
||||||
|
closure->fun = fun;
|
||||||
|
|
||||||
|
return FFI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int FFI_HIDDEN
|
int FFI_HIDDEN
|
||||||
ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
|
ffi_closure_sparc_inner_v9(ffi_cif *cif,
|
||||||
|
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||||
|
void *user_data, void *rvalue,
|
||||||
unsigned long *gpr, unsigned long *fpr)
|
unsigned long *gpr, unsigned long *fpr)
|
||||||
{
|
{
|
||||||
ffi_cif *cif;
|
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
void **avalue;
|
void **avalue;
|
||||||
int i, argn, argx, nargs, flags;
|
int i, argn, argx, nargs, flags;
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
arg_types = cif->arg_types;
|
arg_types = cif->arg_types;
|
||||||
nargs = cif->nargs;
|
nargs = cif->nargs;
|
||||||
flags = cif->flags;
|
flags = cif->flags;
|
||||||
@@ -555,7 +584,7 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke the closure. */
|
/* Invoke the closure. */
|
||||||
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
fun (cif, rvalue, avalue, user_data);
|
||||||
|
|
||||||
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
/* Tell ffi_closure_sparc how to perform return type promotions. */
|
||||||
return flags;
|
return flags;
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ typedef enum ffi_abi {
|
|||||||
/* ---- Definitions for closures ----------------------------------------- */
|
/* ---- Definitions for closures ----------------------------------------- */
|
||||||
|
|
||||||
#define FFI_CLOSURES 1
|
#define FFI_CLOSURES 1
|
||||||
|
#define FFI_GO_CLOSURES 1
|
||||||
#define FFI_NATIVE_RAW_API 0
|
#define FFI_NATIVE_RAW_API 0
|
||||||
|
|
||||||
#ifdef SPARC64
|
#ifdef SPARC64
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ C(ffi_call_v8):
|
|||||||
|
|
||||||
! Call foreign function
|
! Call foreign function
|
||||||
call %i1
|
call %i1
|
||||||
nop
|
mov %i5, %g2 ! load static chain
|
||||||
|
|
||||||
0: call 1f ! load pc in %o7
|
0: call 1f ! load pc in %o7
|
||||||
sll %l0, 4, %l0
|
sll %l0, 4, %l0
|
||||||
@@ -185,7 +185,7 @@ E SPARC_RET_F_1
|
|||||||
! Struct returning functions expect and skip the unimp here.
|
! Struct returning functions expect and skip the unimp here.
|
||||||
.align 8
|
.align 8
|
||||||
8: call %i1
|
8: call %i1
|
||||||
nop
|
mov %i5, %g2 ! load static chain
|
||||||
unimp 4
|
unimp 4
|
||||||
ret
|
ret
|
||||||
restore
|
restore
|
||||||
@@ -211,20 +211,43 @@ E SPARC_RET_F_1
|
|||||||
|
|
||||||
Receives the closure argument in %g2. */
|
Receives the closure argument in %g2. */
|
||||||
|
|
||||||
|
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
|
||||||
|
.register %g2, #scratch
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
.globl C(ffi_go_closure_v8)
|
||||||
|
.type C(ffi_go_closure_v8),@function
|
||||||
|
FFI_HIDDEN(C(ffi_go_closure_v8))
|
||||||
|
|
||||||
|
C(ffi_go_closure_v8):
|
||||||
|
cfi_startproc
|
||||||
|
save %sp, -STACKFRAME, %sp
|
||||||
|
cfi_def_cfa_register(%fp)
|
||||||
|
cfi_window_save
|
||||||
|
|
||||||
|
ld [%g2+4], %o0 ! load cif
|
||||||
|
ld [%g2+8], %o1 ! load fun
|
||||||
|
b 0f
|
||||||
|
mov %g2, %o2 ! load user_data
|
||||||
|
cfi_endproc
|
||||||
|
.size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
|
||||||
|
|
||||||
.align 8
|
.align 8
|
||||||
.globl C(ffi_closure_v8)
|
.globl C(ffi_closure_v8)
|
||||||
.type C(ffi_closure_v8),@function
|
.type C(ffi_closure_v8),@function
|
||||||
FFI_HIDDEN(C(ffi_closure_v8))
|
FFI_HIDDEN(C(ffi_closure_v8))
|
||||||
|
|
||||||
C(ffi_closure_v8):
|
C(ffi_closure_v8):
|
||||||
#ifdef HAVE_AS_REGISTER_PSEUDO_OP
|
|
||||||
.register %g2, #scratch
|
|
||||||
#endif
|
|
||||||
cfi_startproc
|
cfi_startproc
|
||||||
save %sp, -STACKFRAME, %sp
|
save %sp, -STACKFRAME, %sp
|
||||||
cfi_def_cfa_register(%fp)
|
cfi_def_cfa_register(%fp)
|
||||||
cfi_window_save
|
cfi_window_save
|
||||||
|
|
||||||
|
ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
|
||||||
|
ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
|
||||||
|
ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data
|
||||||
|
0:
|
||||||
! Store all of the potential argument registers in va_list format.
|
! Store all of the potential argument registers in va_list format.
|
||||||
st %i0, [%fp+68+0]
|
st %i0, [%fp+68+0]
|
||||||
st %i1, [%fp+68+4]
|
st %i1, [%fp+68+4]
|
||||||
@@ -234,10 +257,9 @@ C(ffi_closure_v8):
|
|||||||
st %i5, [%fp+68+20]
|
st %i5, [%fp+68+20]
|
||||||
|
|
||||||
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
||||||
mov %g2, %o0
|
add %fp, -8*4, %o3
|
||||||
add %fp, -8*4, %o1
|
|
||||||
call ffi_closure_sparc_inner_v8
|
call ffi_closure_sparc_inner_v8
|
||||||
add %fp, 64, %o2
|
add %fp, 64, %o4
|
||||||
|
|
||||||
0: call 1f
|
0: call 1f
|
||||||
and %o0, SPARC_FLAG_RET_MASK, %o0
|
and %o0, SPARC_FLAG_RET_MASK, %o0
|
||||||
|
|||||||
@@ -94,8 +94,9 @@ C(ffi_call_v9):
|
|||||||
ldx [%sp+STACK_BIAS+128+16], %o2
|
ldx [%sp+STACK_BIAS+128+16], %o2
|
||||||
ldx [%sp+STACK_BIAS+128+24], %o3
|
ldx [%sp+STACK_BIAS+128+24], %o3
|
||||||
ldx [%sp+STACK_BIAS+128+32], %o4
|
ldx [%sp+STACK_BIAS+128+32], %o4
|
||||||
|
ldx [%sp+STACK_BIAS+128+40], %o5
|
||||||
call %i1
|
call %i1
|
||||||
ldx [%sp+STACK_BIAS+128+40], %o5
|
mov %i5, %g5 ! load static chain
|
||||||
|
|
||||||
0: call 1f ! load pc in %o7
|
0: call 1f ! load pc in %o7
|
||||||
and %l0, SPARC_FLAG_RET_MASK, %l1
|
and %l0, SPARC_FLAG_RET_MASK, %l1
|
||||||
@@ -210,6 +211,25 @@ E SPARC_RET_F_1
|
|||||||
|
|
||||||
Receives the closure argument in %g1. */
|
Receives the closure argument in %g1. */
|
||||||
|
|
||||||
|
.align 8
|
||||||
|
.globl C(ffi_go_closure_v9)
|
||||||
|
.type C(ffi_go_closure_v9),@function
|
||||||
|
FFI_HIDDEN(C(ffi_go_closure_v9))
|
||||||
|
|
||||||
|
C(ffi_go_closure_v9):
|
||||||
|
cfi_startproc
|
||||||
|
save %sp, -STACKFRAME, %sp
|
||||||
|
cfi_def_cfa_register(%fp)
|
||||||
|
cfi_window_save
|
||||||
|
|
||||||
|
ldx [%g5+8], %o0
|
||||||
|
ldx [%g5+16], %o1
|
||||||
|
b 0f
|
||||||
|
mov %g5, %o2
|
||||||
|
|
||||||
|
cfi_endproc
|
||||||
|
.size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9)
|
||||||
|
|
||||||
.align 8
|
.align 8
|
||||||
.globl C(ffi_closure_v9)
|
.globl C(ffi_closure_v9)
|
||||||
.type C(ffi_closure_v9),@function
|
.type C(ffi_closure_v9),@function
|
||||||
@@ -221,6 +241,10 @@ C(ffi_closure_v9):
|
|||||||
cfi_def_cfa_register(%fp)
|
cfi_def_cfa_register(%fp)
|
||||||
cfi_window_save
|
cfi_window_save
|
||||||
|
|
||||||
|
ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0
|
||||||
|
ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1
|
||||||
|
ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2
|
||||||
|
0:
|
||||||
! Store all of the potential argument registers in va_list format.
|
! Store all of the potential argument registers in va_list format.
|
||||||
stx %i0, [FP+128+0]
|
stx %i0, [FP+128+0]
|
||||||
stx %i1, [FP+128+8]
|
stx %i1, [FP+128+8]
|
||||||
@@ -248,11 +272,10 @@ C(ffi_closure_v9):
|
|||||||
std %f30, [FP-8]
|
std %f30, [FP-8]
|
||||||
|
|
||||||
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
! Call ffi_closure_sparc_inner to do the bulk of the work.
|
||||||
mov %g1, %o0
|
add %fp, STACK_BIAS-160, %o3
|
||||||
add %fp, STACK_BIAS-160, %o1
|
add %fp, STACK_BIAS+128, %o4
|
||||||
add %fp, STACK_BIAS+128, %o2
|
|
||||||
call C(ffi_closure_sparc_inner_v9)
|
call C(ffi_closure_sparc_inner_v9)
|
||||||
add %fp, STACK_BIAS-128, %o3
|
add %fp, STACK_BIAS-128, %o5
|
||||||
|
|
||||||
0: call 1f ! load pc in %o7
|
0: call 1f ! load pc in %o7
|
||||||
and %o0, SPARC_FLAG_RET_MASK, %o0
|
and %o0, SPARC_FLAG_RET_MASK, %o0
|
||||||
|
|||||||
Reference in New Issue
Block a user