diff mbox

Reinstate powerpc bounce buffer copying in ffi.c

Message ID 20131116115236.GK22514@bubble.grove.modra.org
State New
Headers show

Commit Message

Alan Modra Nov. 16, 2013, 11:52 a.m. UTC
The first patch in the series is a little different to the
corresponding upstream libffi patch, because there I needed to revert
some fixes first.  The second patch in the series is entirely missing
due to the testsuite already being fixed in gcc.

This patch properly copies the bounce buffer to destination, and only
uses the bounce buffer for FFI_SYSV.  I also fix an accounting error
in integer register usage.

	* src/powerpc/ffi.c (ffi_prep_cif_machdep): Do not consume an
	int arg when returning a small struct for FFI_SYSV ABI.
	(ffi_call): Only use bounce buffer when FLAG_RETURNS_SMST.
	Properly copy bounce buffer to destination.
diff mbox

Patch

diff -urp gcc-virgin/libffi/src/powerpc/ffi.c gcc1/libffi/src/powerpc/ffi.c
--- gcc-virgin/libffi/src/powerpc/ffi.c	2013-06-25 09:36:39.259402853 +0930
+++ gcc1/libffi/src/powerpc/ffi.c	2013-11-15 23:06:57.313036827 +1030
@@ -691,7 +691,7 @@ 
     case FFI_TYPE_STRUCT:
       /*
        * The final SYSV ABI says that structures smaller or equal 8 bytes
-       * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+       * are returned in r3/r4.  The FFI_GCC_SYSV ABI instead returns them
        * in memory.
        *
        * NOTE: The assembly code can safely assume that it just needs to
@@ -700,7 +700,10 @@ 
        *       set.
        */
       if (cif->abi == FFI_SYSV && size <= 8)
-	flags |= FLAG_RETURNS_SMST;
+	{
+	  flags |= FLAG_RETURNS_SMST;
+	  break;
+	}
       intarg_count++;
       flags |= FLAG_RETVAL_REFERENCE;
       /* Fall through.  */
@@ -919,30 +922,25 @@ 
 {
   /*
    * The final SYSV ABI says that structures smaller or equal 8 bytes
-   * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
+   * are returned in r3/r4.  The FFI_GCC_SYSV ABI instead returns them
    * in memory.
    *
-   * Just to keep things simple for the assembly code, we will always
-   * bounce-buffer struct return values less than or equal to 8 bytes.
-   * This allows the ASM to handle SYSV small structures by directly
-   * writing r3 and r4 to memory without worrying about struct size.
+   * We bounce-buffer SYSV small struct return values so that sysv.S
+   * can write r3 and r4 to memory without worrying about struct size.
    */
   unsigned int smst_buffer[2];
   extended_cif ecif;
-  unsigned int rsize = 0;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
 
-  /* Ensure that we have a valid struct return value */
   ecif.rvalue = rvalue;
-  if (cif->rtype->type == FFI_TYPE_STRUCT) {
-    rsize = cif->rtype->size;
-    if (rsize <= 8)
-      ecif.rvalue = smst_buffer;
-    else if (!rvalue)
-      ecif.rvalue = alloca(rsize);
-  }
+  if ((cif->flags & FLAG_RETURNS_SMST) != 0)
+    ecif.rvalue = smst_buffer;
+  /* Ensure that we have a valid struct return value.
+     FIXME: Isn't this just papering over a user problem?  */
+  else if (!rvalue && cif->rtype->type == FFI_TYPE_STRUCT)
+    ecif.rvalue = alloca (cif->rtype->size);
 
   switch (cif->abi)
     {
@@ -967,7 +965,21 @@ 
 
   /* Check for a bounce-buffered return value */
   if (rvalue && ecif.rvalue == smst_buffer)
-    memcpy(rvalue, smst_buffer, rsize);
+    {
+      unsigned int rsize = cif->rtype->size;
+#ifndef __LITTLE_ENDIAN__
+      /* The SYSV ABI returns a structure of up to 4 bytes in size
+	 left-padded in r3.  */
+      if (rsize <= 4)
+	memcpy (rvalue, (char *) smst_buffer + 4 - rsize, rsize);
+      /* The SYSV ABI returns a structure of up to 8 bytes in size
+	 left-padded in r3/r4.  */
+      else if (rsize <= 8)
+	memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize);
+      else
+#endif
+	memcpy (rvalue, smst_buffer, rsize);
+    }
 }