[Python-checkins] r47224 - python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c

ronald.oussoren python-checkins at python.org
Tue Jul 4 14:30:24 CEST 2006


Author: ronald.oussoren
Date: Tue Jul  4 14:30:22 2006
New Revision: 47224

Modified:
   python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S
   python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c
Log:
Sync the darwin/x86 port libffi with the copy in PyObjC. This fixes a number
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).


Modified: python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S
==============================================================================
--- python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S	(original)
+++ python/trunk/Modules/_ctypes/libffi/src/x86/darwin.S	Tue Jul  4 14:30:22 2006
@@ -35,6 +35,13 @@
 #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 @@
         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 @@
 	
 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

Modified: python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c
==============================================================================
--- python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c	(original)
+++ python/trunk/Modules/_ctypes/libffi/src/x86/ffi_darwin.c	Tue Jul  4 14:30:22 2006
@@ -140,7 +140,7 @@
   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 @@
       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 @@
     }
 
   /* 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 @@
 	      /*@dependent@*/ void **avalue)
 {
   extended_cif ecif;
-  int flags;
 
   ecif.cif = cif;
   ecif.avalue = avalue;
@@ -238,20 +238,6 @@
   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 @@
        * 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 @@
 
 /** 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 @@
      __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 @@
   // 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 @@
   
   (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) \


More information about the Python-checkins mailing list