Commits

Ronald Oussoren  committed aacd3ae

Fix most issues with the darwin/x86 port of libffi. Two tests still fail, those
test structure arguments/returns where sizeof(thestruct) is 1 or 2.

GCC and the published ABI seem to be in disagreement: the ABI says that structs
whose size is 8 bytes or less are returned in registers. GCC only does that
when the size is also a power of two.

  • Participants
  • Parent commits 25d68f8
  • Branches pyobjc-ancient

Comments (0)

Files changed (3)

File libffi-src/src/types.c

 
 #endif
 
-#if defined X86 || defined ARM || defined M68K || defined(POWERPC_DARWIN)
+#if defined X86 || defined ARM || defined M68K || defined(POWERPC_DARWIN) || defined(X86_DARWIN)
 
 FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
 FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);

File libffi-src/src/x86/ffi_darwin.c

-#ifdef __i386__
+# ifdef __i386__
 /* -----------------------------------------------------------------------
    ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
            Copyright (c) 2002  Ranjit Mathew
 /*@-exportheader@*/
 void ffi_prep_args(char *stack, extended_cif *ecif);
 
+static inline int retval_on_stack(ffi_type* tp)
+{
+	if (tp->type == FFI_TYPE_STRUCT) {
+		int sz = tp->size;
+		if (sz > 8) {
+			return 1;
+		}
+		switch (sz) {
+		case 1: case 2: case 4: case 8: return 0;
+		default: return 1;
+		}
+	}
+	return 0;
+}
+
+
 void ffi_prep_args(char *stack, extended_cif *ecif)
 /*@=exportheader@*/
 {
 
   argp = stack;
 
-  if (ecif->cif->flags == FFI_TYPE_STRUCT && ecif->cif->rtype->size > 8)
-    {
+  if (retval_on_stack(ecif->cif->rtype)) {
       *(void **) argp = ecif->rvalue;
       argp += 4;
-    }
+  }
+
 
   p_argv = ecif->avalue;
 
 
       /* Align if necessary */
       if ((sizeof(int) - 1) & (unsigned) argp)
-	argp = (char *) ALIGN(argp, sizeof(int));
+	      argp = (char *) ALIGN(argp, sizeof(int));
 
       z = (*p_arg)->size;
       if (z < sizeof(int))
   /* 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->flags == FFI_TYPE_STRUCT) && (cif->rtype->size > 8))
+  if ((rvalue == NULL) && retval_on_stack(cif->rtype))
     {
       /*@-sysunrecog@*/
       ecif.rvalue = alloca(cif->rtype->size);
   if (flags == FFI_TYPE_STRUCT) {
     if (cif->rtype->size == 8) {
 	flags = FFI_TYPE_SINT64;
-    } else if (cif->rtype->size < 8) {
+    } 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;
     }
   }
     {
     case FFI_SYSV:
       /*@-usedef@*/
-      /* FIXME: we should pass in cif->bytes, the actual code below seems to
-       * work for correctly aligning the stack, but is something that should
-       * be done in the assembly code.
+      /* To avoid changing the assembly code make sure the size of the argument 
+       * 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, 
+      ffi_call_SYSV(ffi_prep_args, &ecif, ALIGN(cif->bytes, 16) +8, 
 		    flags, ecif.rvalue, fn);
       /*@=usedef@*/
       break;
 
   rtype = cif->flags;
 
-  if (rtype == FFI_TYPE_STRUCT && cif->rtype->size <= 8) {
+  if (!retval_on_stack(cif->rtype) && cif->flags == FFI_TYPE_STRUCT) {
       if (cif->rtype->size == 8) {
          rtype = FFI_TYPE_SINT64;
       } else {
 
   argp = stack;
 
-  if ( cif->flags == FFI_TYPE_STRUCT && (cif->rtype->size > 8)) {
+  if (retval_on_stack(cif->rtype)) {
     *rvalue = *(void **) argp;
     argp += 4;
   }
   /* 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->rtype->size > 8))
+  if ((rvalue == NULL) && retval_on_stack(cif->rtype)) 
     {
       /*@-sysunrecog@*/
       ecif.rvalue = alloca(cif->rtype->size);

File setup-lib/dejagnu.py

 
 
     def runTestCase(self):
-        os.environ['DYLD_BIND_AT_LAUNCH'] = '1'
+    #    os.environ['DYLD_BIND_AT_LAUNCH'] = '1'
         fp = os.popen('/tmp/test.bin', 'r')
-        del os.environ['DYLD_BIND_AT_LAUNCH']
+    #    del os.environ['DYLD_BIND_AT_LAUNCH']
         data = fp.read()
         xit = fp.close()
         if xit != None: