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/10] arm: Add support for Go closures
Date: Wed, 29 Oct 2014 20:06:00 -0000	[thread overview]
Message-ID: <1414613147-10917-11-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1414613147-10917-1-git-send-email-rth@twiddle.net>

---
 src/arm/ffi.c       | 76 ++++++++++++++++++++++++++++++++++++++++++++---------
 src/arm/ffitarget.h |  1 +
 src/arm/sysv.S      | 63 ++++++++++++++++++++++++++++----------------
 3 files changed, 105 insertions(+), 35 deletions(-)

diff --git a/src/arm/ffi.c b/src/arm/ffi.c
index eabab47..9c8732d 100644
--- a/src/arm/ffi.c
+++ b/src/arm/ffi.c
@@ -308,6 +308,7 @@ struct call_frame
   void *lr;
   void *rvalue;
   int flags;
+  void *closure;
 };
 
 extern void ffi_call_SYSV (void *stack, struct call_frame *,
@@ -315,8 +316,9 @@ extern void ffi_call_SYSV (void *stack, struct call_frame *,
 extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
 			   void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
 
-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)
 {
   int flags = cif->flags;
   ffi_type *rtype = cif->rtype;
@@ -364,6 +366,7 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
 
   frame->rvalue = new_rvalue;
   frame->flags = flags;
+  frame->closure = closure;
 
   if (vfp_space)
     {
@@ -380,6 +383,19 @@ ffi_call (ffi_cif * cif, void (*fn) (void), void *rvalue, void **avalue)
     memcpy (rvalue, new_rvalue, rtype->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);
+}
+
 static void *
 ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
 			     char *argp, void **avalue)
@@ -476,31 +492,43 @@ ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
   return rvalue;
 }
 
+struct closure_frame
+{
+  char vfp_space[8*8] __attribute__((aligned(8)));
+  char result[8*4];
+  char argp[];
+};
+
 int FFI_HIDDEN
-ffi_closure_inner_SYSV (ffi_closure *closure, void *rvalue, char *argp)
+ffi_closure_inner_SYSV (ffi_cif *cif,
+		        void (*fun) (ffi_cif *, void *, void **, void *),
+		        void *user_data,
+		        struct closure_frame *frame)
 {
-  ffi_cif *cif = closure->cif;
   void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
-
-  rvalue = ffi_prep_incoming_args_SYSV (cif, rvalue, argp, avalue);
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
+					      frame->argp, avalue);
+  fun (cif, rvalue, avalue, user_data);
   return cif->flags;
 }
 
 int FFI_HIDDEN
-ffi_closure_inner_VFP (ffi_closure *closure, void *rvalue,
-		       char *argp, char *vfp_space)
+ffi_closure_inner_VFP (ffi_cif *cif,
+		       void (*fun) (ffi_cif *, void *, void **, void *),
+		       void *user_data,
+		       struct closure_frame *frame)
 {
-  ffi_cif *cif = closure->cif;
   void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
-
-  rvalue = ffi_prep_incoming_args_VFP (cif, rvalue, argp, vfp_space, avalue);
-  closure->fun (cif, rvalue, avalue, closure->user_data);
+  void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
+					     frame->vfp_space, avalue);
+  fun (cif, rvalue, avalue, user_data);
   return cif->flags;
 }
 
 void ffi_closure_SYSV (void) FFI_HIDDEN;
 void ffi_closure_VFP (void) FFI_HIDDEN;
+void ffi_go_closure_SYSV (void) FFI_HIDDEN;
+void ffi_go_closure_VFP (void) FFI_HIDDEN;
 
 #if FFI_EXEC_TRAMPOLINE_TABLE
 
@@ -785,6 +813,28 @@ 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 *))
+{
+  void (*closure_func) (void) = ffi_go_closure_SYSV;
+
+  if (cif->abi == FFI_VFP)
+    {
+      /* We only need take the vfp path if there are vfp arguments.  */
+      if (cif->vfp_used)
+	closure_func = ffi_go_closure_VFP;
+    }
+  else if (cif->abi != FFI_SYSV)
+    return FFI_BAD_ABI;
+
+  closure->tramp = closure_func;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
 /* Below are routines for VFP hard-float support. */
 
 /* A subroutine of vfp_type_p.  Given a structure type, return the type code
diff --git a/src/arm/ffitarget.h b/src/arm/ffitarget.h
index 744a1e1..4f473f9 100644
--- a/src/arm/ffitarget.h
+++ b/src/arm/ffitarget.h
@@ -62,6 +62,7 @@ typedef enum ffi_abi {
 /* ---- Definitions for closures ----------------------------------------- */
 
 #define FFI_CLOSURES 1
+#define FFI_GO_CLOSURES 1
 #define FFI_TRAMPOLINE_SIZE 12
 #define FFI_NATIVE_RAW_API 0
 
diff --git a/src/arm/sysv.S b/src/arm/sysv.S
index ce5450d..fd16589 100644
--- a/src/arm/sysv.S
+++ b/src/arm/sysv.S
@@ -136,6 +136,7 @@ ARM_FUNC_START(ffi_call_SYSV, 1)
 
 	mov	sp, r0		@ install the stack pointer
 	mov	lr, r2		@ move the fn pointer out of the way
+	ldr	ip, [fp, #16]	@ install the static chain
 	ldmia	sp!, {r0-r3}	@ move first 4 parameters in registers.
 	blx	lr		@ call fn
 
@@ -180,22 +181,33 @@ ARM_FUNC_END(ffi_call_SYSV)
 
 
 /*
-	unsigned int FFI_HIDDEN
-	ffi_closure_inner (closure, respp, args)
-	     ffi_closure *closure;
-	     void **respp;
-  	     void *args;
+	int ffi_closure_inner_* (cif, fun, user_data, frame)
 */
 
+ARM_FUNC_START(ffi_go_closure_SYSV, 1)
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #4]			@ load cif
+	ldr	r1, [ip, #8]			@ load fun
+	mov	r2, ip				@ load user_data
+	b	0f
+	cfi_endproc
+ARM_FUNC_END(ffi_go_closure_SYSV)
+
 ARM_FUNC_START(ffi_closure_SYSV, 1)
 	UNWIND	.fnstart
 	cfi_startproc
 	stmdb	sp!, {r0-r3}			@ save argument regs
 	cfi_adjust_cfa_offset(16)
-	mov	r0, ip				@ load closure
+	ldr	r0, [ip, #FFI_TRAMPOLINE_SIZE]	  @ load cif
+	ldr	r1, [ip, #FFI_TRAMPOLINE_SIZE+4]  @ load fun
+	ldr	r2, [ip, #FFI_TRAMPOLINE_SIZE+8]  @ load user_data
+0:
 	add	ip, sp, #16			@ compute entry sp
-	sub	sp, sp, #32			@ allocate rvalue space
-	stmdb	sp!, {sp,lr}
+	sub	sp, sp, #64+32			@ allocate frame
+	cfi_adjust_cfa_offset(64+32)
+	stmdb	sp!, {ip,lr}
 
 	/* Remember that EABI unwind info only applies at call sites.
 	   We need do nothing except note the save of the stack pointer
@@ -204,46 +216,53 @@ ARM_FUNC_START(ffi_closure_SYSV, 1)
 	cfi_adjust_cfa_offset(8)
 	cfi_rel_offset(lr, 4)
 
-	add	r1, sp, #8			@ load respp
-	add	r2, sp, #8+32			@ load args
-	mov	r3, #0				@ load vfp_args
-
+	add	r3, sp, #8			@ load frame
 	bl	CNAME(ffi_closure_inner_SYSV)
 
 	@ Load values returned in registers.
-	add	r2, sp, #8			@ load respp
+	add	r2, sp, #8+64			@ load result
 	adr	r3, CNAME(ffi_closure_ret)
 	add	pc, r3, r0, lsl #3
 	cfi_endproc
 	UNWIND	.fnend
 ARM_FUNC_END(ffi_closure_SYSV)
 
+ARM_FUNC_START(ffi_go_closure_VFP, 1)
+	cfi_startproc
+	stmdb	sp!, {r0-r3}			@ save argument regs
+	cfi_adjust_cfa_offset(16)
+	ldr	r0, [ip, #4]			@ load cif
+	ldr	r1, [ip, #8]			@ load fun
+	mov	r2, ip				@ load user_data
+	b	0f
+	cfi_endproc
+ARM_FUNC_END(ffi_go_closure_VFP)
+
 ARM_FUNC_START(ffi_closure_VFP, 1)
 	UNWIND	.fnstart
 	cfi_startproc
 	stmdb	sp!, {r0-r3}			@ save argument regs
 	cfi_adjust_cfa_offset(16)
-	sub	sp, sp, #64+32			@ allocate vfp+rvalue space
+	ldr	r0, [ip, #FFI_TRAMPOLINE_SIZE]	  @ load cif
+	ldr	r1, [ip, #FFI_TRAMPOLINE_SIZE+4]  @ load fun
+	ldr	r2, [ip, #FFI_TRAMPOLINE_SIZE+8]  @ load user_data
+0:
+	add	ip, sp, #16
+	sub	sp, sp, #64+32			@ allocate frame
 	cfi_adjust_cfa_offset(64+32)
 	stc	p11, cr0, [sp], {16}		@ vstm sp, {d0-d7}
-	mov	r0, ip				@ load closure
-	add	ip, sp, #16+64+32		@ compute entry sp
 	stmdb	sp!, {ip,lr}
 
 	/* See above.  */
 	UNWIND	.save {sp,lr}
 	cfi_adjust_cfa_offset(8)
-	cfi_rel_offset(sp, 0)
 	cfi_rel_offset(lr, 4)
 
-	add	r1, sp, #8+64			@ load respp
-	add	r2, sp, #8+64+32		@ load args
-	add	r3, sp, #8			@ load vfp_args
-
+	add	r3, sp, #8			@ load frame
 	bl	CNAME(ffi_closure_inner_VFP)
 
 	@ Load values returned in registers.
-	add	r2, sp, #8+64			@ load respp
+	add	r2, sp, #8+64			@ load result
 	adr	r3, CNAME(ffi_closure_ret)
 	add	pc, r3, r0, lsl #3
 	cfi_endproc
-- 
1.9.3

  parent reply	other threads:[~2014-10-29 20:06 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-29 20:05 [PATCH 00/10] Go closures for arm Richard Henderson
2014-10-29 20:06 ` [PATCH 03/10] arm: Deref ffi_put_arg arguments Richard Henderson
2014-10-29 20:06 ` [PATCH 07/10] arm: Remove internal FFI_TYPE constants Richard Henderson
2014-10-29 20:06 ` [PATCH 04/10] arm: Rewrite vfp_type_p Richard Henderson
2014-10-29 20:06 ` [PATCH 05/10] arm: Rewrite ffi_call Richard Henderson
2014-10-29 20:06 ` Richard Henderson [this message]
2014-10-29 20:06 ` [PATCH 02/10] arm: Deref ffi_align argument Richard Henderson
2014-10-29 20:06 ` [PATCH 08/10] arm: Add support for complex types Richard Henderson
2014-10-29 20:06 ` [PATCH 01/10] arm: Reindent arm/ffi.c Richard Henderson
2014-10-29 20:06 ` [PATCH 09/10] arm: Add argument space for the hidden struct return pointer Richard Henderson
2014-10-29 20:06 ` [PATCH 06/10] arm: Rewrite ffi_closure 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=1414613147-10917-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).