s390: Go closure support

This commit is contained in:
Dominik Vogt
2014-12-17 13:20:51 -05:00
committed by Richard Henderson
parent 75b2199f26
commit 02b7c89967
3 changed files with 302 additions and 234 deletions

View File

@@ -64,21 +64,6 @@
/*===================== End of Defines ===============================*/ /*===================== End of Defines ===============================*/
/*====================================================================*/
/* Prototypes */
/* ---------- */
/*====================================================================*/
static void ffi_prep_args (unsigned char *, extended_cif *);
void
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
__attribute__ ((visibility ("hidden")))
#endif
ffi_closure_helper_SYSV (ffi_closure *, unsigned long *,
unsigned long long *, unsigned long *);
/*====================== End of Prototypes ===========================*/
/*====================================================================*/ /*====================================================================*/
/* Externals */ /* Externals */
/* --------- */ /* --------- */
@@ -89,9 +74,10 @@ extern void ffi_call_SYSV(unsigned,
void (*)(unsigned char *, extended_cif *), void (*)(unsigned char *, extended_cif *),
unsigned, unsigned,
void *, void *,
void (*fn)(void)); void (*fn)(void), void *);
extern void ffi_closure_SYSV(void); extern void ffi_closure_SYSV(void);
extern void ffi_go_closure_SYSV(void);
/*====================== End of Externals ============================*/ /*====================== End of Externals ============================*/
@@ -504,11 +490,12 @@ ffi_prep_cif_machdep(ffi_cif *cif)
/* */ /* */
/*====================================================================*/ /*====================================================================*/
void static void
ffi_call(ffi_cif *cif, ffi_call_int(ffi_cif *cif,
void (*fn)(void), void (*fn)(void),
void *rvalue, void *rvalue,
void **avalue) void **avalue,
void *closure)
{ {
int ret_type = cif->flags; int ret_type = cif->flags;
extended_cif ecif; extended_cif ecif;
@@ -530,7 +517,7 @@ ffi_call(ffi_cif *cif,
{ {
case FFI_SYSV: case FFI_SYSV:
ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args,
ret_type, ecif.rvalue, fn); ret_type, ecif.rvalue, fn, closure);
break; break;
default: default:
@@ -538,6 +525,19 @@ ffi_call(ffi_cif *cif,
break; break;
} }
} }
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);
}
/*======================== End of Routine ============================*/ /*======================== End of Routine ============================*/
@@ -548,9 +548,12 @@ ffi_call(ffi_cif *cif,
/* Function - Call a FFI closure target function. */ /* Function - Call a FFI closure target function. */
/* */ /* */
/*====================================================================*/ /*====================================================================*/
FFI_HIDDEN
void void
ffi_closure_helper_SYSV (ffi_closure *closure, ffi_closure_helper_SYSV (ffi_cif *cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
unsigned long *p_gpr, unsigned long *p_gpr,
unsigned long long *p_fpr, unsigned long long *p_fpr,
unsigned long *p_ov) unsigned long *p_ov)
@@ -570,20 +573,18 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
/* Allocate buffer for argument list pointers. */ /* Allocate buffer for argument list pointers. */
p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); p_arg = avalue = alloca (cif->nargs * sizeof (void *));
/* If we returning a structure, pass the structure address /* If we returning a structure, pass the structure address
directly to the target function. Otherwise, have the target directly to the target function. Otherwise, have the target
function store the return value to the GPR save area. */ function store the return value to the GPR save area. */
if (closure->cif->flags == FFI390_RET_STRUCT) if (cif->flags == FFI390_RET_STRUCT)
rvalue = (void *) p_gpr[n_gpr++]; rvalue = (void *) p_gpr[n_gpr++];
/* Now for the arguments. */ /* Now for the arguments. */
for (ptr = closure->cif->arg_types, i = closure->cif->nargs; for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++)
i > 0;
i--, p_arg++, ptr++)
{ {
int deref_struct_pointer = 0; int deref_struct_pointer = 0;
int type = (*ptr)->type; int type = (*ptr)->type;
@@ -689,10 +690,10 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
/* Call the target function. */ /* Call the target function. */
(closure->fun) (closure->cif, rvalue, avalue, closure->user_data); (fun) (cif, rvalue, avalue, user_data);
/* Convert the return value. */ /* Convert the return value. */
switch (closure->cif->rtype->type) switch (cif->rtype->type)
{ {
/* Void is easy, and so is struct. */ /* Void is easy, and so is struct. */
case FFI_TYPE_VOID: case FFI_TYPE_VOID:
@@ -790,3 +791,18 @@ ffi_prep_closure_loc (ffi_closure *closure,
/*======================== End of Routine ============================*/ /*======================== End of Routine ============================*/
/* Build a Go language closure. */
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
void (*fun)(ffi_cif*,void*,void**,void*))
{
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
closure->tramp = ffi_go_closure_SYSV;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}

View File

@@ -58,6 +58,7 @@ typedef enum ffi_abi {
/* ---- Definitions for closures ----------------------------------------- */ /* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1 #define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#ifdef S390X #ifdef S390X
#define FFI_TRAMPOLINE_SIZE 32 #define FFI_TRAMPOLINE_SIZE 32
#else #else

View File

@@ -39,18 +39,29 @@
# r5: ret_type # r5: ret_type
# r6: ecif.rvalue # r6: ecif.rvalue
# ov: fn # ov: fn
# ov+8: closure
# This assumes we are using gas. # This assumes we are using gas.
.globl ffi_call_SYSV .globl ffi_call_SYSV
FFI_HIDDEN(ffi_call_SYSV)
.type ffi_call_SYSV,%function .type ffi_call_SYSV,%function
ffi_call_SYSV: ffi_call_SYSV:
.LFB1: .cfi_startproc
stm %r6,%r15,24(%r15) # Save registers stm %r6,%r15,24(%r15) # Save registers
.LCFI0: .cfi_offset r6, -72
.cfi_offset r7, -68
.cfi_offset r8, -64
.cfi_offset r9, -60
.cfi_offset r10, -56
.cfi_offset r11, -52
.cfi_offset r12, -48
.cfi_offset r13, -44
.cfi_offset r14, -40
.cfi_offset r15, -36
basr %r13,0 # Set up base register basr %r13,0 # Set up base register
.Lbase: .Lbase:
lr %r11,%r15 # Set up frame pointer lr %r11,%r15 # Set up frame pointer
.LCFI1: .cfi_def_cfa_register r11
sr %r15,%r2 sr %r15,%r2
ahi %r15,-96-48 # Allocate stack ahi %r15,-96-48 # Allocate stack
lr %r8,%r6 # Save ecif.rvalue lr %r8,%r6 # Save ecif.rvalue
@@ -59,12 +70,13 @@ ffi_call_SYSV:
l %r7,96(%r11) # Load function address l %r7,96(%r11) # Load function address
st %r11,0(%r15) # Set up back chain st %r11,0(%r15) # Set up back chain
ahi %r11,-48 # Register save area ahi %r11,-48 # Register save area
.LCFI2: .cfi_adjust_cfa_offset 48
la %r2,96(%r15) # Save area la %r2,96(%r15) # Save area
# r3 already holds &ecif # r3 already holds &ecif
basr %r14,%r4 # Call ffi_prep_args basr %r14,%r4 # Call ffi_prep_args
l %r0,96+48+4(%r11) # Go closure -> static chain
lm %r2,%r6,0(%r11) # Load arguments lm %r2,%r6,0(%r11) # Load arguments
ld %f0,32(%r11) ld %f0,32(%r11)
ld %f2,40(%r11) ld %f2,40(%r11)
@@ -74,31 +86,106 @@ ffi_call_SYSV:
.LretNone: # Return void .LretNone: # Return void
l %r4,48+56(%r11) l %r4,48+56(%r11)
lm %r6,%r15,48+24(%r11) lm %r6,%r15,48+24(%r11)
.cfi_remember_state
.cfi_restore 15
.cfi_restore 14
.cfi_restore 13
.cfi_restore 12
.cfi_restore 11
.cfi_restore 10
.cfi_restore 9
.cfi_restore 8
.cfi_restore 7
.cfi_restore 6
.cfi_def_cfa r15, 96
br %r4 br %r4
.cfi_restore_state
# This nopr is necessary so that the .cfi instructions between the br
# above and the label below get executed. See execute_cfa_program() in
# the Gcc source code, libgcc/unwind-dw2.c.
nopr
.LretFloat: .LretFloat:
l %r4,48+56(%r11) l %r4,48+56(%r11)
ste %f0,0(%r8) # Return float ste %f0,0(%r8) # Return float
lm %r6,%r15,48+24(%r11) lm %r6,%r15,48+24(%r11)
.cfi_remember_state
.cfi_restore 15
.cfi_restore 14
.cfi_restore 13
.cfi_restore 12
.cfi_restore 11
.cfi_restore 10
.cfi_restore 9
.cfi_restore 8
.cfi_restore 7
.cfi_restore 6
.cfi_def_cfa r15, 96
br %r4 br %r4
.cfi_restore_state
# See comment on the nopr above.
nopr
.LretDouble: .LretDouble:
l %r4,48+56(%r11) l %r4,48+56(%r11)
std %f0,0(%r8) # Return double std %f0,0(%r8) # Return double
lm %r6,%r15,48+24(%r11) lm %r6,%r15,48+24(%r11)
.cfi_remember_state
.cfi_restore 15
.cfi_restore 14
.cfi_restore 13
.cfi_restore 12
.cfi_restore 11
.cfi_restore 10
.cfi_restore 9
.cfi_restore 8
.cfi_restore 7
.cfi_restore 6
.cfi_def_cfa r15, 96
br %r4 br %r4
.cfi_restore_state
# See comment on the nopr above.
nopr
.LretInt32: .LretInt32:
l %r4,48+56(%r11) l %r4,48+56(%r11)
st %r2,0(%r8) # Return int st %r2,0(%r8) # Return int
lm %r6,%r15,48+24(%r11) lm %r6,%r15,48+24(%r11)
.cfi_remember_state
.cfi_restore 15
.cfi_restore 14
.cfi_restore 13
.cfi_restore 12
.cfi_restore 11
.cfi_restore 10
.cfi_restore 9
.cfi_restore 8
.cfi_restore 7
.cfi_restore 6
.cfi_def_cfa r15, 96
br %r4 br %r4
.cfi_restore_state
# See comment on the nopr above.
nopr
.LretInt64: .LretInt64:
l %r4,48+56(%r11) l %r4,48+56(%r11)
stm %r2,%r3,0(%r8) # Return long long stm %r2,%r3,0(%r8) # Return long long
lm %r6,%r15,48+24(%r11) lm %r6,%r15,48+24(%r11)
.cfi_remember_state
.cfi_restore 15
.cfi_restore 14
.cfi_restore 13
.cfi_restore 12
.cfi_restore 11
.cfi_restore 10
.cfi_restore 9
.cfi_restore 8
.cfi_restore 7
.cfi_restore 6
.cfi_def_cfa r15, 96
br %r4 br %r4
.cfi_endproc
.Ltable: .Ltable:
.byte .LretNone-.Lbase # FFI390_RET_VOID .byte .LretNone-.Lbase # FFI390_RET_VOID
@@ -108,129 +195,78 @@ ffi_call_SYSV:
.byte .LretInt32-.Lbase # FFI390_RET_INT32 .byte .LretInt32-.Lbase # FFI390_RET_INT32
.byte .LretInt64-.Lbase # FFI390_RET_INT64 .byte .LretInt64-.Lbase # FFI390_RET_INT64
.LFE1:
.ffi_call_SYSV_end: .ffi_call_SYSV_end:
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
.globl ffi_closure_SYSV .globl ffi_closure_SYSV
FFI_HIDDEN(ffi_closure_SYSV)
.type ffi_closure_SYSV,%function .type ffi_closure_SYSV,%function
ffi_closure_SYSV: ffi_closure_SYSV:
.LFB2: .cfi_startproc
stm %r2,%r6,8(%r15) # Save arguments
.cfi_offset r6, -72
lr %r4,%r0 # Closure
l %r2,16(%r4) # ->cif
l %r3,20(%r4) # ->fun
l %r4,24(%r4) # ->user_data
.Ldoclosure:
stm %r12,%r15,48(%r15) # Save registers stm %r12,%r15,48(%r15) # Save registers
.LCFI10: .cfi_offset r12, -48
.cfi_offset r13, -44
.cfi_offset r14, -40
.cfi_offset r15, -36
basr %r13,0 # Set up base register basr %r13,0 # Set up base register
.Lcbase: .Lcbase:
stm %r2,%r6,8(%r15) # Save arguments
std %f0,64(%r15) std %f0,64(%r15)
std %f2,72(%r15) std %f2,72(%r15)
lr %r1,%r15 # Set up stack frame lr %r1,%r15 # Set up stack frame
ahi %r15,-96 ahi %r15,-104
.LCFI11: .cfi_adjust_cfa_offset 104
l %r12,.Lchelper-.Lcbase(%r13) # Get helper function l %r12,.Lchelper-.Lcbase(%r13) # Get helper function
lr %r2,%r0 # Closure la %r5,96(%r1)
la %r3,8(%r1) # GPRs st %r5,96(%r15) # Overflow
la %r4,64(%r1) # FPRs la %r5,8(%r1) # GPRs
la %r5,96(%r1) # Overflow la %r6,64(%r1) # FPRs
st %r1,0(%r15) # Set up back chain st %r1,0(%r15) # Set up back chain
bas %r14,0(%r12,%r13) # Call helper bas %r14,0(%r12,%r13) # Call helper
l %r4,96+56(%r15) l %r4,104+56(%r15)
ld %f0,96+64(%r15) # Load return registers ld %f0,104+64(%r15) # Load return registers
lm %r2,%r3,96+8(%r15) lm %r2,%r3,104+8(%r15)
lm %r12,%r15,96+48(%r15) l %r6,104+24(%r15) # Restore saved registers
.cfi_restore r6
lm %r12,%r15,104+48(%r15)
.cfi_adjust_cfa_offset -104
.cfi_restore r12
.cfi_restore r13
.cfi_restore r14
.cfi_restore r15
br %r4 br %r4
.cfi_endproc
.align 4 .align 4
.Lchelper: .Lchelper:
.long ffi_closure_helper_SYSV-.Lcbase .long ffi_closure_helper_SYSV-.Lcbase
.LFE2:
.ffi_closure_SYSV_end: .ffi_closure_SYSV_end:
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
.section .eh_frame,EH_FRAME_FLAGS,@progbits .globl ffi_go_closure_SYSV
.Lframe1: FFI_HIDDEN(ffi_go_closure_SYSV)
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry .type ffi_go_closure_SYSV,%function
.LSCIE1: ffi_go_closure_SYSV:
.4byte 0x0 # CIE Identifier Tag .cfi_startproc
.byte 0x1 # CIE Version stm %r2,%r6,8(%r15) # Save arguments
.ascii "zR\0" # CIE Augmentation .cfi_offset r6, -72
.uleb128 0x1 # CIE Code Alignment Factor lr %r4,%r0 # Load closure -> user_data
.sleb128 -4 # CIE Data Alignment Factor l %r2,4(%r4) # ->cif
.byte 0xe # CIE RA Column l %r3,8(%r4) # ->fun
.uleb128 0x1 # Augmentation size j .Ldoclosure
.byte 0x1b # FDE Encoding (pcrel sdata4) .cfi_endproc
.byte 0xc # DW_CFA_def_cfa
.uleb128 0xf
.uleb128 0x60
.align 4
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.4byte .LFB1-. # FDE initial location
.4byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x9
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0xa
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0xb
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0xc
.byte 0x8b # DW_CFA_offset, column 0xb
.uleb128 0xd
.byte 0x8a # DW_CFA_offset, column 0xa
.uleb128 0xe
.byte 0x89 # DW_CFA_offset, column 0x9
.uleb128 0xf
.byte 0x88 # DW_CFA_offset, column 0x8
.uleb128 0x10
.byte 0x87 # DW_CFA_offset, column 0x7
.uleb128 0x11
.byte 0x86 # DW_CFA_offset, column 0x6
.uleb128 0x12
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0xb
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI2-.LCFI1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0x90
.align 4
.LEFDE1:
.LSFDE2:
.4byte .LEFDE2-.LASFDE2 # FDE Length
.LASFDE2:
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
.4byte .LFB2-. # FDE initial location
.4byte .LFE2-.LFB2 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI10-.LFB2
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x9
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0xa
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0xb
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0xc
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI11-.LCFI10
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xc0
.align 4
.LEFDE2:
#else #else
@@ -242,17 +278,28 @@ ffi_closure_SYSV:
# r5: ret_type # r5: ret_type
# r6: ecif.rvalue # r6: ecif.rvalue
# ov: fn # ov: fn
# ov+8: closure
# This assumes we are using gas. # This assumes we are using gas.
.globl ffi_call_SYSV .globl ffi_call_SYSV
FFI_HIDDEN(ffi_call_SYSV)
.type ffi_call_SYSV,%function .type ffi_call_SYSV,%function
ffi_call_SYSV: ffi_call_SYSV:
.LFB1: .cfi_startproc
stmg %r6,%r15,48(%r15) # Save registers stmg %r6,%r15,48(%r15) # Save registers
.LCFI0: .cfi_offset r6, -112
.cfi_offset r7, -104
.cfi_offset r8, -96
.cfi_offset r9, -88
.cfi_offset r10, -80
.cfi_offset r11, -72
.cfi_offset r12, -64
.cfi_offset r13, -56
.cfi_offset r14, -48
.cfi_offset r15, -40
larl %r13,.Lbase # Set up base register larl %r13,.Lbase # Set up base register
lgr %r11,%r15 # Set up frame pointer lgr %r11,%r15 # Set up frame pointer
.LCFI1: .cfi_def_cfa_register r11
sgr %r15,%r2 sgr %r15,%r2
aghi %r15,-160-80 # Allocate stack aghi %r15,-160-80 # Allocate stack
lgr %r8,%r6 # Save ecif.rvalue lgr %r8,%r6 # Save ecif.rvalue
@@ -260,12 +307,13 @@ ffi_call_SYSV:
lg %r7,160(%r11) # Load function address lg %r7,160(%r11) # Load function address
stg %r11,0(%r15) # Set up back chain stg %r11,0(%r15) # Set up back chain
aghi %r11,-80 # Register save area aghi %r11,-80 # Register save area
.LCFI2: .cfi_adjust_cfa_offset 80
la %r2,160(%r15) # Save area la %r2,160(%r15) # Save area
# r3 already holds &ecif # r3 already holds &ecif
basr %r14,%r4 # Call ffi_prep_args basr %r14,%r4 # Call ffi_prep_args
lg %r0,160+80+8(%r11) # Go closure -> static chain
lmg %r2,%r6,0(%r11) # Load arguments lmg %r2,%r6,0(%r11) # Load arguments
ld %f0,48(%r11) ld %f0,48(%r11)
ld %f2,56(%r11) ld %f2,56(%r11)
@@ -278,154 +326,157 @@ ffi_call_SYSV:
.LretNone: # Return void .LretNone: # Return void
lg %r4,80+112(%r11) lg %r4,80+112(%r11)
lmg %r6,%r15,80+48(%r11) lmg %r6,%r15,80+48(%r11)
.cfi_remember_state
.cfi_restore r15
.cfi_restore r14
.cfi_restore r13
.cfi_restore r12
.cfi_restore r11
.cfi_restore r10
.cfi_restore r9
.cfi_restore r8
.cfi_restore r7
.cfi_restore r6
.cfi_def_cfa r15, 160
br %r4 br %r4
.cfi_restore_state
# This nopr is necessary so that the .cfi instructions between the br
# above and the label below get executed. See execute_cfa_program() in
# the Gcc source code, libgcc/unwind-dw2.c.
nopr
.LretFloat: .LretFloat:
lg %r4,80+112(%r11) lg %r4,80+112(%r11)
ste %f0,0(%r8) # Return float ste %f0,0(%r8) # Return float
lmg %r6,%r15,80+48(%r11) lmg %r6,%r15,80+48(%r11)
.cfi_remember_state
.cfi_restore r6
.cfi_restore r7
.cfi_restore r8
.cfi_restore r9
.cfi_restore r10
.cfi_restore r11
.cfi_restore r12
.cfi_restore r13
.cfi_restore r14
.cfi_restore r15
.cfi_def_cfa r15, 160
br %r4 br %r4
.cfi_restore_state
# See comment on the nopr above.
nopr
.LretDouble: .LretDouble:
lg %r4,80+112(%r11) lg %r4,80+112(%r11)
std %f0,0(%r8) # Return double std %f0,0(%r8) # Return double
lmg %r6,%r15,80+48(%r11) lmg %r6,%r15,80+48(%r11)
.cfi_remember_state
.cfi_restore r15
.cfi_restore r14
.cfi_restore r13
.cfi_restore r12
.cfi_restore r11
.cfi_restore r10
.cfi_restore r9
.cfi_restore r8
.cfi_restore r7
.cfi_restore r6
.cfi_def_cfa r15, 160
br %r4 br %r4
.cfi_restore_state
# See comment on the nopr above.
nopr
.LretInt32:
lg %r4,80+112(%r11)
st %r2,0(%r8) # Return int
lmg %r6,%r15,80+48(%r11)
br %r4
.LretInt64: .LretInt64:
lg %r4,80+112(%r11) lg %r4,80+112(%r11)
stg %r2,0(%r8) # Return long stg %r2,0(%r8) # Return long
lmg %r6,%r15,80+48(%r11) lmg %r6,%r15,80+48(%r11)
.cfi_restore r15
.cfi_restore r14
.cfi_restore r13
.cfi_restore r12
.cfi_restore r11
.cfi_restore r10
.cfi_restore r9
.cfi_restore r8
.cfi_restore r7
.cfi_restore r6
.cfi_def_cfa r15, 160
br %r4 br %r4
.cfi_endproc
.Ltable: .Ltable:
.byte .LretNone-.Lbase # FFI390_RET_VOID .byte .LretNone-.Lbase # FFI390_RET_VOID
.byte .LretNone-.Lbase # FFI390_RET_STRUCT .byte .LretNone-.Lbase # FFI390_RET_STRUCT
.byte .LretFloat-.Lbase # FFI390_RET_FLOAT .byte .LretFloat-.Lbase # FFI390_RET_FLOAT
.byte .LretDouble-.Lbase # FFI390_RET_DOUBLE .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE
.byte .LretInt32-.Lbase # FFI390_RET_INT32 .byte 0 # int32 retval not supported
.byte .LretInt64-.Lbase # FFI390_RET_INT64 .byte .LretInt64-.Lbase # FFI390_RET_INT64
.LFE1:
.ffi_call_SYSV_end: .ffi_call_SYSV_end:
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
.globl ffi_closure_SYSV .globl ffi_closure_SYSV
FFI_HIDDEN(ffi_closure_SYSV)
.type ffi_closure_SYSV,%function .type ffi_closure_SYSV,%function
ffi_closure_SYSV: ffi_closure_SYSV:
.LFB2: .cfi_startproc
stmg %r14,%r15,112(%r15) # Save registers
.LCFI10:
stmg %r2,%r6,16(%r15) # Save arguments stmg %r2,%r6,16(%r15) # Save arguments
std %f0,128(%r15) .cfi_offset r6, -112
lgr %r4,%r0 # Load closure
lg %r2,32(%r4) # ->cif
lg %r3,40(%r4) # ->fun
lg %r4,48(%r4) # ->user_data
.Ldoclosure:
stmg %r14,%r15,112(%r15) # Save registers
.cfi_offset r14, -48
.cfi_offset r15, -40
std %f0,128(%r15) # Save arguments
std %f2,136(%r15) std %f2,136(%r15)
std %f4,144(%r15) std %f4,144(%r15)
std %f6,152(%r15) std %f6,152(%r15)
lgr %r1,%r15 # Set up stack frame lgr %r1,%r15 # Set up stack frame
aghi %r15,-160 aghi %r15,-168
.LCFI11: .cfi_adjust_cfa_offset 168
lgr %r2,%r0 # Closure la %r5,160(%r1)
la %r3,16(%r1) # GPRs stg %r5,160(%r15) # Overflow
la %r4,128(%r1) # FPRs la %r5,16(%r1) # GPRs
la %r5,160(%r1) # Overflow la %r6,128(%r1) # FPRs
stg %r1,0(%r15) # Set up back chain stg %r1,0(%r15) # Set up back chain
brasl %r14,ffi_closure_helper_SYSV # Call helper brasl %r14,ffi_closure_helper_SYSV # Call helper
lg %r14,160+112(%r15) ld %f0,168+128(%r15) # Load return registers
ld %f0,160+128(%r15) # Load return registers lg %r2,168+16(%r15)
lg %r2,160+16(%r15) lg %r6,168+48(%r15) # Restore saved registers
la %r15,160(%r15) .cfi_restore r6
lmg %r14,%r15,168+112(%r15)
.cfi_restore r14
.cfi_restore r15
.cfi_adjust_cfa_offset -168
br %r14 br %r14
.LFE2: .cfi_endproc
.ffi_closure_SYSV_end: .ffi_closure_SYSV_end:
.size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
.globl ffi_go_closure_SYSV
FFI_HIDDEN(ffi_go_closure_SYSV)
.type ffi_go_closure_SYSV,%function
ffi_go_closure_SYSV:
.cfi_startproc
stmg %r2,%r6,16(%r15) # Save arguments
.cfi_offset r6, -112
lgr %r4,%r0 # Load closure -> user_data
lg %r2,8(%r4) # ->cif
lg %r3,16(%r4) # ->fun
j .Ldoclosure
.cfi_endproc
.ffi_go_closure_SYSV_end:
.section .eh_frame,EH_FRAME_FLAGS,@progbits .size ffi_go_closure_SYSV,.ffi_go_closure_SYSV_end-ffi_go_closure_SYSV
.Lframe1:
.4byte .LECIE1-.LSCIE1 # Length of Common Information Entry
.LSCIE1:
.4byte 0x0 # CIE Identifier Tag
.byte 0x1 # CIE Version
.ascii "zR\0" # CIE Augmentation
.uleb128 0x1 # CIE Code Alignment Factor
.sleb128 -8 # CIE Data Alignment Factor
.byte 0xe # CIE RA Column
.uleb128 0x1 # Augmentation size
.byte 0x1b # FDE Encoding (pcrel sdata4)
.byte 0xc # DW_CFA_def_cfa
.uleb128 0xf
.uleb128 0xa0
.align 8
.LECIE1:
.LSFDE1:
.4byte .LEFDE1-.LASFDE1 # FDE Length
.LASFDE1:
.4byte .LASFDE1-.Lframe1 # FDE CIE offset
.4byte .LFB1-. # FDE initial location
.4byte .LFE1-.LFB1 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI0-.LFB1
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x5
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0x6
.byte 0x8d # DW_CFA_offset, column 0xd
.uleb128 0x7
.byte 0x8c # DW_CFA_offset, column 0xc
.uleb128 0x8
.byte 0x8b # DW_CFA_offset, column 0xb
.uleb128 0x9
.byte 0x8a # DW_CFA_offset, column 0xa
.uleb128 0xa
.byte 0x89 # DW_CFA_offset, column 0x9
.uleb128 0xb
.byte 0x88 # DW_CFA_offset, column 0x8
.uleb128 0xc
.byte 0x87 # DW_CFA_offset, column 0x7
.uleb128 0xd
.byte 0x86 # DW_CFA_offset, column 0x6
.uleb128 0xe
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI1-.LCFI0
.byte 0xd # DW_CFA_def_cfa_register
.uleb128 0xb
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI2-.LCFI1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0xf0
.align 8
.LEFDE1:
.LSFDE2:
.4byte .LEFDE2-.LASFDE2 # FDE Length
.LASFDE2:
.4byte .LASFDE2-.Lframe1 # FDE CIE offset
.4byte .LFB2-. # FDE initial location
.4byte .LFE2-.LFB2 # FDE address range
.uleb128 0x0 # Augmentation size
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI10-.LFB2
.byte 0x8f # DW_CFA_offset, column 0xf
.uleb128 0x5
.byte 0x8e # DW_CFA_offset, column 0xe
.uleb128 0x6
.byte 0x4 # DW_CFA_advance_loc4
.4byte .LCFI11-.LCFI10
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 0x140
.align 8
.LEFDE2:
#endif #endif