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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
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