backport: ffi.c (ffi_call_go, [...]): New functions.
authorAndreas Schwab <schwab@suse.de>
Wed, 15 Aug 2018 06:57:45 +0000 (06:57 +0000)
committerAndreas Schwab <schwab@gcc.gnu.org>
Wed, 15 Aug 2018 06:57:45 +0000 (06:57 +0000)
Backport of RISC-V support for libffi go closures
* src/riscv/ffi.c (ffi_call_go, ffi_prep_go_closure): New
functions.
(ffi_call_int): Renamed from ffi_call.
(ffi_call_asm, ffi_closure_inner): Adjust interface.
* src/riscv/ffitarget.h (FFI_GO_CLOSURES): Define.
* src/riscv/sysv.S (ffi_go_closure_asm): New function.
(ffi_closure_asm, ffi_call_asm): Update for adjusted interfaces.

From-SVN: r263550

libffi/ChangeLog
libffi/src/riscv/ffi.c
libffi/src/riscv/ffitarget.h
libffi/src/riscv/sysv.S

index f81c30c2bcff5aa60ac977dacefe159199a9d09f..d63d1cee47c28b2f75ca4d6ae5eca1349a616fc3 100644 (file)
@@ -1,3 +1,14 @@
+2018-08-15  Andreas Schwab  <schwab@suse.de>
+
+       Backport of RISC-V support for libffi go closures
+       * src/riscv/ffi.c (ffi_call_go, ffi_prep_go_closure): New
+       functions.
+       (ffi_call_int): Renamed from ffi_call.
+       (ffi_call_asm, ffi_closure_inner): Adjust interface.
+       * src/riscv/ffitarget.h (FFI_GO_CLOSURES): Define.
+       * src/riscv/sysv.S (ffi_go_closure_asm): New function.
+       (ffi_closure_asm, ffi_call_asm): Update for adjusted interfaces.
+
 2018-05-08  Andreas Schwab  <schwab@suse.de>
 
        Backport of RISC-V support for libffi
index b664ee7d4ed286539cfa484b80d720356911b753..8c5a86050607194b5a29bc237d77cd488547efec 100644 (file)
@@ -324,9 +324,12 @@ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsig
 }
 
 /* Low level routine for calling functions */
-extern void ffi_call_asm(void *stack, struct call_context *regs, void (*fn)(void)) FFI_HIDDEN;
+extern void ffi_call_asm (void *stack, struct call_context *regs,
+                         void (*fn) (void), void *closure) 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)
 {
     /* this is a conservative estimate, assuming a complex return value and
        that all remaining arguments are long long / __int128 */
@@ -366,13 +369,26 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     for (i = 0; i < cif->nargs; i++)
         marshal(&cb, cif->arg_types[i], i >= cif->riscv_nfixedargs, avalue[i]);
 
-    ffi_call_asm((void*)alloc_base, cb.aregs, fn);
+    ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure);
 
     cb.used_float = cb.used_integer = 0;
     if (!return_by_ref && rvalue)
         unmarshal(&cb, cif->rtype, 0, rvalue);
 }
 
+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);
+}
+
 extern void ffi_closure_asm(void) FFI_HIDDEN;
 
 ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc)
@@ -406,11 +422,31 @@ ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(
     return FFI_OK;
 }
 
+extern void ffi_go_closure_asm (void) FFI_HIDDEN;
+
+ffi_status
+ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
+                    void (*fun) (ffi_cif *, void *, void **, void *))
+{
+  if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
+    return FFI_BAD_ABI;
+
+  closure->tramp = (void *) ffi_go_closure_asm;
+  closure->cif = cif;
+  closure->fun = fun;
+
+  return FFI_OK;
+}
+
 /* Called by the assembly code with aregs pointing to saved argument registers
    and stack pointing to the stacked arguments.  Return values passed in
    registers will be reloaded from aregs. */
-void FFI_HIDDEN ffi_closure_inner(size_t *stack, call_context *aregs, ffi_closure *closure) {
-    ffi_cif *cif = closure->cif;
+void FFI_HIDDEN
+ffi_closure_inner (ffi_cif *cif,
+                  void (*fun) (ffi_cif *, void *, void **, void *),
+                  void *user_data,
+                  size_t *stack, call_context *aregs)
+{
     void **avalue = alloca(cif->nargs * sizeof(void*));
     /* storage for arguments which will be copied by unmarshal().  We could
        theoretically avoid the copies in many cases and use at most 128 bytes
@@ -436,7 +472,7 @@ void FFI_HIDDEN ffi_closure_inner(size_t *stack, call_context *aregs, ffi_closur
         avalue[i] = unmarshal(&cb, cif->arg_types[i],
             i >= cif->riscv_nfixedargs, astorage + i*MAXCOPYARG);
 
-    (closure->fun)(cif, rvalue, avalue, closure->user_data);
+    fun (cif, rvalue, avalue, user_data);
 
     if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID) {
         cb.used_integer = cb.used_float = 0;
index fcaa8991533077cc4339289cff69b41c66929ec0..75e6462f5bbccd18e399c98350f6281ea9b081a8 100644 (file)
@@ -59,6 +59,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
 #define FFI_EXTRA_CIF_FIELDS unsigned riscv_nfixedargs; unsigned riscv_unused;
index 2d098651d0da14ff81866fb5a1dd1247f518ad24..522d0b0055004b1f440be2baf979a54309313aaa 100644 (file)
@@ -67,8 +67,8 @@
       intreg pad[rv32 ? 2 : 0];
       intreg save_fp, save_ra;
   }
-  void ffi_call_asm(size_t *stackargs, struct call_context *regargs,
-      void (*fn)(void));
+  void ffi_call_asm (size_t *stackargs, struct call_context *regargs,
+                     void (*fn) (void), void *closure);
 */
 
 #define FRAME_LEN (8 * FLTS + 8 * PTRS + 16)
@@ -98,6 +98,7 @@ ffi_call_asm:
 
     # Load arguments
     mv      t1, a2
+    mv      t2, a3
 
 #if FLTS
     FLARG   fa0, -FRAME_LEN+0*FLTS(fp)
@@ -145,8 +146,10 @@ ffi_call_asm:
 
 /*
   ffi_closure_asm. Expects address of the passed-in ffi_closure in t1.
-  void ffi_closure_inner(size_t *stackargs, struct call_context *regargs,
-      ffi_closure *closure);
+  void ffi_closure_inner (ffi_cif *cif,
+                         void (*fun) (ffi_cif *, void *, void **, void *),
+                         void *user_data,
+                         size_t *stackargs, struct call_context *regargs)
 */
 
     .globl ffi_closure_asm
@@ -187,9 +190,11 @@ ffi_closure_asm:
     SARG    a7, 8*FLTS+7*PTRS(sp)
 
     /* enter C */
-    addi    a0, sp, FRAME_LEN
-    mv      a1, sp
-    mv      a2, t1
+    LARG    a0, FFI_TRAMPOLINE_SIZE+0*PTRS(t1)
+    LARG    a1, FFI_TRAMPOLINE_SIZE+1*PTRS(t1)
+    LARG    a2, FFI_TRAMPOLINE_SIZE+2*PTRS(t1)
+    addi    a3, sp, FRAME_LEN
+    mv      a4, sp
 
     call    ffi_closure_inner
 
@@ -212,3 +217,77 @@ ffi_closure_asm:
     ret
     .cfi_endproc
     .size ffi_closure_asm, .-ffi_closure_asm
+
+/*
+  ffi_go_closure_asm.  Expects address of the passed-in ffi_go_closure in t2.
+  void ffi_closure_inner (ffi_cif *cif,
+                         void (*fun) (ffi_cif *, void *, void **, void *),
+                         void *user_data,
+                         size_t *stackargs, struct call_context *regargs)
+*/
+
+    .globl ffi_go_closure_asm
+    .hidden ffi_go_closure_asm
+    .type ffi_go_closure_asm, @function
+ffi_go_closure_asm:
+    .cfi_startproc
+
+    addi    sp,  sp, -FRAME_LEN
+    .cfi_def_cfa_offset FRAME_LEN
+
+    /* make a frame */
+    SARG    fp, FRAME_LEN - 2*PTRS(sp)
+    .cfi_offset 8, -2*PTRS
+    SARG    ra, FRAME_LEN - 1*PTRS(sp)
+    .cfi_offset 1, -1*PTRS
+    addi    fp, sp, FRAME_LEN
+
+    /* save arguments */
+#if FLTS
+    FSARG   fa0, 0*FLTS(sp)
+    FSARG   fa1, 1*FLTS(sp)
+    FSARG   fa2, 2*FLTS(sp)
+    FSARG   fa3, 3*FLTS(sp)
+    FSARG   fa4, 4*FLTS(sp)
+    FSARG   fa5, 5*FLTS(sp)
+    FSARG   fa6, 6*FLTS(sp)
+    FSARG   fa7, 7*FLTS(sp)
+#endif
+
+    SARG    a0, 8*FLTS+0*PTRS(sp)
+    SARG    a1, 8*FLTS+1*PTRS(sp)
+    SARG    a2, 8*FLTS+2*PTRS(sp)
+    SARG    a3, 8*FLTS+3*PTRS(sp)
+    SARG    a4, 8*FLTS+4*PTRS(sp)
+    SARG    a5, 8*FLTS+5*PTRS(sp)
+    SARG    a6, 8*FLTS+6*PTRS(sp)
+    SARG    a7, 8*FLTS+7*PTRS(sp)
+
+    /* enter C */
+    LARG    a0, 1*PTRS(t2)
+    LARG    a1, 2*PTRS(t2)
+    mv      a2, t2
+    addi    a3, sp, FRAME_LEN
+    mv      a4, sp
+
+    call    ffi_closure_inner
+
+    /* return values */
+#if FLTS
+    FLARG   fa0, 0*FLTS(sp)
+    FLARG   fa1, 1*FLTS(sp)
+#endif
+
+    LARG    a0, 8*FLTS+0*PTRS(sp)
+    LARG    a1, 8*FLTS+1*PTRS(sp)
+
+    /* restore and return */
+    LARG    ra, FRAME_LEN-1*PTRS(sp)
+    .cfi_restore 1
+    LARG    fp, FRAME_LEN-2*PTRS(sp)
+    .cfi_restore 8
+    addi    sp, sp, FRAME_LEN
+    .cfi_def_cfa_offset 0
+    ret
+    .cfi_endproc
+    .size ffi_go_closure_asm, .-ffi_go_closure_asm