From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9798 invoked by alias); 7 Nov 2014 15:31:12 -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 9731 invoked by uid 89); 7 Nov 2014 15:31:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 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-wg0-f47.google.com Received: from mail-wg0-f47.google.com (HELO mail-wg0-f47.google.com) (74.125.82.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 07 Nov 2014 15:31:10 +0000 Received: by mail-wg0-f47.google.com with SMTP id a1so4013361wgh.20 for ; Fri, 07 Nov 2014 07:31:07 -0800 (PST) X-Received: by 10.194.239.104 with SMTP id vr8mr17115215wjc.18.1415374267180; Fri, 07 Nov 2014 07:31:07 -0800 (PST) Received: from pike.twiddle.home.com ([87.111.149.167]) by mx.google.com with ESMTPSA id p1sm12186731wjy.22.2014.11.07.07.31.06 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 07 Nov 2014 07:31:06 -0800 (PST) From: Richard Henderson To: libffi-discuss@sourceware.org Subject: [PATCH 10/13] x86: Add support for Go closures Date: Fri, 07 Nov 2014 15:31:00 -0000 Message-Id: <1415374240-1792-11-git-send-email-rth@twiddle.net> In-Reply-To: <1415374240-1792-1-git-send-email-rth@twiddle.net> References: <1415374240-1792-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00197.txt.bz2 --- src/x86/ffi.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++------- src/x86/ffitarget.h | 2 +- src/x86/sysv.S | 34 +++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 11 deletions(-) diff --git a/src/x86/ffi.c b/src/x86/ffi.c index a0d0cf3..359a864 100644 --- a/src/x86/ffi.c +++ b/src/x86/ffi.c @@ -218,25 +218,28 @@ struct call_frame struct abi_params { int dir; /* parameter growth direction */ + int static_chain; /* the static chain register used by gcc */ int nregs; /* number of register parameters */ int regs[3]; }; static const struct abi_params abi_params[FFI_LAST_ABI] = { - [FFI_SYSV] = { 1, 0 }, - [FFI_THISCALL] = { 1, 1, { R_ECX } }, - [FFI_FASTCALL] = { 1, 2, { R_ECX, R_EDX } }, - [FFI_STDCALL] = { 1, 0 }, - [FFI_PASCAL] = { -1, 0 }, - [FFI_REGISTER] = { -1, 3, { R_EAX, R_EDX, R_ECX } }, - [FFI_MS_CDECL] = { 1, 0 } + [FFI_SYSV] = { 1, R_ECX, 0 }, + [FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } }, + [FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } }, + [FFI_STDCALL] = { 1, R_ECX, 0 }, + [FFI_PASCAL] = { -1, R_ECX, 0 }, + /* ??? No defined static chain; gcc does not support REGISTER. */ + [FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } }, + [FFI_MS_CDECL] = { 1, R_ECX, 0 } }; extern void ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN __declspec(fastcall); -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 rsize, bytes; struct call_frame *frame; @@ -281,6 +284,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) frame->fn = fn; frame->flags = flags; frame->rvalue = rvalue; + frame->regs[pabi->static_chain] = (unsigned)closure; narg_reg = 0; switch (flags) @@ -345,6 +349,18 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ffi_call_i386 (frame, stack); } +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); +} /** private members **/ @@ -493,6 +509,42 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +void FFI_HIDDEN ffi_go_closure_EAX(void); +void FFI_HIDDEN ffi_go_closure_ECX(void); +void FFI_HIDDEN ffi_go_closure_STDCALL(void); + +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + void (*dest)(void); + + switch (cif->abi) + { + case FFI_SYSV: + case FFI_MS_CDECL: + dest = ffi_go_closure_ECX; + break; + case FFI_THISCALL: + case FFI_FASTCALL: + dest = ffi_go_closure_ECX; + break; + case FFI_STDCALL: + case FFI_PASCAL: + dest = ffi_go_closure_STDCALL; + break; + case FFI_REGISTER: + default: + return FFI_BAD_ABI; + } + + closure->tramp = dest; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + /* ------- Native raw API support -------------------------------- */ #if !FFI_NO_RAW_API diff --git a/src/x86/ffitarget.h b/src/x86/ffitarget.h index 8fff29f..580522f 100644 --- a/src/x86/ffitarget.h +++ b/src/x86/ffitarget.h @@ -117,6 +117,7 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) #define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) @@ -127,7 +128,6 @@ typedef enum ffi_abi { || (defined (__x86_64__) && defined (X86_DARWIN)) # define FFI_TRAMPOLINE_SIZE 24 # define FFI_NATIVE_RAW_API 0 -# define FFI_GO_CLOSURES 1 #else # define FFI_TRAMPOLINE_SIZE 12 # define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ diff --git a/src/x86/sysv.S b/src/x86/sysv.S index 7b898ae..f412b7a 100644 --- a/src/x86/sysv.S +++ b/src/x86/sysv.S @@ -228,6 +228,28 @@ ENDF(C(ffi_call_i386)) jmp *%eax .endm +.macro FFI_GO_CLOSURE suffix, chain, t1, t2 + .align 16 + .globl C(ffi_go_closure_\suffix) + FFI_HIDDEN(C(ffi_go_closure_\suffix)) +C(ffi_go_closure_\suffix): + cfi_startproc + subl $closure_FS, %esp + cfi_adjust_cfa_offset(closure_FS) + FFI_CLOSURE_SAVE_REGS + movl 4(\chain), \t1 /* copy cif */ + movl 8(\chain), \t2 /* copy fun */ + movl \t1, 28(%esp) + movl \t2, 32(%esp) + movl \chain, 36(%esp) /* closure is user_data */ + jmp 88f + cfi_endproc +ENDF(C(ffi_go_closure_\suffix)) +.endm + +FFI_GO_CLOSURE EAX, %eax, %edx, %ecx +FFI_GO_CLOSURE ECX, %ecx, %edx, %eax + /* The closure entry points are reached from the ffi_closure trampoline. On entry, %eax contains the address of the ffi_closure. */ @@ -242,6 +264,9 @@ C(ffi_closure_i386): FFI_CLOSURE_SAVE_REGS FFI_CLOSURE_COPY_TRAMP_DATA + +88: /* Entry point from preceeding Go closures. */ + FFI_CLOSURE_CALL_INNER FFI_CLOSURE_MASK_AND_JUMP @@ -303,6 +328,8 @@ E(X86_RET_UNUSED15) cfi_endproc ENDF(C(ffi_closure_i386)) +FFI_GO_CLOSURE STDCALL, %ecx, %edx, %eax + /* For REGISTER, we have no available parameter registers, and so we enter here having pushed the closure onto the stack. */ @@ -339,8 +366,13 @@ C(ffi_closure_STDCALL): cfi_adjust_cfa_offset(closure_FS) FFI_CLOSURE_SAVE_REGS -0: + +0: /* Entry point from ffi_closure_REGISTER. */ + FFI_CLOSURE_COPY_TRAMP_DATA + +88: /* Entry point from preceeding Go closure. */ + FFI_CLOSURE_CALL_INNER movl %eax, %ecx -- 1.9.3