From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19748 invoked by alias); 29 Oct 2014 20:06:15 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 19690 invoked by uid 89); 29 Oct 2014 20:06:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qa0-f42.google.com Received: from mail-qa0-f42.google.com (HELO mail-qa0-f42.google.com) (209.85.216.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 29 Oct 2014 20:06:13 +0000 Received: by mail-qa0-f42.google.com with SMTP id k15so972707qaq.15 for ; Wed, 29 Oct 2014 13:06:11 -0700 (PDT) X-Received: by 10.224.69.67 with SMTP id y3mr19454918qai.76.1414613171070; Wed, 29 Oct 2014 13:06:11 -0700 (PDT) Received: from pike.twiddle.home.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id a12sm5020495qai.1.2014.10.29.13.06.09 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Oct 2014 13:06:10 -0700 (PDT) From: Richard Henderson To: libffi-discuss@sourceware.org Subject: [PATCH 10/10] arm: Add support for Go closures Date: Wed, 29 Oct 2014 20:06:00 -0000 Message-Id: <1414613147-10917-11-git-send-email-rth@twiddle.net> In-Reply-To: <1414613147-10917-1-git-send-email-rth@twiddle.net> References: <1414613147-10917-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00166.txt.bz2 --- src/arm/ffi.c | 76 ++++++++++++++++++++++++++++++++++++++++++++--------- src/arm/ffitarget.h | 1 + src/arm/sysv.S | 63 ++++++++++++++++++++++++++++---------------- 3 files changed, 105 insertions(+), 35 deletions(-) diff --git a/src/arm/ffi.c b/src/arm/ffi.c index eabab47..9c8732d 100644 --- a/src/arm/ffi.c +++ b/src/arm/ffi.c @@ -308,6 +308,7 @@ struct call_frame void *lr; void *rvalue; int flags; + void *closure; }; extern void ffi_call_SYSV (void *stack, struct call_frame *, @@ -315,8 +316,9 @@ extern void ffi_call_SYSV (void *stack, struct call_frame *, extern void ffi_call_VFP (void *vfp_space, struct call_frame *, void (*fn) (void), unsigned vfp_used) FFI_HIDDEN; -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) { int flags = cif->flags; ffi_type *rtype = cif->rtype; @@ -364,6 +366,7 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue) frame->rvalue = new_rvalue; frame->flags = flags; + frame->closure = closure; if (vfp_space) { @@ -380,6 +383,19 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue) memcpy (rvalue, new_rvalue, rtype->size); } +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); +} + static void * ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue, char *argp, void **avalue) @@ -476,31 +492,43 @@ ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack, return rvalue; } +struct closure_frame +{ + char vfp_space[8*8] __attribute__((aligned(8))); + char result[8*4]; + char argp[]; +}; + int FFI_HIDDEN -ffi_closure_inner_SYSV (ffi_closure *closure, void *rvalue, char *argp) +ffi_closure_inner_SYSV (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + struct closure_frame *frame) { - ffi_cif *cif = closure->cif; void **avalue = (void **) alloca (cif->nargs * sizeof (void *)); - - rvalue = ffi_prep_incoming_args_SYSV (cif, rvalue, argp, avalue); - closure->fun (cif, rvalue, avalue, closure->user_data); + void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result, + frame->argp, avalue); + fun (cif, rvalue, avalue, user_data); return cif->flags; } int FFI_HIDDEN -ffi_closure_inner_VFP (ffi_closure *closure, void *rvalue, - char *argp, char *vfp_space) +ffi_closure_inner_VFP (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + struct closure_frame *frame) { - ffi_cif *cif = closure->cif; void **avalue = (void **) alloca (cif->nargs * sizeof (void *)); - - rvalue = ffi_prep_incoming_args_VFP (cif, rvalue, argp, vfp_space, avalue); - closure->fun (cif, rvalue, avalue, closure->user_data); + void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp, + frame->vfp_space, avalue); + fun (cif, rvalue, avalue, user_data); return cif->flags; } void ffi_closure_SYSV (void) FFI_HIDDEN; void ffi_closure_VFP (void) FFI_HIDDEN; +void ffi_go_closure_SYSV (void) FFI_HIDDEN; +void ffi_go_closure_VFP (void) FFI_HIDDEN; #if FFI_EXEC_TRAMPOLINE_TABLE @@ -785,6 +813,28 @@ ffi_prep_closure_loc (ffi_closure * closure, return FFI_OK; } +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *)) +{ + void (*closure_func) (void) = ffi_go_closure_SYSV; + + if (cif->abi == FFI_VFP) + { + /* We only need take the vfp path if there are vfp arguments. */ + if (cif->vfp_used) + closure_func = ffi_go_closure_VFP; + } + else if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; + + closure->tramp = closure_func; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + /* Below are routines for VFP hard-float support. */ /* A subroutine of vfp_type_p. Given a structure type, return the type code diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h index 744a1e1..4f473f9 100644 --- a/src/arm/ffitarget.h +++ b/src/arm/ffitarget.h @@ -62,6 +62,7 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 12 #define FFI_NATIVE_RAW_API 0 diff --git a/src/arm/sysv.S b/src/arm/sysv.S index ce5450d..fd16589 100644 --- a/src/arm/sysv.S +++ b/src/arm/sysv.S @@ -136,6 +136,7 @@ ARM_FUNC_START(ffi_call_SYSV, 1) mov sp, r0 @ install the stack pointer mov lr, r2 @ move the fn pointer out of the way + ldr ip, [fp, #16] @ install the static chain ldmia sp!, {r0-r3} @ move first 4 parameters in registers. blx lr @ call fn @@ -180,22 +181,33 @@ ARM_FUNC_END(ffi_call_SYSV) /* - unsigned int FFI_HIDDEN - ffi_closure_inner (closure, respp, args) - ffi_closure *closure; - void **respp; - void *args; + int ffi_closure_inner_* (cif, fun, user_data, frame) */ +ARM_FUNC_START(ffi_go_closure_SYSV, 1) + cfi_startproc + stmdb sp!, {r0-r3} @ save argument regs + cfi_adjust_cfa_offset(16) + ldr r0, [ip, #4] @ load cif + ldr r1, [ip, #8] @ load fun + mov r2, ip @ load user_data + b 0f + cfi_endproc +ARM_FUNC_END(ffi_go_closure_SYSV) + ARM_FUNC_START(ffi_closure_SYSV, 1) UNWIND .fnstart cfi_startproc stmdb sp!, {r0-r3} @ save argument regs cfi_adjust_cfa_offset(16) - mov r0, ip @ load closure + ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif + ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun + ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data +0: add ip, sp, #16 @ compute entry sp - sub sp, sp, #32 @ allocate rvalue space - stmdb sp!, {sp,lr} + sub sp, sp, #64+32 @ allocate frame + cfi_adjust_cfa_offset(64+32) + stmdb sp!, {ip,lr} /* Remember that EABI unwind info only applies at call sites. We need do nothing except note the save of the stack pointer @@ -204,46 +216,53 @@ ARM_FUNC_START(ffi_closure_SYSV, 1) cfi_adjust_cfa_offset(8) cfi_rel_offset(lr, 4) - add r1, sp, #8 @ load respp - add r2, sp, #8+32 @ load args - mov r3, #0 @ load vfp_args - + add r3, sp, #8 @ load frame bl CNAME(ffi_closure_inner_SYSV) @ Load values returned in registers. - add r2, sp, #8 @ load respp + add r2, sp, #8+64 @ load result adr r3, CNAME(ffi_closure_ret) add pc, r3, r0, lsl #3 cfi_endproc UNWIND .fnend ARM_FUNC_END(ffi_closure_SYSV) +ARM_FUNC_START(ffi_go_closure_VFP, 1) + cfi_startproc + stmdb sp!, {r0-r3} @ save argument regs + cfi_adjust_cfa_offset(16) + ldr r0, [ip, #4] @ load cif + ldr r1, [ip, #8] @ load fun + mov r2, ip @ load user_data + b 0f + cfi_endproc +ARM_FUNC_END(ffi_go_closure_VFP) + ARM_FUNC_START(ffi_closure_VFP, 1) UNWIND .fnstart cfi_startproc stmdb sp!, {r0-r3} @ save argument regs cfi_adjust_cfa_offset(16) - sub sp, sp, #64+32 @ allocate vfp+rvalue space + ldr r0, [ip, #FFI_TRAMPOLINE_SIZE] @ load cif + ldr r1, [ip, #FFI_TRAMPOLINE_SIZE+4] @ load fun + ldr r2, [ip, #FFI_TRAMPOLINE_SIZE+8] @ load user_data +0: + add ip, sp, #16 + sub sp, sp, #64+32 @ allocate frame cfi_adjust_cfa_offset(64+32) stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7} - mov r0, ip @ load closure - add ip, sp, #16+64+32 @ compute entry sp stmdb sp!, {ip,lr} /* See above. */ UNWIND .save {sp,lr} cfi_adjust_cfa_offset(8) - cfi_rel_offset(sp, 0) cfi_rel_offset(lr, 4) - add r1, sp, #8+64 @ load respp - add r2, sp, #8+64+32 @ load args - add r3, sp, #8 @ load vfp_args - + add r3, sp, #8 @ load frame bl CNAME(ffi_closure_inner_VFP) @ Load values returned in registers. - add r2, sp, #8+64 @ load respp + add r2, sp, #8+64 @ load result adr r3, CNAME(ffi_closure_ret) add pc, r3, r0, lsl #3 cfi_endproc -- 1.9.3