From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11996 invoked by alias); 30 Oct 2014 03:54:55 -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 11927 invoked by uid 89); 30 Oct 2014 03:54:55 -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-pa0-f49.google.com Received: from mail-pa0-f49.google.com (HELO mail-pa0-f49.google.com) (209.85.220.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 30 Oct 2014 03:54:53 +0000 Received: by mail-pa0-f49.google.com with SMTP id lj1so4516325pab.8 for ; Wed, 29 Oct 2014 20:54:51 -0700 (PDT) X-Received: by 10.66.253.102 with SMTP id zz6mr14164346pac.25.1414641291259; Wed, 29 Oct 2014 20:54:51 -0700 (PDT) Received: from pike.twiddle.home (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPSA id qh7sm5676184pab.48.2014.10.29.20.54.49 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Oct 2014 20:54:50 -0700 (PDT) From: Richard Henderson To: libffi-discuss@sourceware.org Subject: [PATCH 4/4] alpha: Add support for Go closures Date: Thu, 30 Oct 2014 03:54:00 -0000 Message-Id: <1414641281-15172-5-git-send-email-rth@twiddle.net> In-Reply-To: <1414641281-15172-1-git-send-email-rth@twiddle.net> References: <1414641281-15172-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00175.txt.bz2 --- src/alpha/ffi.c | 53 ++++++++++++++++++++++++++------- src/alpha/ffitarget.h | 1 + src/alpha/osf.S | 82 ++++++++++++++++++++++++++++++++++----------------- 3 files changed, 99 insertions(+), 37 deletions(-) diff --git a/src/alpha/ffi.c b/src/alpha/ffi.c index 1e5187e..efae4cc 100644 --- a/src/alpha/ffi.c +++ b/src/alpha/ffi.c @@ -41,9 +41,11 @@ # define FFI_TYPE_LONGDOUBLE 4 #endif -extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void)) - FFI_HIDDEN; +extern void ffi_call_osf(void *stack, void *frame, unsigned flags, + void *raddr, void (*fn)(void), void *closure) + FFI_HIDDEN; extern void ffi_closure_osf(void) FFI_HIDDEN; +extern void ffi_go_closure_osf(void) FFI_HIDDEN; /* Promote a float value to its in-register double representation. Unlike actually casting to double, this does not trap on NaN. */ @@ -222,12 +224,14 @@ extend_basic_type(void *valp, int type, int argn) } } -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) { unsigned long *argp; long i, avn, argn, flags = cif->flags; ffi_type **arg_types; + void *frame; /* If the return value is a struct and we don't have a return value address then we need to make one. */ @@ -236,7 +240,8 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) /* Allocate the space for the arguments, plus 4 words of temp space for ffi_call_osf. */ - argp = alloca(cif->bytes + 4*FFI_SIZEOF_ARG); + argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG); + frame += cif->bytes; argn = 0; if (flags == ALPHA_RET_IN_MEM) @@ -301,9 +306,21 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } flags = (flags >> ALPHA_ST_SHIFT) & 0xff; - ffi_call_osf(argp, cif->bytes, flags, rvalue, fn); + ffi_call_osf(argp, frame, flags, rvalue, fn, 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); +} ffi_status ffi_prep_closure_loc (ffi_closure* closure, @@ -339,15 +356,31 @@ 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_OSF) + return FFI_BAD_ABI; + + closure->tramp = (void *)ffi_go_closure_osf; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + long FFI_HIDDEN -ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) +ffi_closure_osf_inner (ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *rvalue, unsigned long *argp) { - ffi_cif *cif; void **avalue; ffi_type **arg_types; long i, avn, argn, flags; - cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); flags = cif->flags; argn = 0; @@ -481,7 +514,7 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) } /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); + fun (cif, rvalue, avalue, user_data); /* Tell ffi_closure_osf how to perform return type promotions. */ return (flags >> ALPHA_LD_SHIFT) & 0xff; diff --git a/src/alpha/ffitarget.h b/src/alpha/ffitarget.h index 60f92fd..a02dbd0 100644 --- a/src/alpha/ffitarget.h +++ b/src/alpha/ffitarget.h @@ -50,6 +50,7 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 24 #define FFI_NATIVE_RAW_API 0 diff --git a/src/alpha/osf.S b/src/alpha/osf.S index 4059f82..b031828 100644 --- a/src/alpha/osf.S +++ b/src/alpha/osf.S @@ -39,10 +39,10 @@ .org 99b + \index * 16 .endm -/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); +/* ffi_call_osf (void *stack, void *frame, unsigned flags, + void *raddr, void (*fnaddr)(void), void *closure) - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame + Bit o trickiness here -- FRAME is the base of the stack frame for this function. This has been allocated by ffi_call. We also deallocate some of the stack that has been alloca'd. */ @@ -52,22 +52,21 @@ FFI_HIDDEN(ffi_call_osf) ffi_call_osf: - .frame $15, 32, $26, 0 - .mask 0x4008000, -32 cfi_startproc - addq $16,$17,$1 + cfi_def_cfa($17, 32) mov $16, $30 - stq $26, 0($1) - stq $15, 8($1) - stq $18, 16($1) - mov $1, $15 + stq $26, 0($17) + stq $15, 8($17) + mov $17, $15 .prologue 0 - cfi_def_cfa($15, 32) + cfi_def_cfa_register($15) cfi_rel_offset($26, 0) cfi_rel_offset($15, 8) - stq $19, 24($1) - mov $20, $27 + stq $18, 16($17) # save flags into frame + stq $19, 24($17) # save rvalue into frame + mov $20, $27 # fn into place for call + mov $21, $1 # closure into static chain # Load up all of the (potential) argument registers. ldq $16, 0($30) @@ -89,16 +88,16 @@ ffi_call_osf: jsr $26, ($27), 0 0: ldah $29, 0($26) !gpdisp!1 - ldq $2, 24($15) + ldq $2, 24($15) # reload rvalue lda $29, 0($29) !gpdisp!1 - ldq $3, 16($15) + ldq $3, 16($15) # reload flags lda $1, 99f-0b($26) ldq $26, 0($15) ldq $15, 8($15) cfi_restore($26) cfi_restore($15) cfi_def_cfa($sp, 0) - cmoveq $2, ALPHA_ST_VOID, $3 # mash null return to void + cmoveq $2, ALPHA_ST_VOID, $3 # mash null rvalue to void addq $3, $3, $3 s8addq $3, $1, $1 # 99f + stcode * 16 jmp $31, ($1), $st_int @@ -136,13 +135,37 @@ E ALPHA_ST_CPLXD #define CLOSURE_FS (16*8) .align 4 + .globl ffi_go_closure_osf + .ent ffi_go_closure_osf + FFI_HIDDEN(ffi_go_closure_osf) + +ffi_go_closure_osf: + cfi_startproc + ldgp $29, 0($27) + subq $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(CLOSURE_FS) + stq $26, 0($30) + .prologue 1 + cfi_rel_offset($26, 0) + + stq $16, 10*8($30) + stq $17, 11*8($30) + stq $18, 12*8($30) + + ldq $16, 8($1) # load cif + ldq $17, 16($1) # load fun + mov $1, $18 # closure is user_data + br $do_closure + + cfi_endproc + .end ffi_go_closure_osf + + .align 4 .globl ffi_closure_osf .ent ffi_closure_osf FFI_HIDDEN(ffi_closure_osf) ffi_closure_osf: - .frame $30, CLOSURE_FS, $26, 0 - .mask 0x4000000, -CLOSURE_FS cfi_startproc ldgp $29, 0($27) subq $30, CLOSURE_FS, $30 @@ -152,23 +175,28 @@ ffi_closure_osf: cfi_rel_offset($26, 0) # Store all of the potential argument registers in va_list format. - stt $f16, 4*8($30) - stt $f17, 5*8($30) - stt $f18, 6*8($30) - stt $f19, 7*8($30) - stt $f20, 8*8($30) - stt $f21, 9*8($30) stq $16, 10*8($30) stq $17, 11*8($30) stq $18, 12*8($30) + + ldq $16, 24($1) # load cif + ldq $17, 32($1) # load fun + ldq $18, 40($1) # load user_data + +$do_closure: stq $19, 13*8($30) stq $20, 14*8($30) stq $21, 15*8($30) + stt $f16, 4*8($30) + stt $f17, 5*8($30) + stt $f18, 6*8($30) + stt $f19, 7*8($30) + stt $f20, 8*8($30) + stt $f21, 9*8($30) # Call ffi_closure_osf_inner to do the bulk of the work. - mov $1, $16 - lda $17, 2*8($30) - lda $18, 10*8($30) + lda $19, 2*8($30) + lda $20, 10*8($30) jsr $26, ffi_closure_osf_inner 0: ldah $29, 0($26) !gpdisp!2 -- 1.9.3