libffi-03-sparcv8-struct-return.diff revision 20148
20148N/A--- libffi/src/sparc/ffi.c
20148N/A+++ libffi/src/sparc/ffi.c
20148N/A@@ -401,18 +401,56 @@ void ffi_call(ffi_cif *cif, void (*fn)(v
20148N/A
20148N/A switch (cif->abi)
20148N/A {
20148N/A case FFI_V8:
20148N/A #ifdef SPARC64
20148N/A /* We don't yet support calling 32bit code from 64bit */
20148N/A FFI_ASSERT(0);
20148N/A #else
20148N/A- ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
20148N/A- cif->flags, rvalue, fn);
20148N/A+ if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
20148N/A+#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
20148N/A+ || cif->flags == FFI_TYPE_LONGDOUBLE
20148N/A+#endif
20148N/A+ ))
20148N/A+ {
20148N/A+ /* For v8, we need an "unimp" with size of returning struct */
20148N/A+ /* behind "call", so we alloc some executable space for it. */
20148N/A+ /* l7 is used, we need to make sure v8.S doesn't use %l7. */
20148N/A+ unsigned int *call_struct = NULL;
20148N/A+ ffi_closure_alloc(32, &call_struct);
20148N/A+ if (call_struct)
20148N/A+ {
20148N/A+ unsigned long f = (unsigned long)fn;
20148N/A+ call_struct[0] = 0xae10001f; /* mov %i7, %l7 */
20148N/A+ call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */
20148N/A+ call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */
20148N/A+ call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
20148N/A+ call_struct[4] = 0x01000000; /* nop */
20148N/A+ if (cif->rtype->size < 0x7f)
20148N/A+ call_struct[5] = cif->rtype->size; /* unimp */
20148N/A+ else
20148N/A+ call_struct[5] = 0x01000000; /* nop */
20148N/A+ call_struct[6] = 0x81c7e008; /* ret */
20148N/A+ call_struct[7] = 0xbe100017; /* mov %l7, %i7 */
20148N/A+ ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
20148N/A+ cif->flags, rvalue, call_struct);
20148N/A+ ffi_closure_free(call_struct);
20148N/A+ }
20148N/A+ else
20148N/A+ {
20148N/A+ ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
20148N/A+ cif->flags, rvalue, fn);
20148N/A+ }
20148N/A+ }
20148N/A+ else
20148N/A+ {
20148N/A+ ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
20148N/A+ cif->flags, rvalue, fn);
20148N/A+ }
20148N/A #endif
20148N/A break;
20148N/A case FFI_V9:
20148N/A #ifdef SPARC64
20148N/A ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes,
20148N/A cif->flags, rval, fn);
20148N/A if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT)
20148N/A ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32);