]> granicus.if.org Git - python/commitdiff
Sync the darwin/x86 port libffi with the copy in PyObjC. This fixes a number
authorRonald Oussoren <ronaldoussoren@mac.com>
Tue, 4 Jul 2006 12:30:22 +0000 (12:30 +0000)
committerRonald Oussoren <ronaldoussoren@mac.com>
Tue, 4 Jul 2006 12:30:22 +0000 (12:30 +0000)
of bugs in that port. The most annoying ones were due to some subtle differences
between the document ABI and the actual implementation :-(

(there are no python unittests that fail without this patch, but without it
 some of libffi's unittests fail).

Modules/_ctypes/libffi/src/x86/darwin.S
Modules/_ctypes/libffi/src/x86/ffi_darwin.c

index c5e55b5400f3e0d8ef6467260171bd7766a023c6..d91bdc084e303a9c4ffa1ccb8cf206221c03bb56 100644 (file)
 #include <fficonfig.h>
 #include <ffi.h>
 
+#ifdef PyObjC_STRICT_DEBUGGING
+  /* XXX: Debugging of stack alignment, to be removed */
+#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0
+#else
+#define ASSERT_STACK_ALIGNED 
+#endif
+
 .text
 
 .globl _ffi_prep_args
@@ -47,30 +54,41 @@ _ffi_call_SYSV:
         pushl %ebp
 .LCFI0:
         movl  %esp,%ebp
+       subl  $8,%esp
+       ASSERT_STACK_ALIGNED
 .LCFI1:
        /* Make room for all of the new args.  */
        movl  16(%ebp),%ecx
        subl  %ecx,%esp
 
+       ASSERT_STACK_ALIGNED
+
        movl  %esp,%eax
 
        /* Place all of the ffi_prep_args in position  */
+       subl  $8,%esp
        pushl 12(%ebp)
        pushl %eax
        call  *8(%ebp)
 
+       ASSERT_STACK_ALIGNED
+
        /* Return stack to previous state and call the function  */
-       addl  $8,%esp   
+       addl  $16,%esp
 
-       call  *28(%ebp)
+       ASSERT_STACK_ALIGNED
 
-       /* Remove the space we pushed for the args  */
+       call  *28(%ebp)
+       
+       /* XXX: return returns return with 'ret $4', that upsets the stack! */
        movl  16(%ebp),%ecx
        addl  %ecx,%esp
 
+
        /* Load %ecx with the return type code  */
        movl  20(%ebp),%ecx     
 
+
        /* If the return value pointer is NULL, assume no return value.  */
        cmpl  $0,24(%ebp)
        jne   retint
@@ -117,17 +135,47 @@ retlongdouble:
        
 retint64:      
        cmpl  $FFI_TYPE_SINT64,%ecx
-        jne   retstruct
+        jne   retstruct1b
        /* Load %ecx with the pointer to storage for the return value  */
        movl  24(%ebp),%ecx     
        movl  %eax,0(%ecx)
        movl  %edx,4(%ecx)
+       jmp   epilogue
+
+retstruct1b:
+   cmpl $FFI_TYPE_SINT8,%ecx
+   jne  retstruct2b
+   movl 24(%ebp),%ecx
+   movb  %al,0(%ecx)
+   jmp  epilogue
+
+retstruct2b:
+   cmpl $FFI_TYPE_SINT16,%ecx
+   jne  retstruct
+   movl 24(%ebp),%ecx
+   movw %ax,0(%ecx)
+   jmp  epilogue
        
 retstruct:
+   cmpl $FFI_TYPE_STRUCT,%ecx
+   jne  noretval
        /* Nothing to do!  */
 
+       subl $4,%esp
+
+       ASSERT_STACK_ALIGNED
+
+       addl $8,%esp
+       movl %ebp, %esp
+       popl %ebp
+       ret
+
 noretval:
 epilogue:
+       ASSERT_STACK_ALIGNED
+       addl $8, %esp
+
+
         movl %ebp,%esp
         popl %ebp
         ret
index 4f82b3a10ced1394c6a0e8ae4ce3d2425a27642f..c9742d876c72f85bd1eb9cb6219bec1051f9a22a 100644 (file)
@@ -140,7 +140,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
   switch (cif->rtype->type)
     {
     case FFI_TYPE_VOID:
-#if !defined(X86_WIN32) 
+#if !defined(X86_WIN32)  && !defined(X86_DARWIN)
     case FFI_TYPE_STRUCT:
 #endif
     case FFI_TYPE_SINT64:
@@ -154,7 +154,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
       cif->flags = FFI_TYPE_SINT64;
       break;
 
-#if defined X86_WIN32  
+#if defined(X86_WIN32) || defined(X86_DARWIN)
 
     case FFI_TYPE_STRUCT:
       if (cif->rtype->size == 1)
@@ -186,10 +186,11 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
     }
 
   /* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
-#if 0
+#if 1
   cif->bytes = (cif->bytes + 15) & ~0xF;
 #endif
 
+
   return FFI_OK;
 }
 
@@ -221,7 +222,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
              /*@dependent@*/ void **avalue)
 {
   extended_cif ecif;
-  int flags;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
@@ -238,20 +238,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
   else
     ecif.rvalue = rvalue;
 
-  flags = cif->flags;
-  if (flags == FFI_TYPE_STRUCT) {
-    if (cif->rtype->size == 8) {
-       flags = FFI_TYPE_SINT64;
-    } else if (cif->rtype->size == 4) {
-        flags = FFI_TYPE_INT;
-    } else if (cif->rtype->size == 2) {
-        flags = FFI_TYPE_INT;
-    } else if (cif->rtype->size == 1) {
-        flags = FFI_TYPE_INT;
-    }
-  }
-
-  
   switch (cif->abi) 
     {
     case FFI_SYSV:
@@ -260,8 +246,8 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
        * block is a multiple of 16. Then add 8 to compensate for local variables
        * in ffi_call_SYSV.
        */
-      ffi_call_SYSV(ffi_prep_args, &ecif, ALIGN(cif->bytes, 16) +8
-                   flags, ecif.rvalue, fn);
+      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes
+                   cif->flags, ecif.rvalue, fn);
       /*@=usedef@*/
       break;
 #ifdef X86_WIN32
@@ -281,8 +267,6 @@ void ffi_call(/*@dependent@*/ ffi_cif *cif,
 
 /** private members **/
 
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-                                        void** args, ffi_cif* cif);
 static void ffi_closure_SYSV (ffi_closure *)
      __attribute__ ((regparm(1)));
 #if !FFI_NO_RAW_API
@@ -290,6 +274,48 @@ static void ffi_closure_raw_SYSV (ffi_raw_closure *)
      __attribute__ ((regparm(1)));
 #endif
 
+/*@-exportheader@*/
+static inline void 
+ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
+                           void **avalue, ffi_cif *cif)
+/*@=exportheader@*/
+{
+  register unsigned int i;
+  register void **p_argv;
+  register char *argp;
+  register ffi_type **p_arg;
+
+  argp = stack;
+
+  if (retval_on_stack(cif->rtype)) {
+    *rvalue = *(void **) argp;
+    argp += 4;
+  }
+
+  p_argv = avalue;
+
+  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+    {
+      size_t z;
+
+      /* Align if necessary */
+      if ((sizeof(int) - 1) & (unsigned) argp) {
+       argp = (char *) ALIGN(argp, sizeof(int));
+      }
+
+      z = (*p_arg)->size;
+
+      /* because we're little endian, this is what it turns into.   */
+
+      *p_argv = (void*) argp;
+
+      p_argv++;
+      argp += z;
+    }
+  
+  return;
+}
+
 /* This function is jumped to by the trampoline */
 
 static void
@@ -302,10 +328,10 @@ ffi_closure_SYSV (closure)
   // our various things...
   ffi_cif       *cif;
   void         **arg_area;
-  unsigned short rtype;
   void          *resp = (void*)&res;
   void *args = __builtin_dwarf_cfa ();
 
+
   cif         = closure->cif;
   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
 
@@ -319,94 +345,52 @@ ffi_closure_SYSV (closure)
   
   (closure->fun) (cif, resp, arg_area, closure->user_data);
 
-  rtype = cif->flags;
-
-  if (!retval_on_stack(cif->rtype) && cif->flags == FFI_TYPE_STRUCT) {
-      if (cif->rtype->size == 8) {
-         rtype = FFI_TYPE_SINT64;
-      } else {
-         rtype = FFI_TYPE_INT;
-      }
-  }
-
   /* now, do a generic return based on the value of rtype */
-  if (rtype == FFI_TYPE_INT)
+  if (cif->flags == FFI_TYPE_INT)
     {
       asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
     }
-  else if (rtype == FFI_TYPE_FLOAT)
+  else if (cif->flags == FFI_TYPE_FLOAT)
     {
       asm ("flds (%0)" : : "r" (resp) : "st" );
     }
-  else if (rtype == FFI_TYPE_DOUBLE)
+  else if (cif->flags == FFI_TYPE_DOUBLE)
     {
       asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
     }
-  else if (rtype == FFI_TYPE_LONGDOUBLE)
+  else if (cif->flags == FFI_TYPE_LONGDOUBLE)
     {
       asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
     }
-  else if (rtype == FFI_TYPE_SINT64)
+  else if (cif->flags == FFI_TYPE_SINT64)
     {
       asm ("movl 0(%0),%%eax;"
           "movl 4(%0),%%edx" 
           : : "r"(resp)
           : "eax", "edx");
     }
-#ifdef X86_WIN32
-  else if (rtype == FFI_TYPE_SINT8) /* 1-byte struct  */
+#if defined(X86_WIN32) || defined(X86_DARWIN)
+  else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct  */
     {
       asm ("movsbl (%0),%%eax" : : "r" (resp) : "eax");
     }
-  else if (rtype == FFI_TYPE_SINT16) /* 2-bytes struct */
+  else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
     {
       asm ("movswl (%0),%%eax" : : "r" (resp) : "eax");
     }
 #endif
-}
 
-/*@-exportheader@*/
-static void 
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
-                           void **avalue, ffi_cif *cif)
-/*@=exportheader@*/
-{
-  register unsigned int i;
-  register void **p_argv;
-  register char *argp;
-  register ffi_type **p_arg;
-
-  argp = stack;
-
-  if (retval_on_stack(cif->rtype)) {
-    *rvalue = *(void **) argp;
-    argp += 4;
-  }
-
-  p_argv = avalue;
-
-  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
+  else if (cif->flags == FFI_TYPE_STRUCT)
     {
-      size_t z;
-
-      /* Align if necessary */
-      if ((sizeof(int) - 1) & (unsigned) argp) {
-       argp = (char *) ALIGN(argp, sizeof(int));
-      }
-
-      z = (*p_arg)->size;
-
-      /* because we're little endian, this is what it turns into.   */
-
-      *p_argv = (void*) argp;
-
-      p_argv++;
-      argp += z;
+      asm ("lea -8(%ebp),%esp;"
+          "pop %esi;"
+          "pop %edi;"
+          "pop %ebp;"
+          "ret $4"); 
     }
-  
-  return;
 }
 
+
 /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
 
 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \