public inbox for libffi-discuss@sourceware.org
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: libffi-discuss@sourceware.org
Subject: [PATCH 10/13] x86: Add support for Go closures
Date: Fri, 07 Nov 2014 15:31:00 -0000	[thread overview]
Message-ID: <1415374240-1792-11-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1415374240-1792-1-git-send-email-rth@twiddle.net>

---
 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

  parent reply	other threads:[~2014-11-07 15:31 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-07 15:30 [PATCH 00/13] Go closures for i686 Richard Henderson
2014-11-07 15:30 ` [PATCH 02/13] x86: Remove some conditional compilation Richard Henderson
2014-11-07 15:31 ` [PATCH 09/13] x86: Add support for Complex Richard Henderson
2014-11-07 15:31 ` [PATCH 11/13] x86: Use win32 name mangling for fastcall functions Richard Henderson
2014-11-07 15:31 ` Richard Henderson [this message]
2014-11-07 15:31 ` [PATCH 12/13] testsuite: Add two dg-do run markers Richard Henderson
2014-11-07 15:31 ` [PATCH 05/13] ffi_cif: Add cfa_escape Richard Henderson
2014-11-07 15:31 ` [PATCH 07/13] x86: Rewrite closures Richard Henderson
2014-11-07 15:31 ` [PATCH 03/13] x86: Force FFI_TYPE_LONGDOUBLE different from FFI_TYPE_DOUBLE Richard Henderson
2014-11-07 15:31 ` [PATCH 13/13] x86: Work around two clang assembler bugs Richard Henderson
2014-11-07 15:31 ` [PATCH 08/13] testsuite: Fix return_complex2 vs excessive precision Richard Henderson
2014-11-07 15:31 ` [PATCH 01/13] x86: Tidy ffi_abi Richard Henderson
2014-11-07 15:31 ` [PATCH 06/13] x86: Rewrite ffi_call Richard Henderson
2014-11-07 15:31 ` [PATCH 04/13] x86: Convert to gas generated unwind info Richard Henderson
2014-11-07 16:09 ` [PATCH 00/13] Go closures for i686 Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1415374240-1792-11-git-send-email-rth@twiddle.net \
    --to=rth@twiddle.net \
    --cc=libffi-discuss@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).