This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch] libffi: Fixes for MIPS n32 ABI.
- From: David Daney <ddaney at avtrex dot com>
- To: Java Patches <java-patches at gcc dot gnu dot org>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 28 Nov 2007 23:09:35 -0800
- Subject: [Patch] libffi: Fixes for MIPS n32 ABI.
The initial patches for mips64/n32 ABI support passed the libffi
testsuite, however the java_raw_api support that is used by libjava
still contained several problems. This patch attempts to correct them.
With the patch applied we now have zero failures in the libjava
testsuite (down from around 30).
The problem was that libffi and libjava's interpreter use different
union definitions to describe stack elements. In the case of
mips64/n32, these unions had different sizes (8 vs. 4 bytes). This
caused most interpreter method calls to fail.
My patch adds a new macro FFI_SIZEOF_RAW that can be set by a libffi
target as well as allowing the target to define its own ffi_raw union.
If the target does not override these the FFI_SIZEOF_RAW is set to
FFI_SIZEOF_ARG, and the default definition of the ffi_raw union is
used. The code in java_raw_api, was changed to use FFI_SIZEOF_RAW in
most places it was using FFI_SIZEOF_ARG. In addition special handling
was added for pointer return values where FFI_SIZEOF_RAW != FFI_SIZEOF_ARG.
There were several places where the alignment of the raw pointer was
adjusted all using different but equivalent size calculations. I change
thse so that they all use sizeof(ffi_raw) as that seemed more correct.
Tested on mips64-linux-gnu/n32 and x86_64-pc-linux-gnu{m64,m32} with no
regressions. I will also test it on mipsel-linux.
OK to commit?
2007-11-28 David Daney <ddaney@avtrex.com>
* include/ffi.h.in (FFI_SIZEOF_RAW): Define ifndef.
(ffi_raw): Make declaration conditional on FFI_RAW_DEFINED. Make
length of data element FFI_SIZEOF_RAW.
* src/java_raw_api.c (ffi_java_raw_size): Replace FFI_SIZEOF_ARG
with FFI_SIZEOF_RAW.
(ffi_java_raw_to_ptrarray): ReplaceFFI_SIZEOF_ARG with
FFI_SIZEOF_RAW. Use sizeof(ffi_raw) for alignment calculations.
(ffi_java_ptrarray_to_raw): Same.
(ffi_java_rvalue_to_raw): Add special handling for FFI_TYPE_POINTER
if FFI_SIZEOF_RAW == 4.
(ffi_java_raw_to_rvalue): Same.
* src/mips/ffitarget.h (FFI_SIZEOF_RAW): Define for N32 and N64 ABIs.
(ffi_raw_arg, ffi_raw_sarg, ffi_raw) Declare for N32 ABI.
(FFI_RAW_DEFINED): Define for N32 ABI.
Index: include/ffi.h.in
===================================================================
--- include/ffi.h.in (revision 130154)
+++ include/ffi.h.in (working copy)
@@ -193,13 +193,19 @@ typedef struct {
# endif
#endif
+#ifndef FFI_SIZEOF_RAW
+# define FFI_SIZEOF_RAW FFI_SIZEOF_ARG
+#endif
+
+#ifndef FFI_RAW_DEFINED
typedef union {
ffi_sarg sint;
ffi_arg uint;
float flt;
- char data[FFI_SIZEOF_ARG];
+ char data[FFI_SIZEOF_RAW];
void* ptr;
} ffi_raw;
+#endif
void ffi_raw_call (ffi_cif *cif,
void (*fn)(),
Index: src/java_raw_api.c
===================================================================
--- src/java_raw_api.c (revision 130154)
+++ src/java_raw_api.c (working copy)
@@ -54,13 +54,13 @@ ffi_java_raw_size (ffi_cif *cif)
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
- result += 2 * FFI_SIZEOF_ARG;
+ result += 2 * FFI_SIZEOF_RAW;
break;
case FFI_TYPE_STRUCT:
/* No structure parameters in Java. */
abort();
default:
- result += FFI_SIZEOF_ARG;
+ result += FFI_SIZEOF_RAW;
}
}
@@ -90,7 +90,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif,
*args = (void*) ((char*)(raw++) + 2);
break;
-#if FFI_SIZEOF_ARG == 8
+#if FFI_SIZEOF_RAW == 8
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
@@ -105,7 +105,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif,
default:
*args = raw;
- raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+ raw += ALIGN ((*tp)->size, sizeof(ffi_raw)) / sizeof(ffi_raw);
}
}
@@ -116,7 +116,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif,
/* then assume little endian */
for (i = 0; i < cif->nargs; i++, tp++, args++)
{
-#if FFI_SIZEOF_ARG == 8
+#if FFI_SIZEOF_RAW == 8
switch((*tp)->type) {
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
@@ -127,10 +127,10 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif,
default:
*args = (void*) raw++;
}
-#else /* FFI_SIZEOF_ARG != 8 */
+#else /* FFI_SIZEOF_RAW != 8 */
*args = (void*) raw;
- raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*);
-#endif /* FFI_SIZEOF_ARG == 8 */
+ raw += ALIGN ((*tp)->size, sizeof(ffi_raw)) / sizeof(ffi_raw);
+#endif /* FFI_SIZEOF_RAW == 8 */
}
#else
@@ -202,7 +202,7 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif,
(raw++)->flt = *(FLOAT32*) (*args);
break;
-#if FFI_SIZEOF_ARG == 8
+#if FFI_SIZEOF_RAW == 8
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_DOUBLE:
@@ -216,11 +216,11 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif,
break;
default:
-#if FFI_SIZEOF_ARG == 8
+#if FFI_SIZEOF_RAW == 8
FFI_ASSERT(0); /* Should have covered all cases */
#else
memcpy ((void*) raw->data, (void*)*args, (*tp)->size);
- raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
+ raw += ALIGN ((*tp)->size, sizeof(ffi_raw)) / sizeof(ffi_raw);
#endif
}
}
@@ -244,6 +244,9 @@ ffi_java_rvalue_to_raw (ffi_cif *cif, vo
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_INT:
+#if FFI_SIZEOF_RAW == 4
+ case FFI_TYPE_POINTER:
+#endif
*(SINT64 *)rvalue <<= 32;
break;
@@ -269,6 +272,9 @@ ffi_java_raw_to_rvalue (ffi_cif *cif, vo
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
case FFI_TYPE_INT:
+#if FFI_SIZEOF_RAW == 4
+ case FFI_TYPE_POINTER:
+#endif
*(SINT64 *)rvalue >>= 32;
break;
Index: src/mips/ffitarget.h
===================================================================
--- src/mips/ffitarget.h (revision 130154)
+++ src/mips/ffitarget.h (working copy)
@@ -42,10 +42,15 @@
#ifdef FFI_MIPS_O32
/* O32 stack frames have 32bit integer args */
-#define FFI_SIZEOF_ARG 4
+# define FFI_SIZEOF_ARG 4
#else
/* N32 and N64 frames have 64bit integer args */
-#define FFI_SIZEOF_ARG 8
+# define FFI_SIZEOF_ARG 8
+# ifdef FFI_MIPS_N32
+# define FFI_SIZEOF_RAW 4
+# else /* N64 */
+# define FFI_SIZEOF_RAW FFI_SIZEOF_ARG
+# endif
#endif
#define FFI_FLAG_BITS 2
@@ -136,6 +141,20 @@ typedef signed int ffi_sarg __attr
/* N32 and N64 frames have 64bit integer args */
typedef unsigned int ffi_arg __attribute__((__mode__(__DI__)));
typedef signed int ffi_sarg __attribute__((__mode__(__DI__)));
+
+# ifdef FFI_MIPS_N32
+typedef unsigned int ffi_raw_arg __attribute__((__mode__(__SI__)));
+typedef signed int ffi_raw_sarg __attribute__((__mode__(__SI__)));
+# define FFI_RAW_DEFINED
+typedef union {
+ ffi_raw_sarg sint;
+ ffi_raw_arg uint;
+ float flt;
+ char data[FFI_SIZEOF_RAW];
+ void* ptr;
+} ffi_raw;
+# endif /* FFI_MIPS_N32 */
+
#endif
typedef enum ffi_abi {