ffi.c (ffi_struct_type): Put type declaration on separate line.

* src/pa/ffi.c (ffi_struct_type): Put type declaration on separate line.
	(ffi_prep_args_pa32): Likewise.
	(ffi_size_stack_pa32): Likewise.
	(ffi_prep_cif_machdep): Likewise.
	(ffi_call): Likewise.  Rename to ffi_call_int.  Add closure argument
	and update call to ffi_call_pa32.
	(ffi_call, ffi_call_go, ffi_prep_go_closure): New.
	(ffi_closure_inner_pa32): Update to handle go closures.
	* src/pa/ffitarget.h (FFI_GO_CLOSURES): Define.
	* src/pa/hpux32.S (ffi_call_pa32): Pass go closure argument in static
	chain register (%ret1).
	(ffi_closure_pa32): Set closure type argument to zero.
	(ffi_go_closure_pa32): New function.  Add unwind data for it.
	* src/pa/linux.S: Likewise.  Use cfi directives for unwind data.
	* testsuite/libffi.go/static-chain.h (STATIC_CHAIN_REG): Define for
	hppa.

From-SVN: r239978
This commit is contained in:
John David Anglin 2016-09-04 17:39:05 +00:00
parent d6598cf719
commit 5961d13d27
6 changed files with 220 additions and 89 deletions

View File

@ -1,3 +1,22 @@
2016-09-04 John David Anglin <danglin@gcc.gnu.org>
* src/pa/ffi.c (ffi_struct_type): Put type declaration on separate line.
(ffi_prep_args_pa32): Likewise.
(ffi_size_stack_pa32): Likewise.
(ffi_prep_cif_machdep): Likewise.
(ffi_call): Likewise. Rename to ffi_call_int. Add closure argument
and update call to ffi_call_pa32.
(ffi_call, ffi_call_go, ffi_prep_go_closure): New.
(ffi_closure_inner_pa32): Update to handle go closures.
* src/pa/ffitarget.h (FFI_GO_CLOSURES): Define.
* src/pa/hpux32.S (ffi_call_pa32): Pass go closure argument in static
chain register (%ret1).
(ffi_closure_pa32): Set closure type argument to zero.
(ffi_go_closure_pa32): New function. Add unwind data for it.
* src/pa/linux.S: Likewise. Use cfi directives for unwind data.
* testsuite/libffi.go/static-chain.h (STATIC_CHAIN_REG): Define for
hppa.
2016-05-23 Thomas Schwinge <thomas@codesourcery.com>
PR libffi/65567

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
ffi.c - (c) 2011 Anthony Green
ffi.c - (c) 2016 John David Anglin
(c) 2011 Anthony Green
(c) 2008 Red Hat, Inc.
(c) 2006 Free Software Foundation, Inc.
(c) 2003-2004 Randolph Chung <tausq@debian.org>
@ -51,7 +52,8 @@
#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
static inline int ffi_struct_type(ffi_type *t)
static inline int
ffi_struct_type (ffi_type *t)
{
size_t sz = t->size;
@ -139,7 +141,8 @@ static inline int ffi_struct_type(ffi_type *t)
NOTE: We load floating point args in this function... that means we
assume gcc will not mess with fp regs in here. */
void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
void
ffi_prep_args_pa32 (UINT32 *stack, extended_cif *ecif, unsigned bytes)
{
register unsigned int i;
register ffi_type **p_arg;
@ -275,7 +278,8 @@ void ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
return;
}
static void ffi_size_stack_pa32(ffi_cif *cif)
static void
ffi_size_stack_pa32 (ffi_cif *cif)
{
ffi_type **ptr;
int i;
@ -316,7 +320,8 @@ static void ffi_size_stack_pa32(ffi_cif *cif)
}
/* Perform machine dependent cif processing. */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
ffi_status
ffi_prep_cif_machdep (ffi_cif *cif)
{
/* Set the return type flag */
switch (cif->rtype->type)
@ -369,11 +374,13 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
extern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
extended_cif *, unsigned, unsigned, unsigned *,
void (*fn)(void));
extern void ffi_call_pa32 (void (*)(UINT32 *, extended_cif *, unsigned),
extended_cif *, unsigned, unsigned, unsigned *,
void (*fn)(void), void *closure);
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
static void
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue,
void *closure)
{
extended_cif ecif;
@ -401,8 +408,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
case FFI_PA32:
debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
ffi_call_pa32 (ffi_prep_args_pa32, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn, closure);
break;
default:
@ -411,14 +418,30 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
}
}
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);
}
#if FFI_CLOSURES
/* This is more-or-less an inverse of ffi_call -- we have arguments on
the stack, and we need to fill them into a cif structure and invoke
the user function. This really ought to be in asm to make sure
the compiler doesn't do things we don't expect. */
ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
ffi_status
ffi_closure_inner_pa32 (void *closure, UINT32 *stack, int closure_type)
{
ffi_cif *cif;
void (*fun)(ffi_cif *,void *,void **,void *);
void *user_data;
void **avalue;
void *rvalue;
UINT32 ret[2]; /* function can return up to 64-bits in registers */
@ -428,7 +451,19 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
unsigned int slot = FIRST_ARG_SLOT;
register UINT32 r28 asm("r28");
cif = closure->cif;
/* A non-zero closure type indicates a go closure. */
if (closure_type)
{
cif = ((ffi_go_closure *)closure)->cif;
fun = ((ffi_go_closure *)closure)->fun;
user_data = closure;
}
else
{
cif = ((ffi_closure *)closure)->cif;
fun = ((ffi_closure *)closure)->fun;
user_data = ((ffi_closure *)closure)->user_data;
}
/* If returning via structure, callee will write to our pointer. */
if (cif->flags == FFI_TYPE_STRUCT)
@ -436,7 +471,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
else
rvalue = &ret[0];
avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
avalue = (void **) alloca (cif->nargs * FFI_SIZEOF_ARG);
avn = cif->nargs;
p_arg = cif->arg_types;
@ -529,7 +564,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
}
/* Invoke the closure. */
(closure->fun) (cif, rvalue, avalue, closure->user_data);
fun (cif, rvalue, avalue, user_data);
debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
ret[1]);
@ -621,6 +656,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
cif specifies the argument and result types for fun.
The cif must already be prep'ed. */
extern void ffi_go_closure_pa32(void);
extern void ffi_closure_pa32(void);
ffi_status
@ -716,4 +752,21 @@ ffi_prep_closure_loc (ffi_closure* closure,
return FFI_OK;
}
#ifdef FFI_GO_CLOSURES
ffi_status
ffi_prep_go_closure (ffi_go_closure *closure,
ffi_cif *cif,
void (*fun)(ffi_cif *, void *, void **, void *))
{
if (cif->abi != FFI_PA32)
return FFI_BAD_ABI;
closure->tramp = &ffi_go_closure_pa32;
closure->cif = cif;
closure->fun = fun;
return FFI_OK;
}
#endif /* FFI_GO_CLOSURES */
#endif

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2012 Anthony Green
ffitarget.h - Copyright (c) 2016 John David Anglin
Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for hppa.
@ -67,6 +68,7 @@ typedef enum ffi_abi {
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#define FFI_GO_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#ifdef PA_LINUX

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
(c) 2008 Red Hat, Inc.
(c) 2016 John David Anglin
based on src/pa/linux.S
HP-UX PA Foreign Function Interface
@ -41,7 +42,8 @@
unsigned bytes,
unsigned flags,
unsigned *rvalue,
void (*fn)(void));
void (*fn)(void),
ffi_go_closure *closure);
*/
.export ffi_call_pa32,ENTRY,PRIV_LEV=3
@ -104,6 +106,7 @@ L$CFI13
we need to give it a place to put the result. */
ldw -52(%r3), %ret0 ; %ret0 <- rvalue
ldw -56(%r3), %r22 ; %r22 <- function to call
ldw -60(%r3), %ret1 ; %ret1 <- closure
bl $$dyncall, %r31 ; Call the user function
copy %r31, %rp
@ -285,7 +288,9 @@ L$CFI22
stw %arg2, -44(%r3)
stw %arg3, -48(%r3)
/* Closure type 0. */
copy %r21, %arg0
copy %r0, %arg2
bl ffi_closure_inner_pa32, %r2
copy %r3, %arg1
ldwm -64(%sp), %r3
@ -297,6 +302,47 @@ L$CFI22
.procend
L$FE2:
/* void ffi_go_closure_pa32(void);
Called with closure argument in %ret1 */
.SPACE $TEXT$
.SUBSPA $CODE$
.export ffi_go_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
.import ffi_closure_inner_pa32,CODE
.align 4
L$FB3
ffi_go_closure_pa32
.proc
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
.entry
stw %rp, -20(%sp)
copy %r3, %r1
L$CFI31
copy %sp, %r3
L$CFI32
stwm %r1, 64(%sp)
/* Put arguments onto the stack and call ffi_closure_inner. */
stw %arg0, -36(%r3)
stw %arg1, -40(%r3)
stw %arg2, -44(%r3)
stw %arg3, -48(%r3)
/* Closure type 1. */
copy %ret1, %arg0
ldi 1, %arg2
bl ffi_closure_inner_pa32, %r2
copy %r3, %arg1
ldwm -64(%sp), %r3
ldw -20(%sp), %rp
ldw -36(%sp), %ret0
bv %r0(%rp)
ldw -40(%sp), %ret1
.exit
.procend
L$FE3:
.SPACE $PRIVATE$
.SUBSPA $DATA$
@ -366,3 +412,25 @@ L$ASFDE2:
.align 4
L$EFDE2:
L$SFDE3:
.word L$EFDE3-L$ASFDE3 ;# FDE Length
L$ASFDE3:
.word L$ASFDE3-L$frame1 ;# FDE CIE offset
.word L$FB3 ;# FDE initial location
.word L$FE3-L$FB3 ;# FDE address range
.byte 0x4 ;# DW_CFA_advance_loc4
.word L$CFI31-L$FB3
.byte 0x83 ;# DW_CFA_offset, column 0x3
.uleb128 0x0
.byte 0x11 ;# DW_CFA_offset_extended_sf
.uleb128 0x2
.sleb128 -5
.byte 0x4 ;# DW_CFA_advance_loc4
.word L$CFI32-L$CFI31
.byte 0xd ;# DW_CFA_def_cfa_register = r3
.uleb128 0x3
.align 4
L$EFDE3:

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
(c) 2008 Red Hat, Inc.
(c) 2016 John David Anglin
HPPA Foreign Function Interface
@ -37,24 +38,26 @@
unsigned bytes,
unsigned flags,
unsigned *rvalue,
void (*fn)(void));
void (*fn)(void),
ffi_go_closure *closure);
*/
.export ffi_call_pa32,code
.import ffi_prep_args_pa32,code
.type ffi_call_pa32, @function
.LFB1:
.cfi_startproc
ffi_call_pa32:
.proc
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
.entry
stw %rp, -20(%sp)
copy %r3, %r1
.LCFI11:
.cfi_offset 2, -20
.cfi_register 3, 1
copy %sp, %r3
.LCFI12:
.cfi_def_cfa_register 3
/* Setup the stack for calling prep_args...
We want the stack to look like this:
@ -70,8 +73,8 @@ ffi_call_pa32:
*/
stwm %r1, 64(%sp)
.cfi_offset 3, 0
stw %r4, 12(%r3)
.LCFI13:
copy %sp, %r4
addl %arg2, %r4, %arg0 /* arg stack */
@ -98,6 +101,7 @@ ffi_call_pa32:
we need to give it a place to put the result. */
ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
ldw -56(%r3), %r22 /* %r22 <- function to call */
ldw -60(%r3), %ret1 /* %ret1 <- closure */
bl $$dyncall, %r31 /* Call the user function */
copy %r31, %rp
@ -249,27 +253,27 @@ ffi_call_pa32:
nop
.exit
.procend
.LFE1:
.cfi_endproc
/* void ffi_closure_pa32(void);
Called with closure argument in %r21 */
Called with ffi_closure argument in %r21. */
.export ffi_closure_pa32,code
.import ffi_closure_inner_pa32,code
.type ffi_closure_pa32, @function
.LFB2:
.cfi_startproc
ffi_closure_pa32:
.proc
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
.entry
stw %rp, -20(%sp)
.LCFI20:
copy %r3, %r1
.LCFI21:
.cfi_offset 2, -20
.cfi_register 3, 1
copy %sp, %r3
.LCFI22:
.cfi_def_cfa_register 3
stwm %r1, 64(%sp)
.cfi_offset 3, 0
/* Put arguments onto the stack and call ffi_closure_inner. */
stw %arg0, -36(%r3)
@ -277,7 +281,9 @@ ffi_closure_pa32:
stw %arg2, -44(%r3)
stw %arg3, -48(%r3)
/* Closure type 0. */
copy %r21, %arg0
copy %r0, %arg2
bl ffi_closure_inner_pa32, %r2
copy %r3, %arg1
@ -289,69 +295,46 @@ ffi_closure_pa32:
.exit
.procend
.LFE2:
.cfi_endproc
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
.Lframe1:
.word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
.LSCIE1:
.word 0x0 ;# CIE Identifier Tag
.byte 0x1 ;# CIE Version
.ascii "\0" ;# CIE Augmentation
.uleb128 0x1 ;# CIE Code Alignment Factor
.sleb128 4 ;# CIE Data Alignment Factor
.byte 0x2 ;# CIE RA Column
.byte 0xc ;# DW_CFA_def_cfa
.uleb128 0x1e
.uleb128 0x0
.align 4
.LECIE1:
.LSFDE1:
.word .LEFDE1-.LASFDE1 ;# FDE Length
.LASFDE1:
.word .LASFDE1-.Lframe1 ;# FDE CIE offset
.word .LFB1 ;# FDE initial location
.word .LFE1-.LFB1 ;# FDE address range
/* void ffi_go_closure_pa32(void);
Called with ffi_go_closure argument in %ret1. */
.export ffi_go_closure_pa32,code
.import ffi_closure_inner_pa32,code
.type ffi_go_closure_pa32, @function
.cfi_startproc
ffi_go_closure_pa32:
.proc
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
.entry
.byte 0x4 ;# DW_CFA_advance_loc4
.word .LCFI11-.LFB1
.byte 0x83 ;# DW_CFA_offset, column 0x3
.uleb128 0x0
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
.uleb128 0x2
.sleb128 -5
stw %rp, -20(%sp)
copy %r3, %r1
.cfi_offset 2, -20
.cfi_register 3, 1
copy %sp, %r3
.cfi_def_cfa_register 3
stwm %r1, 64(%sp)
.cfi_offset 3, 0
.byte 0x4 ;# DW_CFA_advance_loc4
.word .LCFI12-.LCFI11
.byte 0xd ;# DW_CFA_def_cfa_register = r3
.uleb128 0x3
/* Put arguments onto the stack and call ffi_closure_inner. */
stw %arg0, -36(%r3)
stw %arg1, -40(%r3)
stw %arg2, -44(%r3)
stw %arg3, -48(%r3)
.byte 0x4 ;# DW_CFA_advance_loc4
.word .LCFI13-.LCFI12
.byte 0x84 ;# DW_CFA_offset, column 0x4
.uleb128 0x3
/* Closure type 1. */
copy %ret1, %arg0
ldi 1, %arg2
bl ffi_closure_inner_pa32, %r2
copy %r3, %arg1
.align 4
.LEFDE1:
ldwm -64(%sp), %r3
ldw -20(%sp), %rp
ldw -36(%sp), %ret0
bv %r0(%r2)
ldw -40(%sp), %ret1
.LSFDE2:
.word .LEFDE2-.LASFDE2 ;# FDE Length
.LASFDE2:
.word .LASFDE2-.Lframe1 ;# FDE CIE offset
.word .LFB2 ;# FDE initial location
.word .LFE2-.LFB2 ;# FDE address range
.byte 0x4 ;# DW_CFA_advance_loc4
.word .LCFI21-.LFB2
.byte 0x83 ;# DW_CFA_offset, column 0x3
.uleb128 0x0
.byte 0x11 ;# DW_CFA_offset_extended_sf
.uleb128 0x2
.sleb128 -5
.byte 0x4 ;# DW_CFA_advance_loc4
.word .LCFI22-.LCFI21
.byte 0xd ;# DW_CFA_def_cfa_register = r3
.uleb128 0x3
.align 4
.LEFDE2:
.exit
.procend
.cfi_endproc

View File

@ -4,6 +4,12 @@
# define STATIC_CHAIN_REG "$1"
#elif defined(__arm__)
# define STATIC_CHAIN_REG "ip"
#elif defined(__hppa__)
# if defined(__LP64)
# define define STATIC_CHAIN_REG "%r31"
# else
# define define STATIC_CHAIN_REG "%r29" /* %ret1 */
# endif
#elif defined(__sparc__)
# if defined(__arch64__) || defined(__sparcv9)
# define STATIC_CHAIN_REG "g5"