Revamp PA_LINUX and PA_HPUX target closures to use function descriptors.
authorMoxie Bot <bot@moxielogic.com>
Mon, 24 Feb 2020 15:29:20 +0000 (10:29 -0500)
committerMoxie Bot <bot@moxielogic.com>
Mon, 24 Feb 2020 15:29:20 +0000 (10:29 -0500)
2020-02-23  John David Anglin  <danglin@gcc.gnu.org>

* include/ffi.h.in (FFI_CLOSURE_PTR, FFI_RESTORE_PTR): Define.
* src/closures.c (ffi_closure_alloc): Convert closure pointer
return by malloc to function pointer.
(ffi_closure_free): Convert function pointer back to malloc pointer.
* src/pa/ffi.c (ffi_closure_inner_pa32): Use union to double word
align return address on stack.  Adjust statements referencing return
address.  Convert closure argument from function pointer to standard
closure pointer.
(ffi_prep_closure_loc): Likewise convert closure argument back to
closure pointer.  Remove assembler trampolines.  Setup simulated
function descriptor as on ia64.
src/pa/ffitarget.h (FFI_TRAMPOLINE_SIZE): Reduce to 12.
src/pa/hpux32.S (ffi_closure_pa32): Retrieve closure pointer and real
gp from fake gp value in register %r19.
src/pa/linux.S (ffi_closure_pa32): Likewise.

include/ffi.h.in
src/closures.c
src/pa/ffi.c
src/pa/ffitarget.h
src/pa/hpux32.S
src/pa/linux.S

index 71cc05c9d8a9ca52ef52535878e3e608a3a4d0c2..38885b0ab857f0904c81048c032a72067b272405 100644 (file)
@@ -330,6 +330,14 @@ typedef struct {
 FFI_API void *ffi_closure_alloc (size_t size, void **code);
 FFI_API void ffi_closure_free (void *);
 
+#if defined(PA_LINUX) || defined(PA_HPUX)
+#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2))
+#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3))
+#else
+#define FFI_CLOSURE_PTR(X) (X)
+#define FFI_RESTORE_PTR(X) (X)
+#endif
+
 FFI_API ffi_status
 ffi_prep_closure (ffi_closure*,
                  ffi_cif *,
index 512002165254dcd08d5e8b097c54056547b52752..047abcd6b2ed95e00ea918cbcf91dcaac555be59 100644 (file)
@@ -921,7 +921,7 @@ ffi_closure_alloc (size_t size, void **code)
   if (!code)
     return NULL;
 
-  ptr = dlmalloc (size);
+  ptr = FFI_CLOSURE_PTR (dlmalloc (size));
 
   if (ptr)
     {
@@ -961,7 +961,7 @@ ffi_closure_free (void *ptr)
     ptr = sub_segment_exec_offset (ptr, seg);
 #endif
 
-  dlfree (ptr);
+  dlfree (FFI_RESTORE_PTR (ptr));
 }
 
 # else /* ! FFI_MMAP_EXEC_WRIT */
@@ -977,13 +977,13 @@ ffi_closure_alloc (size_t size, void **code)
   if (!code)
     return NULL;
 
-  return *code = malloc (size);
+  return *code = FFI_CLOSURE_PTR (malloc (size));
 }
 
 void
 ffi_closure_free (void *ptr)
 {
-  free (ptr);
+  free (FFI_RESTORE_PTR (ptr));
 }
 
 void *
index 4ce2bc6f0e4c46336acffbc05fb754c93ffbf881..95e669473e1ecda58a1d5f50e05b7b132b414b5c 100644 (file)
@@ -421,12 +421,15 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
   ffi_cif *cif;
   void **avalue;
   void *rvalue;
-  UINT32 ret[2]; /* function can return up to 64-bits in registers */
+  /* Functions can return up to 64-bits in registers.  Return address
+     must be double word aligned.  */
+  union { double rd; UINT32 ret[2]; } u;
   ffi_type **p_arg;
   char *tmp;
   int i, avn;
   unsigned int slot = FIRST_ARG_SLOT;
   register UINT32 r28 asm("r28");
+  ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
 
   cif = closure->cif;
 
@@ -434,7 +437,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
   if (cif->flags == FFI_TYPE_STRUCT)
     rvalue = (void *)r28;
   else
-    rvalue = &ret[0];
+    rvalue = &u;
 
   avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
   avn = cif->nargs;
@@ -529,35 +532,35 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
     }
 
   /* Invoke the closure.  */
-  (closure->fun) (cif, rvalue, avalue, closure->user_data);
+  (c->fun) (cif, rvalue, avalue, c->user_data);
 
-  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
-       ret[1]);
+  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0],
+       u.ret[1]);
 
   /* Store the result using the lower 2 bytes of the flags.  */
   switch (cif->flags)
     {
     case FFI_TYPE_UINT8:
-      *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
+      *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24);
       break;
     case FFI_TYPE_SINT8:
-      *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
+      *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24);
       break;
     case FFI_TYPE_UINT16:
-      *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
+      *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16);
       break;
     case FFI_TYPE_SINT16:
-      *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
+      *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16);
       break;
     case FFI_TYPE_INT:
     case FFI_TYPE_SINT32:
     case FFI_TYPE_UINT32:
-      *(stack - FIRST_ARG_SLOT) = ret[0];
+      *(stack - FIRST_ARG_SLOT) = u.ret[0];
       break;
     case FFI_TYPE_SINT64:
     case FFI_TYPE_UINT64:
-      *(stack - FIRST_ARG_SLOT) = ret[0];
-      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
+      *(stack - FIRST_ARG_SLOT) = u.ret[0];
+      *(stack - FIRST_ARG_SLOT - 1) = u.ret[1];
       break;
 
     case FFI_TYPE_DOUBLE:
@@ -577,7 +580,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
     case FFI_TYPE_SMALL_STRUCT4:
       tmp = (void*)(stack -  FIRST_ARG_SLOT);
       tmp += 4 - cif->rtype->size;
-      memcpy((void*)tmp, &ret[0], cif->rtype->size);
+      memcpy((void*)tmp, &u, cif->rtype->size);
       break;
 
     case FFI_TYPE_SMALL_STRUCT5:
@@ -598,7 +601,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
          }
 
        memset (ret2, 0, sizeof (ret2));
-       memcpy ((char *)ret2 + off, ret, 8 - off);
+       memcpy ((char *)ret2 + off, &u, 8 - off);
 
        *(stack - FIRST_ARG_SLOT) = ret2[0];
        *(stack - FIRST_ARG_SLOT - 1) = ret2[1];
@@ -630,89 +633,41 @@ ffi_prep_closure_loc (ffi_closure* closure,
                      void *user_data,
                      void *codeloc)
 {
-  UINT32 *tramp = (UINT32 *)(closure->tramp);
-#ifdef PA_HPUX
-  UINT32 *tmp;
-#endif
+  ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure);
+
+  /* The layout of a function descriptor.  A function pointer with the PLABEL
+     bit set points to a function descriptor.  */
+  struct pa32_fd
+  {
+    UINT32 code_pointer;
+    UINT32 gp;
+  };
+
+  struct ffi_pa32_trampoline_struct
+  {
+     UINT32 code_pointer;        /* Pointer to ffi_closure_unix.  */
+     UINT32 fake_gp;             /* Pointer to closure, installed as gp.  */
+     UINT32 real_gp;             /* Real gp value.  */
+  };
+
+  struct ffi_pa32_trampoline_struct *tramp;
+  struct pa32_fd *fd;
 
   if (cif->abi != FFI_PA32)
     return FFI_BAD_ABI;
 
-  /* Make a small trampoline that will branch to our
-     handler function. Use PC-relative addressing.  */
-
-#ifdef PA_LINUX
-  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8 */
-  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits */
-  tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1    ; load plabel */
-  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr */
-  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler */
-  tramp[5] = 0xeac0c000; /* bv%r0(%r22)         ; branch to handler */
-  tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler */
-  tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
-
-  /* Flush d/icache -- have to flush up 2 two lines because of
-     alignment.  */
-  __asm__ volatile(
-                  "fdc 0(%0)\n\t"
-                  "fdc %1(%0)\n\t"
-                  "fic 0(%%sr4, %0)\n\t"
-                  "fic %1(%%sr4, %0)\n\t"
-                  "sync\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n"
-                  :
-                  : "r"((unsigned long)tramp & ~31),
-                    "r"(32 /* stride */)
-                  : "memory");
-#endif
+  /* Get function descriptor address for ffi_closure_pa32.  */
+  fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3);
 
-#ifdef PA_HPUX
-  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8  */
-  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits  */
-  tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1    ; load plabel  */
-  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr  */
-  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler  */
-  tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20   ; load space id  */
-  tramp[6] = 0x00141820; /* mtsp %r20,%sr0      ; into %sr0  */
-  tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22)     ; branch to handler  */
-  tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler  */
-  tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
-
-  /* Flush d/icache -- have to flush three lines because of alignment.  */
-  __asm__ volatile(
-                  "copy %1,%0\n\t"
-                  "fdc,m %2(%0)\n\t"
-                  "fdc,m %2(%0)\n\t"
-                  "fdc,m %2(%0)\n\t"
-                  "ldsid (%1),%0\n\t"
-                  "mtsp %0,%%sr0\n\t"
-                  "copy %1,%0\n\t"
-                  "fic,m %2(%%sr0,%0)\n\t"
-                  "fic,m %2(%%sr0,%0)\n\t"
-                  "fic,m %2(%%sr0,%0)\n\t"
-                  "sync\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n\t"
-                  "nop\n"
-                  : "=&r" ((unsigned long)tmp)
-                  : "r" ((unsigned long)tramp & ~31),
-                    "r" (32/* stride */)
-                  : "memory");
-#endif
+  /* Setup trampoline.  */
+  tramp = (struct ffi_pa32_trampoline_struct *)c->tramp;
+  tramp->code_pointer = fd->code_pointer;
+  tramp->fake_gp = (UINT32)codeloc & ~3;
+  tramp->real_gp = fd->gp;
 
-  closure->cif  = cif;
-  closure->user_data = user_data;
-  closure->fun  = fun;
+  c->cif  = cif;
+  c->user_data = user_data;
+  c->fun  = fun;
 
   return FFI_OK;
 }
index fff4c6b382e54cf1d0001883db258e849a4e5440..df1209eb16700e0284d114ed134bca2fa0afdecd 100644 (file)
@@ -68,12 +68,7 @@ typedef enum ffi_abi {
 
 #define FFI_CLOSURES 1
 #define FFI_NATIVE_RAW_API 0
-
-#ifdef PA_LINUX
-#define FFI_TRAMPOLINE_SIZE 32
-#else
-#define FFI_TRAMPOLINE_SIZE 40
-#endif
+#define FFI_TRAMPOLINE_SIZE 12
 
 #define FFI_TYPE_SMALL_STRUCT2 -1
 #define FFI_TYPE_SMALL_STRUCT3 -2
index 40528bad7511cec19bf8c6dad08ce12561eb6720..d0e5f695297bb837f3a360e5af27b0c4010da508 100644 (file)
@@ -259,7 +259,7 @@ L$done
 L$FE1
 
        /* void ffi_closure_pa32(void);
-          Called with closure argument in %r21 */
+          Called with closure argument in %r19 */
 
        .SPACE $TEXT$
        .SUBSPA $CODE$
@@ -285,7 +285,9 @@ L$CFI22
        stw     %arg2, -44(%r3)
        stw     %arg3, -48(%r3)
 
-       copy    %r21, %arg0
+       /* Retrieve closure pointer and real gp.  */
+       copy    %r19, %arg0
+       ldw     8(%r19), %r19
        bl      ffi_closure_inner_pa32, %r2
        copy    %r3, %arg1
        ldwm    -64(%sp), %r3
index ab04c75f4371dd661d3c4376e73293462ba2f5cd..33ef0b137a4118bcfce9bc1e4b1dc4335cb4f027 100644 (file)
@@ -252,7 +252,7 @@ ffi_call_pa32:
 .LFE1:
 
        /* void ffi_closure_pa32(void);
-          Called with closure argument in %r21 */
+          Called with closure argument in %r19 */
        .export ffi_closure_pa32,code
        .import ffi_closure_inner_pa32,code
 
@@ -277,7 +277,9 @@ ffi_closure_pa32:
        stw %arg2, -44(%r3)
        stw %arg3, -48(%r3)
 
-       copy %r21, %arg0
+       /* Retrieve closure pointer and real gp.  */
+       copy    %r19, %arg0
+       ldw     8(%r19), %r19
        bl ffi_closure_inner_pa32, %r2
        copy %r3, %arg1