From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9500 invoked by alias); 28 Oct 2014 19:46:45 -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 9381 invoked by uid 89); 28 Oct 2014 19:46:43 -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-qg0-f45.google.com Received: from mail-qg0-f45.google.com (HELO mail-qg0-f45.google.com) (209.85.192.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 28 Oct 2014 19:46:40 +0000 Received: by mail-qg0-f45.google.com with SMTP id z107so1137957qgd.18 for ; Tue, 28 Oct 2014 12:46:38 -0700 (PDT) X-Received: by 10.140.43.194 with SMTP id e60mr8169753qga.10.1414525598652; Tue, 28 Oct 2014 12:46:38 -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 11sm2042715qgj.34.2014.10.28.12.46.37 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Oct 2014 12:46:38 -0700 (PDT) From: Richard Henderson To: libffi-discuss@sourceware.org Cc: davem@davemloft.net Subject: [PATCH 7/8] sparc: Add support for Go closures Date: Tue, 28 Oct 2014 19:46:00 -0000 Message-Id: <1414525555-21256-8-git-send-email-rth@twiddle.net> In-Reply-To: <1414525555-21256-1-git-send-email-rth@twiddle.net> References: <1414525555-21256-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00156.txt.bz2 --- src/sparc/ffi.c | 45 +++++++++++++++++++++++++++++++++++++-------- src/sparc/ffi64.c | 45 +++++++++++++++++++++++++++++++++++++-------- src/sparc/ffitarget.h | 1 + src/sparc/v8.S | 38 ++++++++++++++++++++++++++++++-------- src/sparc/v9.S | 33 ++++++++++++++++++++++++++++----- 5 files changed, 133 insertions(+), 29 deletions(-) diff --git a/src/sparc/ffi.c b/src/sparc/ffi.c index d319c03..19c3586 100644 --- a/src/sparc/ffi.c +++ b/src/sparc/ffi.c @@ -176,7 +176,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) } extern void ffi_call_v8(ffi_cif *cif, void (*fn)(void), void *rvalue, - void **avalue, size_t bytes) FFI_HIDDEN; + void **avalue, size_t bytes, void *closure) FFI_HIDDEN; int FFI_HIDDEN ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) @@ -280,8 +280,9 @@ ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) return flags; } -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) { size_t bytes = cif->bytes; @@ -292,7 +293,20 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) if (rvalue == NULL && cif->flags == SPARC_RET_STRUCT) bytes += ALIGN (cif->rtype->size, 8); - ffi_call_v8(cif, fn, rvalue, avalue, -bytes); + ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure); +} + +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); } #ifdef __GNUC__ @@ -308,6 +322,7 @@ extern void ffi_flush_icache (void *) FFI_HIDDEN; #endif extern void ffi_closure_v8(void) FFI_HIDDEN; +extern void ffi_go_closure_v8(void) FFI_HIDDEN; ffi_status ffi_prep_closure_loc (ffi_closure *closure, @@ -337,16 +352,30 @@ 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*)) +{ + if (cif->abi != FFI_V8) + return FFI_BAD_ABI; + + closure->tramp = ffi_go_closure_v8; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + int FFI_HIDDEN -ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue, +ffi_closure_sparc_inner_v8(ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, unsigned long *argp) { - ffi_cif *cif; ffi_type **arg_types; void **avalue; int i, nargs, flags; - cif = closure->cif; arg_types = cif->arg_types; nargs = cif->nargs; flags = cif->flags; @@ -424,7 +453,7 @@ ffi_closure_sparc_inner_v8(ffi_closure *closure, void *rvalue, } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); + fun (cif, rvalue, avalue, user_data); /* Tell ffi_closure_sparc how to perform return type promotions. */ return flags; diff --git a/src/sparc/ffi64.c b/src/sparc/ffi64.c index 1e2d3f4..02f3d75 100644 --- a/src/sparc/ffi64.c +++ b/src/sparc/ffi64.c @@ -305,7 +305,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) } extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue, - void **avalue, size_t bytes) FFI_HIDDEN; + void **avalue, size_t bytes, void *closure) FFI_HIDDEN; /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ @@ -402,8 +402,9 @@ ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) return flags; } -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) { size_t bytes = cif->bytes; @@ -412,7 +413,20 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM)) bytes += ALIGN (cif->rtype->size, 16); - ffi_call_v9(cif, fn, rvalue, avalue, -bytes); + ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure); +} + +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); } #ifdef __GNUC__ @@ -426,6 +440,7 @@ extern void ffi_flush_icache (void *) FFI_HIDDEN; #endif extern void ffi_closure_v9(void) FFI_HIDDEN; +extern void ffi_go_closure_v9(void) FFI_HIDDEN; ffi_status ffi_prep_closure_loc (ffi_closure* closure, @@ -458,16 +473,30 @@ 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*)) +{ + if (cif->abi != FFI_V9) + return FFI_BAD_ABI; + + closure->tramp = ffi_go_closure_v9; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + int FFI_HIDDEN -ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue, +ffi_closure_sparc_inner_v9(ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, unsigned long *gpr, unsigned long *fpr) { - ffi_cif *cif; ffi_type **arg_types; void **avalue; int i, argn, argx, nargs, flags; - cif = closure->cif; arg_types = cif->arg_types; nargs = cif->nargs; flags = cif->flags; @@ -555,7 +584,7 @@ ffi_closure_sparc_inner_v9(ffi_closure *closure, void *rvalue, } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); + fun (cif, rvalue, avalue, user_data); /* Tell ffi_closure_sparc how to perform return type promotions. */ return flags; diff --git a/src/sparc/ffitarget.h b/src/sparc/ffitarget.h index f70c937..6982903 100644 --- a/src/sparc/ffitarget.h +++ b/src/sparc/ffitarget.h @@ -63,6 +63,7 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 #ifdef SPARC64 diff --git a/src/sparc/v8.S b/src/sparc/v8.S index e76d813..66cf76f 100644 --- a/src/sparc/v8.S +++ b/src/sparc/v8.S @@ -102,7 +102,7 @@ C(ffi_call_v8): ! Call foreign function call %i1 - nop + mov %i5, %g2 ! load static chain 0: call 1f ! load pc in %o7 sll %l0, 4, %l0 @@ -185,7 +185,7 @@ E SPARC_RET_F_1 ! Struct returning functions expect and skip the unimp here. .align 8 8: call %i1 - nop + mov %i5, %g2 ! load static chain unimp 4 ret restore @@ -211,20 +211,43 @@ E SPARC_RET_F_1 Receives the closure argument in %g2. */ +#ifdef HAVE_AS_REGISTER_PSEUDO_OP + .register %g2, #scratch +#endif + + .align 8 + .globl C(ffi_go_closure_v8) + .type C(ffi_go_closure_v8),@function + FFI_HIDDEN(C(ffi_go_closure_v8)) + +C(ffi_go_closure_v8): + cfi_startproc + save %sp, -STACKFRAME, %sp + cfi_def_cfa_register(%fp) + cfi_window_save + + ld [%g2+4], %o0 ! load cif + ld [%g2+8], %o1 ! load fun + b 0f + mov %g2, %o2 ! load user_data + cfi_endproc + .size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8) + .align 8 .globl C(ffi_closure_v8) .type C(ffi_closure_v8),@function FFI_HIDDEN(C(ffi_closure_v8)) C(ffi_closure_v8): -#ifdef HAVE_AS_REGISTER_PSEUDO_OP - .register %g2, #scratch -#endif cfi_startproc save %sp, -STACKFRAME, %sp cfi_def_cfa_register(%fp) cfi_window_save + ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif + ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun + ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data +0: ! Store all of the potential argument registers in va_list format. st %i0, [%fp+68+0] st %i1, [%fp+68+4] @@ -234,10 +257,9 @@ C(ffi_closure_v8): st %i5, [%fp+68+20] ! Call ffi_closure_sparc_inner to do the bulk of the work. - mov %g2, %o0 - add %fp, -8*4, %o1 + add %fp, -8*4, %o3 call ffi_closure_sparc_inner_v8 - add %fp, 64, %o2 + add %fp, 64, %o4 0: call 1f and %o0, SPARC_FLAG_RET_MASK, %o0 diff --git a/src/sparc/v9.S b/src/sparc/v9.S index 5c3f27b..d848f9a 100644 --- a/src/sparc/v9.S +++ b/src/sparc/v9.S @@ -94,8 +94,9 @@ C(ffi_call_v9): ldx [%sp+STACK_BIAS+128+16], %o2 ldx [%sp+STACK_BIAS+128+24], %o3 ldx [%sp+STACK_BIAS+128+32], %o4 + ldx [%sp+STACK_BIAS+128+40], %o5 call %i1 - ldx [%sp+STACK_BIAS+128+40], %o5 + mov %i5, %g5 ! load static chain 0: call 1f ! load pc in %o7 and %l0, SPARC_FLAG_RET_MASK, %l1 @@ -211,6 +212,25 @@ E SPARC_RET_F_1 Receives the closure argument in %g1. */ .align 8 + .globl C(ffi_go_closure_v9) + .type C(ffi_go_closure_v9),@function + FFI_HIDDEN(C(ffi_go_closure_v9)) + +C(ffi_go_closure_v9): + cfi_startproc + save %sp, -STACKFRAME, %sp + cfi_def_cfa_register(%fp) + cfi_window_save + + ldx [%g5+8], %o0 + ldx [%g5+16], %o1 + b 0f + mov %g5, %o2 + + cfi_endproc + .size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9) + + .align 8 .globl C(ffi_closure_v9) .type C(ffi_closure_v9),@function FFI_HIDDEN(C(ffi_closure_v9)) @@ -221,6 +241,10 @@ C(ffi_closure_v9): cfi_def_cfa_register(%fp) cfi_window_save + ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0 + ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1 + ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2 +0: ! Store all of the potential argument registers in va_list format. stx %i0, [FP+128+0] stx %i1, [FP+128+8] @@ -248,11 +272,10 @@ C(ffi_closure_v9): std %f30, [FP-8] ! Call ffi_closure_sparc_inner to do the bulk of the work. - mov %g1, %o0 - add %fp, STACK_BIAS-160, %o1 - add %fp, STACK_BIAS+128, %o2 + add %fp, STACK_BIAS-160, %o3 + add %fp, STACK_BIAS+128, %o4 call C(ffi_closure_sparc_inner_v9) - add %fp, STACK_BIAS-128, %o3 + add %fp, STACK_BIAS-128, %o5 0: call 1f ! load pc in %o7 and %o0, SPARC_FLAG_RET_MASK, %o0 -- 1.9.3