From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14645 invoked by alias); 10 Oct 2014 20:43:51 -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 14102 invoked by uid 89); 10 Oct 2014 20:43:47 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 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-qg0-f42.google.com Received: from mail-qg0-f42.google.com (HELO mail-qg0-f42.google.com) (209.85.192.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 10 Oct 2014 20:43:45 +0000 Received: by mail-qg0-f42.google.com with SMTP id z60so4534426qgd.15 for ; Fri, 10 Oct 2014 13:43:43 -0700 (PDT) X-Received: by 10.224.76.5 with SMTP id a5mr12804121qak.72.1412973823744; Fri, 10 Oct 2014 13:43:43 -0700 (PDT) Received: from anchor.com (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id s49sm5909008qge.15.2014.10.10.13.43.42 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 10 Oct 2014 13:43:43 -0700 (PDT) From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: libffi-discuss@sourceware.org, gofrontend-dev@googlegroups.com Subject: [PATCH 11/13] libffi: Support go closures on aarch64 Date: Fri, 10 Oct 2014 20:43:00 -0000 Message-Id: <1412973773-3942-12-git-send-email-rth@redhat.com> In-Reply-To: <1412973773-3942-1-git-send-email-rth@redhat.com> References: <1412973773-3942-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes X-SW-Source: 2014/txt/msg00105.txt.bz2 --- libffi/src/aarch64/ffi.c | 42 ++++++++++++++++++++++++++--- libffi/src/aarch64/ffitarget.h | 3 ++- libffi/src/aarch64/sysv.S | 60 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/libffi/src/aarch64/ffi.c b/libffi/src/aarch64/ffi.c index c409c0c..1fe5a60 100644 --- a/libffi/src/aarch64/ffi.c +++ b/libffi/src/aarch64/ffi.c @@ -72,10 +72,13 @@ get_d_addr (struct call_context *context, unsigned n) extern void ffi_call_SYSV (void *frame, void *rvalue, struct call_context *context, - unsigned flags, void (*fn)(void)) FFI_HIDDEN; + unsigned flags, void (*fn)(void), + void *static_chain) FFI_HIDDEN; extern void ffi_closure_SYSV (void) FFI_HIDDEN; extern void ffi_closure_SYSV_V (void) FFI_HIDDEN; +extern void ffi_go_closure_SYSV (void) FFI_HIDDEN; +extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN; /* A subroutine of is_hfa. Given a structure type, return the type code of the first non-structure element. Recurse for structure elements. @@ -336,8 +339,9 @@ ffi_prep_cif_machdep (ffi_cif *cif) /* Call a function with the provided arguments and capture the return value. */ -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) { struct call_context *context; UINT64 *stack, *slot; @@ -533,11 +537,24 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } size = cif->rtype->size; - ffi_call_SYSV (frame, local_rvalue, context, cif->flags, fn); + ffi_call_SYSV (frame, local_rvalue, context, cif->flags, fn, closure); if (local_rvalue != rvalue && rvalue != NULL) memcpy (rvalue, local_rvalue, 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); +} + /* Build a trampoline. */ ffi_status @@ -574,6 +591,23 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +/* 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 = (cif->flags & AARCH64_FLAG_ARG_V + ? ffi_go_closure_SYSV_V : ffi_go_closure_SYSV); + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + /* Primary handler to setup and invoke a function within a closure. A closure when invoked enters via the assembler wrapper diff --git a/libffi/src/aarch64/ffitarget.h b/libffi/src/aarch64/ffitarget.h index ecfa159..bb7340b 100644 --- a/libffi/src/aarch64/ffitarget.h +++ b/libffi/src/aarch64/ffitarget.h @@ -42,7 +42,8 @@ typedef enum ffi_abi /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 24 +#define FFI_GO_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 24 #define FFI_NATIVE_RAW_API 0 #endif diff --git a/libffi/src/aarch64/sysv.S b/libffi/src/aarch64/sysv.S index 126c527..0544176 100644 --- a/libffi/src/aarch64/sysv.S +++ b/libffi/src/aarch64/sysv.S @@ -35,7 +35,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ extern void ffi_call_SYSV (void *frame, void *rvalue, struct call_context *context, - unsigned flags, void (*fn)(void)) + unsigned flags, void (*fn)(void), void *static_chain) This function uses an unusual stack layout. Our local frame has been allocated by the caller in FRAME with the outgoing arguments @@ -60,6 +60,7 @@ ffi_call_SYSV: mov x8, x1 /* rvalue into place */ mov x10, x2 /* context */ mov x11, x4 /* fn */ + mov x18, x5 /* static chain into place */ /* Load the vector argument passing registers, if needed. */ tbz w3, #AARCH64_FLAG_ARG_V_BIT, 1f @@ -304,3 +305,60 @@ ffi_closure_SYSV: ret .cfi_endproc .size ffi_closure_SYSV, .-ffi_closure_SYSV + +/* ffi_go_closure_SYSV + + Similarly for a Go closure. The difference here is that the + calling convention loads x18 with the ffi_go_closure structure + automatically. Further, the ffi_go_closure is also the user_data + that want passed to the inner function. +*/ + + .globl ffi_go_closure_SYSV_V + .hidden ffi_go_closure_SYSV_V + .type ffi_go_closure_SYSV_V, %function + .balign 32 + +ffi_go_closure_SYSV_V: + .cfi_startproc + stp x29, x30, [sp, #-ffi_closure_FS]! + .cfi_adjust_cfa_offset ffi_closure_FS + .cfi_rel_offset x29, 0 + .cfi_rel_offset x30, 8 + mov x29, sp + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 8*AARCH64_N_XREG + 0] + stp q2, q3, [sp, #16 + 8*AARCH64_N_XREG + 32] + stp q4, q5, [sp, #16 + 8*AARCH64_N_XREG + 64] + stp q6, q7, [sp, #16 + 8*AARCH64_N_XREG + 96] + b 0f + + .cfi_endproc + .size ffi_go_closure_SYSV_V, . - ffi_go_closure_SYSV_V + + .globl ffi_go_closure_SYSV + .hidden ffi_go_closure_SYSV + .type ffi_go_closure_SYSV, %function + .balign 32 + +ffi_go_closure_SYSV: + .cfi_startproc + stp x29, x30, [sp, #-ffi_closure_FS]! + .cfi_adjust_cfa_offset ffi_closure_FS + .cfi_rel_offset x29, 0 + .cfi_rel_offset x30, 8 + mov x29, sp + + /* Save the argument passing core registers. */ +0: stp x0, x1, [sp, #16 + 0] + stp x2, x3, [sp, #16 + 16] + stp x4, x5, [sp, #16 + 32] + stp x6, x7, [sp, #16 + 48] + + ldp x0, x1, [x18, #8] /* cif and fun */ + mov x2, x18 /* user_data */ + b .Ldo_closure + + .cfi_endproc + .size ffi_go_closure_SYSV, . - ffi_go_closure_SYSV -- 1.9.3