alpha: Add support for Go closures
This commit is contained in:
@@ -41,9 +41,11 @@
|
|||||||
# define FFI_TYPE_LONGDOUBLE 4
|
# define FFI_TYPE_LONGDOUBLE 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void))
|
extern void ffi_call_osf(void *stack, void *frame, unsigned flags,
|
||||||
FFI_HIDDEN;
|
void *raddr, void (*fn)(void), void *closure)
|
||||||
|
FFI_HIDDEN;
|
||||||
extern void ffi_closure_osf(void) FFI_HIDDEN;
|
extern void ffi_closure_osf(void) FFI_HIDDEN;
|
||||||
|
extern void ffi_go_closure_osf(void) FFI_HIDDEN;
|
||||||
|
|
||||||
/* Promote a float value to its in-register double representation.
|
/* Promote a float value to its in-register double representation.
|
||||||
Unlike actually casting to double, this does not trap on NaN. */
|
Unlike actually casting to double, this does not trap on NaN. */
|
||||||
@@ -222,12 +224,14 @@ extend_basic_type(void *valp, int type, int argn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
unsigned long *argp;
|
unsigned long *argp;
|
||||||
long i, avn, argn, flags = cif->flags;
|
long i, avn, argn, flags = cif->flags;
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
|
void *frame;
|
||||||
|
|
||||||
/* If the return value is a struct and we don't have a return
|
/* If the return value is a struct and we don't have a return
|
||||||
value address then we need to make one. */
|
value address then we need to make one. */
|
||||||
@@ -236,7 +240,8 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
|
|
||||||
/* Allocate the space for the arguments, plus 4 words of temp
|
/* Allocate the space for the arguments, plus 4 words of temp
|
||||||
space for ffi_call_osf. */
|
space for ffi_call_osf. */
|
||||||
argp = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG);
|
||||||
|
frame += cif->bytes;
|
||||||
|
|
||||||
argn = 0;
|
argn = 0;
|
||||||
if (flags == ALPHA_RET_IN_MEM)
|
if (flags == ALPHA_RET_IN_MEM)
|
||||||
@@ -301,9 +306,21 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
|
flags = (flags >> ALPHA_ST_SHIFT) & 0xff;
|
||||||
ffi_call_osf(argp, cif->bytes, flags, rvalue, fn);
|
ffi_call_osf(argp, frame, flags, rvalue, fn, 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);
|
||||||
|
}
|
||||||
|
|
||||||
ffi_status
|
ffi_status
|
||||||
ffi_prep_closure_loc (ffi_closure* closure,
|
ffi_prep_closure_loc (ffi_closure* closure,
|
||||||
@@ -339,15 +356,31 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||||||
return FFI_OK;
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
long FFI_HIDDEN
|
ffi_status
|
||||||
ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
|
ffi_prep_go_closure (ffi_go_closure* closure,
|
||||||
|
ffi_cif* cif,
|
||||||
|
void (*fun)(ffi_cif*, void*, void**, void*))
|
||||||
|
{
|
||||||
|
if (cif->abi != FFI_OSF)
|
||||||
|
return FFI_BAD_ABI;
|
||||||
|
|
||||||
|
closure->tramp = (void *)ffi_go_closure_osf;
|
||||||
|
closure->cif = cif;
|
||||||
|
closure->fun = fun;
|
||||||
|
|
||||||
|
return FFI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
long FFI_HIDDEN
|
||||||
|
ffi_closure_osf_inner (ffi_cif *cif,
|
||||||
|
void (*fun)(ffi_cif*, void*, void**, void*),
|
||||||
|
void *user_data,
|
||||||
|
void *rvalue, unsigned long *argp)
|
||||||
{
|
{
|
||||||
ffi_cif *cif;
|
|
||||||
void **avalue;
|
void **avalue;
|
||||||
ffi_type **arg_types;
|
ffi_type **arg_types;
|
||||||
long i, avn, argn, flags;
|
long i, avn, argn, flags;
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
avalue = alloca(cif->nargs * sizeof(void *));
|
avalue = alloca(cif->nargs * sizeof(void *));
|
||||||
flags = cif->flags;
|
flags = cif->flags;
|
||||||
argn = 0;
|
argn = 0;
|
||||||
@@ -481,7 +514,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke the closure. */
|
/* Invoke the closure. */
|
||||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
fun (cif, rvalue, avalue, user_data);
|
||||||
|
|
||||||
/* Tell ffi_closure_osf how to perform return type promotions. */
|
/* Tell ffi_closure_osf how to perform return type promotions. */
|
||||||
return (flags >> ALPHA_LD_SHIFT) & 0xff;
|
return (flags >> ALPHA_LD_SHIFT) & 0xff;
|
||||||
|
|||||||
@@ -50,6 +50,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_TRAMPOLINE_SIZE 24
|
#define FFI_TRAMPOLINE_SIZE 24
|
||||||
#define FFI_NATIVE_RAW_API 0
|
#define FFI_NATIVE_RAW_API 0
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,10 @@
|
|||||||
.org 99b + \index * 16
|
.org 99b + \index * 16
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags,
|
/* ffi_call_osf (void *stack, void *frame, unsigned flags,
|
||||||
void *raddr, void (*fnaddr)(void));
|
void *raddr, void (*fnaddr)(void), void *closure)
|
||||||
|
|
||||||
Bit o trickiness here -- ARGS+BYTES is the base of the stack frame
|
Bit o trickiness here -- FRAME is the base of the stack frame
|
||||||
for this function. This has been allocated by ffi_call. We also
|
for this function. This has been allocated by ffi_call. We also
|
||||||
deallocate some of the stack that has been alloca'd. */
|
deallocate some of the stack that has been alloca'd. */
|
||||||
|
|
||||||
@@ -52,22 +52,21 @@
|
|||||||
FFI_HIDDEN(ffi_call_osf)
|
FFI_HIDDEN(ffi_call_osf)
|
||||||
|
|
||||||
ffi_call_osf:
|
ffi_call_osf:
|
||||||
.frame $15, 32, $26, 0
|
|
||||||
.mask 0x4008000, -32
|
|
||||||
cfi_startproc
|
cfi_startproc
|
||||||
addq $16,$17,$1
|
cfi_def_cfa($17, 32)
|
||||||
mov $16, $30
|
mov $16, $30
|
||||||
stq $26, 0($1)
|
stq $26, 0($17)
|
||||||
stq $15, 8($1)
|
stq $15, 8($17)
|
||||||
stq $18, 16($1)
|
mov $17, $15
|
||||||
mov $1, $15
|
|
||||||
.prologue 0
|
.prologue 0
|
||||||
cfi_def_cfa($15, 32)
|
cfi_def_cfa_register($15)
|
||||||
cfi_rel_offset($26, 0)
|
cfi_rel_offset($26, 0)
|
||||||
cfi_rel_offset($15, 8)
|
cfi_rel_offset($15, 8)
|
||||||
|
|
||||||
stq $19, 24($1)
|
stq $18, 16($17) # save flags into frame
|
||||||
mov $20, $27
|
stq $19, 24($17) # save rvalue into frame
|
||||||
|
mov $20, $27 # fn into place for call
|
||||||
|
mov $21, $1 # closure into static chain
|
||||||
|
|
||||||
# Load up all of the (potential) argument registers.
|
# Load up all of the (potential) argument registers.
|
||||||
ldq $16, 0($30)
|
ldq $16, 0($30)
|
||||||
@@ -89,16 +88,16 @@ ffi_call_osf:
|
|||||||
jsr $26, ($27), 0
|
jsr $26, ($27), 0
|
||||||
0:
|
0:
|
||||||
ldah $29, 0($26) !gpdisp!1
|
ldah $29, 0($26) !gpdisp!1
|
||||||
ldq $2, 24($15)
|
ldq $2, 24($15) # reload rvalue
|
||||||
lda $29, 0($29) !gpdisp!1
|
lda $29, 0($29) !gpdisp!1
|
||||||
ldq $3, 16($15)
|
ldq $3, 16($15) # reload flags
|
||||||
lda $1, 99f-0b($26)
|
lda $1, 99f-0b($26)
|
||||||
ldq $26, 0($15)
|
ldq $26, 0($15)
|
||||||
ldq $15, 8($15)
|
ldq $15, 8($15)
|
||||||
cfi_restore($26)
|
cfi_restore($26)
|
||||||
cfi_restore($15)
|
cfi_restore($15)
|
||||||
cfi_def_cfa($sp, 0)
|
cfi_def_cfa($sp, 0)
|
||||||
cmoveq $2, ALPHA_ST_VOID, $3 # mash null return to void
|
cmoveq $2, ALPHA_ST_VOID, $3 # mash null rvalue to void
|
||||||
addq $3, $3, $3
|
addq $3, $3, $3
|
||||||
s8addq $3, $1, $1 # 99f + stcode * 16
|
s8addq $3, $1, $1 # 99f + stcode * 16
|
||||||
jmp $31, ($1), $st_int
|
jmp $31, ($1), $st_int
|
||||||
@@ -135,14 +134,38 @@ E ALPHA_ST_CPLXD
|
|||||||
|
|
||||||
#define CLOSURE_FS (16*8)
|
#define CLOSURE_FS (16*8)
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.globl ffi_go_closure_osf
|
||||||
|
.ent ffi_go_closure_osf
|
||||||
|
FFI_HIDDEN(ffi_go_closure_osf)
|
||||||
|
|
||||||
|
ffi_go_closure_osf:
|
||||||
|
cfi_startproc
|
||||||
|
ldgp $29, 0($27)
|
||||||
|
subq $30, CLOSURE_FS, $30
|
||||||
|
cfi_adjust_cfa_offset(CLOSURE_FS)
|
||||||
|
stq $26, 0($30)
|
||||||
|
.prologue 1
|
||||||
|
cfi_rel_offset($26, 0)
|
||||||
|
|
||||||
|
stq $16, 10*8($30)
|
||||||
|
stq $17, 11*8($30)
|
||||||
|
stq $18, 12*8($30)
|
||||||
|
|
||||||
|
ldq $16, 8($1) # load cif
|
||||||
|
ldq $17, 16($1) # load fun
|
||||||
|
mov $1, $18 # closure is user_data
|
||||||
|
br $do_closure
|
||||||
|
|
||||||
|
cfi_endproc
|
||||||
|
.end ffi_go_closure_osf
|
||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
.globl ffi_closure_osf
|
.globl ffi_closure_osf
|
||||||
.ent ffi_closure_osf
|
.ent ffi_closure_osf
|
||||||
FFI_HIDDEN(ffi_closure_osf)
|
FFI_HIDDEN(ffi_closure_osf)
|
||||||
|
|
||||||
ffi_closure_osf:
|
ffi_closure_osf:
|
||||||
.frame $30, CLOSURE_FS, $26, 0
|
|
||||||
.mask 0x4000000, -CLOSURE_FS
|
|
||||||
cfi_startproc
|
cfi_startproc
|
||||||
ldgp $29, 0($27)
|
ldgp $29, 0($27)
|
||||||
subq $30, CLOSURE_FS, $30
|
subq $30, CLOSURE_FS, $30
|
||||||
@@ -152,23 +175,28 @@ ffi_closure_osf:
|
|||||||
cfi_rel_offset($26, 0)
|
cfi_rel_offset($26, 0)
|
||||||
|
|
||||||
# Store all of the potential argument registers in va_list format.
|
# Store all of the potential argument registers in va_list format.
|
||||||
|
stq $16, 10*8($30)
|
||||||
|
stq $17, 11*8($30)
|
||||||
|
stq $18, 12*8($30)
|
||||||
|
|
||||||
|
ldq $16, 24($1) # load cif
|
||||||
|
ldq $17, 32($1) # load fun
|
||||||
|
ldq $18, 40($1) # load user_data
|
||||||
|
|
||||||
|
$do_closure:
|
||||||
|
stq $19, 13*8($30)
|
||||||
|
stq $20, 14*8($30)
|
||||||
|
stq $21, 15*8($30)
|
||||||
stt $f16, 4*8($30)
|
stt $f16, 4*8($30)
|
||||||
stt $f17, 5*8($30)
|
stt $f17, 5*8($30)
|
||||||
stt $f18, 6*8($30)
|
stt $f18, 6*8($30)
|
||||||
stt $f19, 7*8($30)
|
stt $f19, 7*8($30)
|
||||||
stt $f20, 8*8($30)
|
stt $f20, 8*8($30)
|
||||||
stt $f21, 9*8($30)
|
stt $f21, 9*8($30)
|
||||||
stq $16, 10*8($30)
|
|
||||||
stq $17, 11*8($30)
|
|
||||||
stq $18, 12*8($30)
|
|
||||||
stq $19, 13*8($30)
|
|
||||||
stq $20, 14*8($30)
|
|
||||||
stq $21, 15*8($30)
|
|
||||||
|
|
||||||
# Call ffi_closure_osf_inner to do the bulk of the work.
|
# Call ffi_closure_osf_inner to do the bulk of the work.
|
||||||
mov $1, $16
|
lda $19, 2*8($30)
|
||||||
lda $17, 2*8($30)
|
lda $20, 10*8($30)
|
||||||
lda $18, 10*8($30)
|
|
||||||
jsr $26, ffi_closure_osf_inner
|
jsr $26, ffi_closure_osf_inner
|
||||||
0:
|
0:
|
||||||
ldah $29, 0($26) !gpdisp!2
|
ldah $29, 0($26) !gpdisp!2
|
||||||
|
|||||||
Reference in New Issue
Block a user