Commit 8eb2d2b05626b1cbbed100725bc440709499e8a6

Moxie Bot 2020-02-24T10:29:20

Revamp PA_LINUX and PA_HPUX target closures to use function descriptors. 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.

diff --git a/include/ffi.h.in b/include/ffi.h.in
index 71cc05c..38885b0 100644
--- a/include/ffi.h.in
+++ b/include/ffi.h.in
@@ -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 *,
diff --git a/src/closures.c b/src/closures.c
index 5120021..047abcd 100644
--- a/src/closures.c
+++ b/src/closures.c
@@ -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 *
diff --git a/src/pa/ffi.c b/src/pa/ffi.c
index 4ce2bc6..95e6694 100644
--- a/src/pa/ffi.c
+++ b/src/pa/ffi.c
@@ -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;
 }
diff --git a/src/pa/ffitarget.h b/src/pa/ffitarget.h
index fff4c6b..df1209e 100644
--- a/src/pa/ffitarget.h
+++ b/src/pa/ffitarget.h
@@ -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
diff --git a/src/pa/hpux32.S b/src/pa/hpux32.S
index 40528ba..d0e5f69 100644
--- a/src/pa/hpux32.S
+++ b/src/pa/hpux32.S
@@ -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
diff --git a/src/pa/linux.S b/src/pa/linux.S
index ab04c75..33ef0b1 100644
--- a/src/pa/linux.S
+++ b/src/pa/linux.S
@@ -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