GO closures for powerpc linux

Plus .cfi async unwind info, rearrangement of ffi_call_linux64 and
ffi_call_SYSV function params to avoid register copies, tweaks to
trampolines.

	* src/powerpc/ffitarget.h (FFI_GO_CLOSURES): Define.
	* src/powerpc/ffi.c (ffi_call_int): New function with extra
	closure param, and args rearranged on ffi_call_linux64 and
	ffi_call_SYSV calls, extracted from ..
	(ffi_call): ..here.
	(ffi_call_go, ffi_prep_go_closure): New functions.
	* src/powerpc/ffi_linux64.c (ffi_prep_closure_loc_linux64): Make
	hidden.  Only flush insn part of ELFv2 trampoline.  Don't shuffle
	ELFv1 trampoline.
	(ffi_closure_helper_LINUX64): Replace closure param with cif, fun,
	user_data params.
	* src/powerpc/ffi_powerpc.h (ffi_go_closure_sysv): Declare.
	(ffi_go_closure_linux64): Declare.
	(ffi_call_SYSV, fi_call_LINUX64): Update.
	(ffi_prep_closure_loc_sysv, ffi_prep_closure_loc_linux64): Declare.
	(ffi_closure_helper_SYSV, ffi_closure_helper_LINUX64): Update.
	* src/powerpc/ffi_sysv.c (ASM_NEEDS_REGISTERS): Increase to 6.
	(ffi_prep_closure_loc_sysv): Use bcl in trampoline, put data words
	last, flush just the insn part.
	(ffi_closure_helper_SYSV): Replace closure param with cif, fun and
	user_data params.
	* src/powerpc/linux64.S (ffi_call_LINUX64): Replace hand-written
	.eh_frame with .cfi directives.  Adjust for changed param order.
	Pass extra "closure" param to user function in static chain.  Add
	.cfi directives to describe epilogue.  Don't provide traceback
	table for ELFv2 or _CALL_LINUX.
	* src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Replace
	hand-written .eh_frame with .cfi directives.  Adjust for changed
	ffi_closure_helper_LINUX64 params.  Add .cfi directives to
	describe epilogue.  Don't provide traceback table for ELFv2 or
	_CALL_LINUX.
	(ffi_go_closure_linux64): New function.
	* src/powerpc/sysv.S: Remove redundant .globl ffi_prep_args_SYSV.
	(ffi_call_SYSV): Make hidden.  Replace hand-written .eh_frame with
	.cfi directives.  Adjust for changed params.  Pass extra "closure"
	param to user function in static chain.  Add .cfi directives to
	describe epilogue.
	* src/powerpc/ppc_closure.S (ffi_closure_SYSV): Make hidden.
	Replace hand-written .eh_frame with .cfi directives.  Adjust for
	changed ffi_closure_helper_SYSV params.  Add .cfi directives to
	describe epilogue.  Don't just use nops in the dead __NO_FPRS__
	epilogues.
	(ffi_go_closure_sysv): New function.
This commit is contained in:
Alan Modra
2014-11-20 11:35:12 +10:30
parent d3d06f4c94
commit fa1040c111
9 changed files with 403 additions and 313 deletions
+18 -15
View File
@@ -36,7 +36,7 @@
/* About the SYSV ABI. */
#define ASM_NEEDS_REGISTERS 4
#define ASM_NEEDS_REGISTERS 6
#define NUM_GPR_ARG_REGISTERS 8
#define NUM_FPR_ARG_REGISTERS 8
@@ -654,18 +654,18 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */
tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
tramp[4] = 0x7d6802a6; /* mflr r11 */
tramp[5] = 0x7c0803a6; /* mtlr r0 */
tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
tramp[8] = 0x7c0903a6; /* mtctr r0 */
tramp[9] = 0x4e800420; /* bctr */
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
*(void **) &tramp[3] = codeloc; /* context */
tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
tramp[2] = 0x7d6802a6; /* mflr r11 */
tramp[3] = 0x7c0803a6; /* mtlr r0 */
tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
tramp[6] = 0x7c0903a6; /* mtctr r0 */
tramp[7] = 0x4e800420; /* bctr */
*(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
*(void **) &tramp[9] = codeloc; /* context */
/* Flush the icache. */
flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
closure->cif = cif;
closure->fun = fun;
@@ -682,8 +682,12 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure,
following helper function to do most of the work. */
int
ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
unsigned long *pgr, ffi_dblfl *pfr,
ffi_closure_helper_SYSV (ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data,
void *rvalue,
unsigned long *pgr,
ffi_dblfl *pfr,
unsigned long *pst)
{
/* rvalue is the pointer to space for return value in closure assembly */
@@ -699,7 +703,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
#endif
long ng = 0; /* number of general registers already used */
ffi_cif *cif = closure->cif;
unsigned size = cif->rtype->size;
unsigned short rtypenum = cif->rtype->type;
@@ -915,7 +918,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
i++;
}
(closure->fun) (cif, rvalue, avalue, closure->user_data);
(*fun) (cif, rvalue, avalue, user_data);
/* Tell ffi_closure_SYSV how to perform return type promotions.
Because the FFI_SYSV ABI returns the structures <= 8 bytes in