This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java 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]

libffi fixes for ARM EABI


I found quite a few bugs in libffi: fixed thusly.  Now, everything
passes except the unwind tests, which I am working on.

Andrew.


2007-08-10  Andrew Haley  <aph@redhat.com>

        * src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes.
        Only treat r0 as a struct address if we're actually returning a
        struct by address.
        Only copy the bytes that are actually within a struct.
        (ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes
        is returned in r0, not passed by address.
        (ffi_call): Allocate a word-sized temporary for the case where
        a composite is returned in r0.
        (ffi_prep_incoming_args_SYSV): Align as necessary.

Index: ffi.c
===================================================================
--- ffi.c	(revision 127334)
+++ ffi.c	(working copy)
@@ -40,7 +40,7 @@
 
   argp = stack;
 
-  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) {
+  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
     *(void **) argp = ecif->rvalue;
     argp += 4;
   }
@@ -58,6 +58,9 @@
 	argp = (char *) ALIGN(argp, (*p_arg)->alignment);
       }
 
+      if ((*p_arg)->type == FFI_TYPE_STRUCT)
+	argp = (char *) ALIGN(argp, 4);
+
 	  z = (*p_arg)->size;
 	  if (z < sizeof(int))
 	    {
@@ -81,7 +84,7 @@
 		  break;
 		  
 		case FFI_TYPE_STRUCT:
-		  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
+		  memcpy(argp, *p_argv, (*p_arg)->size);
 		  break;
 
 		default:
@@ -115,7 +118,6 @@
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-    case FFI_TYPE_STRUCT:
     case FFI_TYPE_FLOAT:
     case FFI_TYPE_DOUBLE:
       cif->flags = (unsigned) cif->rtype->type;
@@ -126,6 +128,17 @@
       cif->flags = (unsigned) FFI_TYPE_SINT64;
       break;
 
+    case FFI_TYPE_STRUCT:
+      if (cif->rtype->size <= 4)
+	/* A Composite Type not larger than 4 bytes is returned in r0.  */
+	cif->flags = (unsigned)FFI_TYPE_INT;
+      else
+	/* A Composite Type larger than 4 bytes, or whose size cannot
+	   be determined statically ... is stored in memory at an
+	   address passed [in r0].  */
+	cif->flags = (unsigned)FFI_TYPE_STRUCT;
+      break;
+
     default:
       cif->flags = FFI_TYPE_INT;
       break;
@@ -141,21 +154,27 @@
 {
   extended_cif ecif;
 
+  int small_struct = (cif->flags == FFI_TYPE_INT 
+		      && cif->rtype->type == FFI_TYPE_STRUCT);
+
   ecif.cif = cif;
   ecif.avalue = avalue;
+
+  unsigned int temp;
   
   /* If the return value is a struct and we don't have a return	*/
   /* value address then we need to make one		        */
 
   if ((rvalue == NULL) && 
-      (cif->rtype->type == FFI_TYPE_STRUCT))
+      (cif->flags == FFI_TYPE_STRUCT))
     {
       ecif.rvalue = alloca(cif->rtype->size);
     }
+  else if (small_struct)
+    ecif.rvalue = &temp;
   else
     ecif.rvalue = rvalue;
-    
-  
+
   switch (cif->abi) 
     {
     case FFI_SYSV:
@@ -167,6 +186,8 @@
       FFI_ASSERT(0);
       break;
     }
+  if (small_struct)
+    memcpy (rvalue, &temp, cif->rtype->size);
 }
 
 /** private members **/
@@ -228,9 +249,12 @@
     {
       size_t z;
 
+      size_t alignment = (*p_arg)->alignment;
+      if (alignment < 4)
+	alignment = 4;
       /* Align if necessary */
-      if ((sizeof(int) - 1) & (unsigned) argp) {
-	argp = (char *) ALIGN(argp, sizeof(int));
+      if ((alignment - 1) & (unsigned) argp) {
+	argp = (char *) ALIGN(argp, alignment);
       }
 
       z = (*p_arg)->size;


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