This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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 {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]