[multiple changes]
authorAndrew Haley <aph@gcc.gnu.org>
Mon, 8 Jun 2009 17:03:31 +0000 (17:03 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Mon, 8 Jun 2009 17:03:31 +0000 (17:03 +0000)
2009-06-08  Andrew Haley  <aph@redhat.com>

* testsuite/libffi.call/err_bad_abi.c: Add xfails.
* testsuite/libffi.call/cls_longdouble_va.c: Add xfails.
* testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*.
* testsuite/libffi.call/err_bad_typedef.c: Add xfails.

* testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args.
* testsuite/libffi.call/stret_medium.c: Likewise.
* testsuite/libffi.call/stret_large2.c: Likewise.
* testsuite/libffi.call/stret_large.c:  Likewise.

2008-12-26  Timothy Wall  <twall@users.sf.net>

        * testsuite/libffi.call/cls_longdouble.c,
        testsuite/libffi.call/cls_longdouble_va.c,
        testsuite/libffi.call/cls_align_longdouble.c,
        testsuite/libffi.call/cls_align_longdouble_split.c,
        testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected
        failures on x86_64 cygwin/mingw.

2008-12-22  Timothy Wall  <twall@users.sf.net>

        * testsuite/libffi.call/closure_fn0.c,
        testsuite/libffi.call/closure_fn1.c,
        testsuite/libffi.call/closure_fn2.c,
        testsuite/libffi.call/closure_fn3.c,
        testsuite/libffi.call/closure_fn4.c,
        testsuite/libffi.call/closure_fn5.c,
        testsuite/libffi.call/closure_fn6.c,
        testsuite/libffi.call/closure_loc_fn0.c,
        testsuite/libffi.call/closure_stdcall.c,
        testsuite/libffi.call/cls_align_pointer.c,
        testsuite/libffi.call/cls_pointer.c,
        testsuite/libffi.call/cls_pointer_stack.c: use portable cast from
        pointer to integer (intptr_t).
        * testsuite/libffi.call/cls_longdouble.c: disable for win64.

2008-07-24  Anthony Green  <green@redhat.com>

        * testsuite/libffi.call/cls_dbls_struct.c,
        testsuite/libffi.call/cls_double_va.c,
        testsuite/libffi.call/cls_longdouble.c,
        testsuite/libffi.call/cls_longdouble_va.c,
        testsuite/libffi.call/cls_pointer.c,
        testsuite/libffi.call/cls_pointer_stack.c,
        testsuite/libffi.call/err_bad_abi.c: Clean up failures from
        compiler warnings.

2008-03-04  Anthony Green  <green@redhat.com>
            Blake Chaffin
            hos@tamanegi.org

        * testsuite/libffi.call/cls_align_longdouble_split2.c
          testsuite/libffi.call/cls_align_longdouble_split.c
          testsuite/libffi.call/cls_dbls_struct.c
          testsuite/libffi.call/cls_double_va.c
          testsuite/libffi.call/cls_longdouble.c
          testsuite/libffi.call/cls_longdouble_va.c
          testsuite/libffi.call/cls_pointer.c
          testsuite/libffi.call/cls_pointer_stack.c
          testsuite/libffi.call/err_bad_abi.c
          testsuite/libffi.call/err_bad_typedef.c
          testsuite/libffi.call/stret_large2.c
          testsuite/libffi.call/stret_large.c
          testsuite/libffi.call/stret_medium2.c
          testsuite/libffi.call/stret_medium.c: New tests from Apple.

From-SVN: r148285

27 files changed:
libffi/ChangeLog
libffi/testsuite/libffi.call/closure_fn0.c
libffi/testsuite/libffi.call/closure_fn1.c
libffi/testsuite/libffi.call/closure_fn2.c
libffi/testsuite/libffi.call/closure_fn3.c
libffi/testsuite/libffi.call/closure_fn4.c
libffi/testsuite/libffi.call/closure_fn5.c
libffi/testsuite/libffi.call/closure_fn6.c
libffi/testsuite/libffi.call/closure_loc_fn0.c [new file with mode: 0644]
libffi/testsuite/libffi.call/closure_stdcall.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_align_longdouble.c
libffi/testsuite/libffi.call/cls_align_longdouble_split.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_align_longdouble_split2.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_align_pointer.c
libffi/testsuite/libffi.call/cls_dbls_struct.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_double_va.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_longdouble.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_longdouble_va.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_pointer.c [new file with mode: 0644]
libffi/testsuite/libffi.call/cls_pointer_stack.c [new file with mode: 0644]
libffi/testsuite/libffi.call/err_bad_abi.c [new file with mode: 0644]
libffi/testsuite/libffi.call/err_bad_typedef.c [new file with mode: 0644]
libffi/testsuite/libffi.call/ffitest.h
libffi/testsuite/libffi.call/stret_large.c [new file with mode: 0644]
libffi/testsuite/libffi.call/stret_large2.c [new file with mode: 0644]
libffi/testsuite/libffi.call/stret_medium.c [new file with mode: 0644]
libffi/testsuite/libffi.call/stret_medium2.c [new file with mode: 0644]

index bf34ca1..f88d16c 100644 (file)
@@ -1,3 +1,71 @@
+2009-06-08  Andrew Haley  <aph@redhat.com>
+
+       * testsuite/libffi.call/err_bad_abi.c: Add xfails.
+       * testsuite/libffi.call/cls_longdouble_va.c: Add xfails.
+       * testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*.
+       * testsuite/libffi.call/err_bad_typedef.c: Add xfails.
+
+       * testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args.
+       * testsuite/libffi.call/stret_medium.c: Likewise.
+       * testsuite/libffi.call/stret_large2.c: Likewise.
+       * testsuite/libffi.call/stret_large.c:  Likewise.
+
+2008-12-26  Timothy Wall  <twall@users.sf.net>
+
+        * testsuite/libffi.call/cls_longdouble.c,
+        testsuite/libffi.call/cls_longdouble_va.c,
+        testsuite/libffi.call/cls_align_longdouble.c,
+        testsuite/libffi.call/cls_align_longdouble_split.c,
+        testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected
+        failures on x86_64 cygwin/mingw.
+
+2008-12-22  Timothy Wall  <twall@users.sf.net>
+
+        * testsuite/libffi.call/closure_fn0.c,
+        testsuite/libffi.call/closure_fn1.c,
+        testsuite/libffi.call/closure_fn2.c,
+        testsuite/libffi.call/closure_fn3.c,
+        testsuite/libffi.call/closure_fn4.c,
+        testsuite/libffi.call/closure_fn5.c,
+        testsuite/libffi.call/closure_fn6.c,
+        testsuite/libffi.call/closure_loc_fn0.c,
+        testsuite/libffi.call/closure_stdcall.c,
+        testsuite/libffi.call/cls_align_pointer.c,
+        testsuite/libffi.call/cls_pointer.c,
+        testsuite/libffi.call/cls_pointer_stack.c: use portable cast from
+        pointer to integer (intptr_t).
+        * testsuite/libffi.call/cls_longdouble.c: disable for win64.
+
+2008-07-24  Anthony Green  <green@redhat.com>
+
+        * testsuite/libffi.call/cls_dbls_struct.c,
+        testsuite/libffi.call/cls_double_va.c,
+        testsuite/libffi.call/cls_longdouble.c,
+        testsuite/libffi.call/cls_longdouble_va.c,
+        testsuite/libffi.call/cls_pointer.c,
+        testsuite/libffi.call/cls_pointer_stack.c,
+        testsuite/libffi.call/err_bad_abi.c: Clean up failures from
+        compiler warnings.
+
+2008-03-04  Anthony Green  <green@redhat.com>
+            Blake Chaffin
+            hos@tamanegi.org
+
+        * testsuite/libffi.call/cls_align_longdouble_split2.c
+          testsuite/libffi.call/cls_align_longdouble_split.c
+          testsuite/libffi.call/cls_dbls_struct.c
+          testsuite/libffi.call/cls_double_va.c
+          testsuite/libffi.call/cls_longdouble.c
+          testsuite/libffi.call/cls_longdouble_va.c
+          testsuite/libffi.call/cls_pointer.c
+          testsuite/libffi.call/cls_pointer_stack.c
+          testsuite/libffi.call/err_bad_abi.c
+          testsuite/libffi.call/err_bad_typedef.c
+          testsuite/libffi.call/stret_large2.c
+          testsuite/libffi.call/stret_large.c
+          testsuite/libffi.call/stret_medium2.c
+          testsuite/libffi.call/stret_medium.c: New tests from Apple.
+
 2009-06-05  Andrew Haley  <aph@redhat.com>
 
        * src/x86/ffitarget.h, src/x86/ffi.c: Merge stdcall changes from
index e487527..b42fc20 100644 (file)
@@ -25,7 +25,7 @@ closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
     (int)(*(double *)args[8]) + (int)*(int *)args[9] +
     (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
     (int)*(int *)args[12] + (int)(*(int *)args[13]) +
-    (int)(*(int *)args[14]) +  *(int *)args[15] + (int)(long)userdata;
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (intptr_t)userdata;
 
   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
         (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]),
@@ -37,7 +37,7 @@ closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
         (int)(*(int *)args[10]), (int)(*(float *)args[11]),
         (int)*(int *)args[12], (int)(*(int *)args[13]),
         (int)(*(int *)args[14]),*(int *)args[15],
-        (int)(long)userdata, (int)*(ffi_arg *)resp);
+        (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
 
 }
 
index db26c42..82b9b1d 100644 (file)
@@ -21,7 +21,7 @@ static void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
     (int)(*(double*)args[8]) + (int)*(int *)args[9] +
     (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
     (int)*(int *)args[12] + (int)(*(int *)args[13]) +
-    (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
+    (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata;
 
   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
         (int)*(float *)args[0], (int)(*(float *)args[1]),
@@ -32,7 +32,7 @@ static void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
         (int)(*(int *)args[10]), (int)(*(float *)args[11]),
         (int)*(int *)args[12], (int)(*(int *)args[13]),
         (int)(*(int *)args[14]), *(int *)args[15],
-        (int)(long)userdata, (int)*(ffi_arg *)resp);
+        (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
 }
 
 typedef int (*closure_test_type1)(float, float, float, float, signed short,
index cbf7385..d0ba48e 100644 (file)
@@ -20,7 +20,7 @@ static void closure_test_fn2(ffi_cif* cif __UNUSED__, void* resp, void** args,
     (int)(*(double *)args[8]) + (int)*(int *)args[9] +
     (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
     (int)*(int *)args[12] + (int)(*(float *)args[13]) +
-    (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
+    (int)(*(int *)args[14]) + *(int *)args[15] + (intptr_t)userdata;
 
   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
         (int)*(double *)args[0], (int)(*(double *)args[1]),
@@ -30,7 +30,7 @@ static void closure_test_fn2(ffi_cif* cif __UNUSED__, void* resp, void** args,
         (int)(*(double*)args[8]), (int)*(int *)args[9],
         (int)(*(int *)args[10]), (int)(*(float *)args[11]),
         (int)*(int *)args[12], (int)(*(float *)args[13]),
-        (int)(*(int *)args[14]), *(int *)args[15], (int)(long)userdata,
+        (int)(*(int *)args[14]), *(int *)args[15], (int)(intptr_t)userdata,
         (int)*(ffi_arg *)resp);
 }
 
index 1fb32a8..be4062d 100644 (file)
@@ -20,7 +20,7 @@ static void closure_test_fn3(ffi_cif* cif __UNUSED__, void* resp, void** args,
      (int)(*(double *)args[8]) + (int)*(int *)args[9] +
      (int)(*(float *)args[10]) + (int)(*(float *)args[11]) +
      (int)*(int *)args[12] + (int)(*(float *)args[13]) +
-     (int)(*(float *)args[14]) +  *(int *)args[15] + (int)(long)userdata;
+     (int)(*(float *)args[14]) +  *(int *)args[15] + (intptr_t)userdata;
 
    printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
          (int)*(float *)args[0], (int)(*(float *)args[1]),
@@ -30,7 +30,7 @@ static void closure_test_fn3(ffi_cif* cif __UNUSED__, void* resp, void** args,
          (int)(*(double *)args[8]), (int)*(int *)args[9],
          (int)(*(float *)args[10]), (int)(*(float *)args[11]),
          (int)*(int *)args[12], (int)(*(float *)args[13]),
-         (int)(*(float *)args[14]), *(int *)args[15], (int)(long)userdata,
+         (int)(*(float *)args[14]), *(int *)args[15], (int)(intptr_t)userdata,
          (int)*(ffi_arg *)resp);
 
  }
index 74506f3..9a70b99 100644 (file)
@@ -25,7 +25,7 @@ closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
     (int)*(unsigned long long *)args[12] +
     (int)*(unsigned long long *)args[13] +
     (int)*(unsigned long long *)args[14] +
-    *(int *)args[15] + (int)(long)userdata;
+    *(int *)args[15] + (intptr_t)userdata;
 
   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
         (int)*(unsigned long long *)args[0],
@@ -44,7 +44,7 @@ closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
         (int)*(unsigned long long *)args[13],
         (int)*(unsigned long long *)args[14],
         *(int *)args[15],
-        (int)(long)userdata, (int)*(ffi_arg *)resp);
+        (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
 
 }
 
index c64ee8d..c12491e 100644 (file)
@@ -24,7 +24,7 @@ closure_test_fn5(ffi_cif* cif __UNUSED__, void* resp, void** args,
     (int)*(unsigned long long *)args[12] +
     (int)*(unsigned long long *)args[13] +
     (int)*(unsigned long long *)args[14] +
-    *(int *)args[15] + (int)(long)userdata;
+    *(int *)args[15] + (intptr_t)userdata;
 
   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
         (int)*(unsigned long long *)args[0],
@@ -43,7 +43,7 @@ closure_test_fn5(ffi_cif* cif __UNUSED__, void* resp, void** args,
         (int)*(unsigned long long *)args[13],
         (int)*(unsigned long long *)args[14],
         *(int *)args[15],
-        (int)(long)userdata, (int)*(ffi_arg *)resp);
+        (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
 
 }
 
index 16c52fd..5d9389d 100644 (file)
@@ -23,7 +23,7 @@ closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
     (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
     (int)*(int *)args[12] + (int)(*(int *)args[13]) +
     (int)(*(double *)args[14]) +  (int)*(double *)args[15] +
-    (int)(long)userdata;
+    (intptr_t)userdata;
 
   printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
         (int)*(unsigned long long  *)args[0],
@@ -36,7 +36,7 @@ closure_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
         (int)(*(int *)args[10]), (int)(*(float *)args[11]),
         (int)*(int *)args[12], (int)(*(int *)args[13]),
         (int)(*(double *)args[14]), (int)(*(double *)args[15]),
-        (int)(long)userdata, (int)*(ffi_arg *)resp);
+        (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
 
 }
 
diff --git a/libffi/testsuite/libffi.call/closure_loc_fn0.c b/libffi/testsuite/libffi.call/closure_loc_fn0.c
new file mode 100644 (file)
index 0000000..b3afa0b
--- /dev/null
@@ -0,0 +1,95 @@
+/* Area:       closure_call
+   Purpose:    Check multiple values passing from different type.
+               Also, exceed the limit of gpr and fpr registers on PowerPC
+               Darwin.
+   Limitations:        none.
+   PR:         none.
+   Originator: <andreast@gcc.gnu.org> 20030828  */
+
+
+
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static void
+closure_loc_test_fn0(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
+    (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
+    (int)(*(signed short *)args[4]) +
+    (int)(*(unsigned long long *)args[5]) +
+    (int)*(int *)args[6] + (int)(*(int *)args[7]) +
+    (int)(*(double *)args[8]) + (int)*(int *)args[9] +
+    (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+    (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+    (int)(*(int *)args[14]) +  *(int *)args[15] + (intptr_t)userdata;
+
+  printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+        (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]),
+        (int)(*(unsigned long long *)args[2]),
+        (int)*(int *)args[3], (int)(*(signed short *)args[4]),
+        (int)(*(unsigned long long *)args[5]),
+        (int)*(int *)args[6], (int)(*(int *)args[7]),
+        (int)(*(double *)args[8]), (int)*(int *)args[9],
+        (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+        (int)*(int *)args[12], (int)(*(int *)args[13]),
+        (int)(*(int *)args[14]),*(int *)args[15],
+        (int)(intptr_t)userdata, (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (*closure_loc_test_type0)(unsigned long long, int, unsigned long long,
+                                 int, signed short, unsigned long long, int,
+                                 int, double, int, int, float, int, int,
+                                 int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+  void *codeloc;
+
+  cl_arg_types[0] = &ffi_type_uint64;
+  cl_arg_types[1] = &ffi_type_sint;
+  cl_arg_types[2] = &ffi_type_uint64;
+  cl_arg_types[3] = &ffi_type_sint;
+  cl_arg_types[4] = &ffi_type_sshort;
+  cl_arg_types[5] = &ffi_type_uint64;
+  cl_arg_types[6] = &ffi_type_sint;
+  cl_arg_types[7] = &ffi_type_sint;
+  cl_arg_types[8] = &ffi_type_double;
+  cl_arg_types[9] = &ffi_type_sint;
+  cl_arg_types[10] = &ffi_type_sint;
+  cl_arg_types[11] = &ffi_type_float;
+  cl_arg_types[12] = &ffi_type_sint;
+  cl_arg_types[13] = &ffi_type_sint;
+  cl_arg_types[14] = &ffi_type_sint;
+  cl_arg_types[15] = &ffi_type_sint;
+  cl_arg_types[16] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  pcl = ffi_closure_alloc(sizeof(ffi_closure), &codeloc);
+  CHECK(pcl != NULL);
+  CHECK(codeloc != NULL);
+
+  CHECK(ffi_prep_closure_loc(pcl, &cif, closure_loc_test_fn0,
+                        (void *) 3 /* userdata */, codeloc) == FFI_OK);
+  
+  CHECK(memcmp(pcl, codeloc, sizeof(*pcl)) == 0);
+
+  res = (*((closure_loc_test_type0)codeloc))
+    (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13,
+     19, 21, 1);
+  /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 680" } */
+     exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/closure_stdcall.c b/libffi/testsuite/libffi.call/closure_stdcall.c
new file mode 100644 (file)
index 0000000..020b469
--- /dev/null
@@ -0,0 +1,72 @@
+/* Area:       closure_call (stdcall convention)
+   Purpose:    Check handling when caller expects stdcall callee
+   Limitations:        none.
+   PR:         none.
+   Originator: <twalljava@dev.java.net> */
+
+/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
+#include "ffitest.h"
+
+static void
+closure_test_stdcall(ffi_cif* cif __UNUSED__, void* resp, void** args,
+                void* userdata)
+{
+  *(ffi_arg*)resp =
+    (int)*(int *)args[0] + (int)(*(int *)args[1])
+    + (int)(*(int *)args[2])  + (int)(*(int *)args[3])
+    + (int)(intptr_t)userdata;
+
+  printf("%d %d %d %d: %d\n",
+        (int)*(int *)args[0], (int)(*(int *)args[1]),
+        (int)(*(int *)args[2]), (int)(*(int *)args[3]),
+         (int)*(ffi_arg *)resp);
+
+}
+
+typedef int (__stdcall *closure_test_type0)(int, int, int, int);
+
+int main (void)
+{
+  ffi_cif cif;
+#ifndef USING_MMAP
+  static ffi_closure cl;
+#endif
+  ffi_closure *pcl;
+  ffi_type * cl_arg_types[17];
+  int res;
+  void* sp_pre;
+  void* sp_post;
+  char buf[1024];
+
+#ifdef USING_MMAP
+  pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+  pcl = &cl;
+#endif
+
+  cl_arg_types[0] = &ffi_type_uint;
+  cl_arg_types[1] = &ffi_type_uint;
+  cl_arg_types[2] = &ffi_type_uint;
+  cl_arg_types[3] = &ffi_type_uint;
+  cl_arg_types[4] = NULL;
+
+  /* Initialize the cif */
+  CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
+                    &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+  CHECK(ffi_prep_closure(pcl, &cif, closure_test_stdcall,
+                        (void *) 3 /* userdata */) == FFI_OK);
+
+  asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
+  res = (*(closure_test_type0)pcl)(0, 1, 2, 3);
+  asm volatile (" movl %%esp,%0" : "=g" (sp_post));
+  /* { dg-output "0 1 2 3: 9" } */
+
+  printf("res: %d\n",res);
+  /* { dg-output "\nres: 9" } */
+
+  sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
+  printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
+  /* { dg-output "\nstack pointer match" } */
+  exit(0);
+}
index cb60395..74cddc3 100644 (file)
@@ -4,7 +4,7 @@
    PR:         none.
    Originator: <hos@tamanegi.org> 20031203      */
 
-/* { dg-do run } */
+/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
 
 #include "ffitest.h"
 
diff --git a/libffi/testsuite/libffi.call/cls_align_longdouble_split.c b/libffi/testsuite/libffi.call/cls_align_longdouble_split.c
new file mode 100644 (file)
index 0000000..b350b3d
--- /dev/null
@@ -0,0 +1,140 @@
+/* Area:       ffi_call, closure_call
+   Purpose:    Check structure alignment of long double.
+   Limitations:        none.
+   PR:         none.
+   Originator: <hos@tamanegi.org> 20031203      */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  long double a;
+  long double b;
+  long double c;
+  long double d;
+  long double e;
+  long double f;
+  long double g;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+       cls_struct_align        a1,
+       cls_struct_align        a2)
+{
+       struct cls_struct_align r;
+
+       r.a = a1.a + a2.a;
+       r.b = a1.b + a2.b;
+       r.c = a1.c + a2.c;
+       r.d = a1.d + a2.d;
+       r.e = a1.e + a2.e;
+       r.f = a1.f + a2.f;
+       r.g = a1.g + a2.g;
+
+       printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
+               "%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
+               a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+               a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+               r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+       return r;
+}
+
+cls_struct_align cls_struct_align_fn2(
+       cls_struct_align        a1)
+{
+       struct cls_struct_align r;
+
+       r.a = a1.a + 1;
+       r.b = a1.b + 1;
+       r.c = a1.c + 1;
+       r.d = a1.d + 1;
+       r.e = a1.e + 1;
+       r.f = a1.f + 1;
+       r.g = a1.g + 1;
+
+       printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
+               "%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
+               a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+               r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+       return r;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, 
+                   void* userdata __UNUSED__)
+{
+       struct cls_struct_align a1, a2;
+
+       a1 = *(struct cls_struct_align*)(args[0]);
+       a2 = *(struct cls_struct_align*)(args[1]);
+
+       *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args_dbl[3];
+       ffi_type* cls_struct_fields[8];
+       ffi_type cls_struct_type;
+       ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       cls_struct_type.size = 0;
+       cls_struct_type.alignment = 0;
+       cls_struct_type.type = FFI_TYPE_STRUCT;
+       cls_struct_type.elements = cls_struct_fields;
+
+       struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
+       struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
+       struct cls_struct_align res_dbl;
+
+       cls_struct_fields[0] = &ffi_type_longdouble;
+       cls_struct_fields[1] = &ffi_type_longdouble;
+       cls_struct_fields[2] = &ffi_type_longdouble;
+       cls_struct_fields[3] = &ffi_type_longdouble;
+       cls_struct_fields[4] = &ffi_type_longdouble;
+       cls_struct_fields[5] = &ffi_type_longdouble;
+       cls_struct_fields[6] = &ffi_type_longdouble;
+       cls_struct_fields[7] = NULL;
+
+       dbl_arg_types[0] = &cls_struct_type;
+       dbl_arg_types[1] = &cls_struct_type;
+       dbl_arg_types[2] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+               dbl_arg_types) == FFI_OK);
+
+       args_dbl[0] = &g_dbl;
+       args_dbl[1] = &f_dbl;
+       args_dbl[2] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+       /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+       printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+       /* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+       res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+       /* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+       printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+       /* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+  exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c b/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c
new file mode 100644 (file)
index 0000000..0e8be3f
--- /dev/null
@@ -0,0 +1,120 @@
+/*     Area:                   ffi_call, closure_call
+       Purpose:                Check structure alignment of long double.
+       Limitations:    none.
+       PR:                             none.
+       Originator:             Blake Chaffin   6/18/2007
+*/
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-* } } */
+
+#include "ffitest.h"
+
+typedef struct cls_struct_align {
+  long double a;
+  long double b;
+  long double c;
+  long double d;
+  long double e;
+  double f;
+  long double g;
+} cls_struct_align;
+
+cls_struct_align cls_struct_align_fn(
+       cls_struct_align        a1,
+       cls_struct_align        a2)
+{
+       struct cls_struct_align r;
+
+       r.a = a1.a + a2.a;
+       r.b = a1.b + a2.b;
+       r.c = a1.c + a2.c;
+       r.d = a1.d + a2.d;
+       r.e = a1.e + a2.e;
+       r.f = a1.f + a2.f;
+       r.g = a1.g + a2.g;
+
+       printf("%Lg %Lg %Lg %Lg %Lg %g %Lg %Lg %Lg %Lg %Lg %Lg %g %Lg: "
+               "%Lg %Lg %Lg %Lg %Lg %g %Lg\n",
+               a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
+               a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
+               r.a, r.b, r.c, r.d, r.e, r.f, r.g);
+
+       return r;
+}
+
+static void
+cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, 
+                   void* userdata __UNUSED__)
+{
+       struct cls_struct_align a1, a2;
+
+       a1 = *(struct cls_struct_align*)(args[0]);
+       a2 = *(struct cls_struct_align*)(args[1]);
+
+       *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args_dbl[3];
+       ffi_type* cls_struct_fields[8];
+       ffi_type cls_struct_type;
+       ffi_type* dbl_arg_types[3];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       cls_struct_type.size = 0;
+       cls_struct_type.alignment = 0;
+       cls_struct_type.type = FFI_TYPE_STRUCT;
+       cls_struct_type.elements = cls_struct_fields;
+
+       struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
+       struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
+       struct cls_struct_align res_dbl;
+
+       cls_struct_fields[0] = &ffi_type_longdouble;
+       cls_struct_fields[1] = &ffi_type_longdouble;
+       cls_struct_fields[2] = &ffi_type_longdouble;
+       cls_struct_fields[3] = &ffi_type_longdouble;
+       cls_struct_fields[4] = &ffi_type_longdouble;
+       cls_struct_fields[5] = &ffi_type_double;
+       cls_struct_fields[6] = &ffi_type_longdouble;
+       cls_struct_fields[7] = NULL;
+
+       dbl_arg_types[0] = &cls_struct_type;
+       dbl_arg_types[1] = &cls_struct_type;
+       dbl_arg_types[2] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
+               dbl_arg_types) == FFI_OK);
+
+       args_dbl[0] = &g_dbl;
+       args_dbl[1] = &f_dbl;
+       args_dbl[2] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
+       /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+       printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+       /* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
+
+       res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
+       /* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
+       printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
+       /* { dg-output "\nres: 9 11 13 15 17 19 21" } */
+
+  exit(0);
+}
index 441edcb..9a79922 100644 (file)
@@ -19,11 +19,13 @@ cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
   struct cls_struct_align result;
 
   result.a = a1.a + a2.a;
-  result.b = (void *)((unsigned long)a1.b + (unsigned long)a2.b);
+  result.b = (void *)((uintptr_t)a1.b + (uintptr_t)a2.b);
   result.c = a1.c + a2.c;
 
-  printf("%d %lu %d %d %lu %d: %d %lu %d\n", a1.a, (unsigned long)a1.b, a1.c,
-        a2.a, (unsigned long)a2.b, a2.c, result.a, (unsigned long)result.b,
+  printf("%d %" PRIuPTR " %d %d %" PRIuPTR " %d: %d %" PRIuPTR " %d\n", 
+         a1.a, (uintptr_t)a1.b, a1.c,
+        a2.a, (uintptr_t)a2.b, a2.c,
+         result.a, (uintptr_t)result.b,
         result.c);
 
   return result;
@@ -87,14 +89,14 @@ int main (void)
 
   ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
   /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
-  printf("res: %d %lu %d\n", res_dbl.a, (unsigned long)res_dbl.b, res_dbl.c);
+  printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
   /* { dg-output "\nres: 13 14271 140" } */
 
   CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK);
 
   res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl);
   /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
-  printf("res: %d %lu %d\n", res_dbl.a, (unsigned long)res_dbl.b, res_dbl.c);
+  printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
   /* { dg-output "\nres: 13 14271 140" } */
 
   exit(0);
diff --git a/libffi/testsuite/libffi.call/cls_dbls_struct.c b/libffi/testsuite/libffi.call/cls_dbls_struct.c
new file mode 100644 (file)
index 0000000..c568381
--- /dev/null
@@ -0,0 +1,75 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check double arguments in structs.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/23/2007 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+typedef struct Dbls {
+       double x;
+       double y;
+} Dbls;
+
+void
+closure_test_fn(Dbls p)
+{
+       printf("%.1f %.1f\n", p.x, p.y);
+}
+
+void
+closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+               void** args, void* userdata __UNUSED__)
+{
+       closure_test_fn(*(Dbls*)args[0]);
+}
+
+int main(int argc __UNUSED__, char** argv __UNUSED__)
+{
+       ffi_cif cif;
+
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+
+       ffi_closure*    pcl;
+       ffi_type*               cl_arg_types[1];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap(sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       ffi_type        ts1_type;
+       ffi_type*       ts1_type_elements[4];
+
+       ts1_type.size = 0;
+       ts1_type.alignment = 0;
+       ts1_type.type = FFI_TYPE_STRUCT;
+       ts1_type.elements = ts1_type_elements;
+
+       ts1_type_elements[0] = &ffi_type_double;
+       ts1_type_elements[1] = &ffi_type_double;
+       ts1_type_elements[2] = NULL;
+
+       cl_arg_types[0] = &ts1_type;
+
+       Dbls arg = { 1.0, 2.0 };
+
+       /* Initialize the cif */
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+                                &ffi_type_void, cl_arg_types) == FFI_OK);
+
+       CHECK(ffi_prep_closure(pcl, &cif, closure_test_gn, NULL) == FFI_OK);
+
+       ((void*(*)(Dbls))(pcl))(arg);
+       /* { dg-output "1.0 2.0\n" { xfail x86_64-*-linux-* } } */
+
+       closure_test_fn(arg);
+       /* { dg-output "1.0 2.0\n" } */
+
+       return 0;
+}
diff --git a/libffi/testsuite/libffi.call/cls_double_va.c b/libffi/testsuite/libffi.call/cls_double_va.c
new file mode 100644 (file)
index 0000000..4d6d5b7
--- /dev/null
@@ -0,0 +1,64 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Test doubles passed in variable argument lists.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/6/2007   */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static void
+cls_double_va_fn(ffi_cif* cif __UNUSED__, void* resp, 
+                void** args, void* userdata __UNUSED__)
+{
+       char*   format          = *(char**)args[0];
+       double  doubleValue     = *(double*)args[1];
+
+       *(ffi_arg*)resp = printf(format, doubleValue);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args[3];
+       ffi_type* arg_types[3];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap(sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       char*   format          = "%.1f\n";
+       double  doubleArg       = 7;
+       ffi_arg res                     = 0;
+
+       arg_types[0] = &ffi_type_pointer;
+       arg_types[1] = &ffi_type_double;
+       arg_types[2] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
+               arg_types) == FFI_OK);
+
+       args[0] = &format;
+       args[1] = &doubleArg;
+       args[2] = NULL;
+
+       ffi_call(&cif, FFI_FN(printf), &res, args);
+       // { dg-output "7.0" }
+       printf("res: %d\n", (int) res);
+       // { dg-output "\nres: 4" }
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_double_va_fn, NULL) == FFI_OK);
+
+       res     = ((int(*)(char*, double))(pcl))(format, doubleArg);
+       // { dg-output "\n7.0" }
+       printf("res: %d\n", (int) res);
+       // { dg-output "\nres: 4" }
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/cls_longdouble.c b/libffi/testsuite/libffi.call/cls_longdouble.c
new file mode 100644 (file)
index 0000000..a0fafc9
--- /dev/null
@@ -0,0 +1,111 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check long double arguments.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin   */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* x86_64-*-mingw* x86_64-*-cygwin* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-* } } */
+
+#include "ffitest.h"
+
+long double cls_ldouble_fn(
+       long double     a1,
+       long double     a2,
+       long double     a3,
+       long double     a4,
+       long double     a5,
+       long double     a6,
+       long double     a7,
+       long double     a8)
+{
+       long double     r = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;
+
+       printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: %Lg\n",
+               a1, a2, a3, a4, a5, a6, a7, a8, r);
+
+       return r;
+}
+
+static void
+cls_ldouble_gn(ffi_cif* cif __UNUSED__, void* resp, 
+              void** args, void* userdata __UNUSED__)
+{
+       long double     a1      = *(long double*)args[0];
+       long double     a2      = *(long double*)args[1];
+       long double     a3      = *(long double*)args[2];
+       long double     a4      = *(long double*)args[3];
+       long double     a5      = *(long double*)args[4];
+       long double     a6      = *(long double*)args[5];
+       long double     a7      = *(long double*)args[6];
+       long double     a8      = *(long double*)args[7];
+
+       *(long double*)resp = cls_ldouble_fn(
+               a1, a2, a3, a4, a5, a6, a7, a8);
+}
+
+int main(void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure      cl;
+#endif
+       ffi_closure*    pcl;
+       void*                   args[9];
+       ffi_type*               arg_types[9];
+       long double             res     = 0;
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap(sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       long double     arg1    = 1;
+       long double     arg2    = 2;
+       long double     arg3    = 3;
+       long double     arg4    = 4;
+       long double     arg5    = 5;
+       long double     arg6    = 6;
+       long double     arg7    = 7;
+       long double     arg8    = 8;
+
+       arg_types[0] = &ffi_type_longdouble;
+       arg_types[1] = &ffi_type_longdouble;
+       arg_types[2] = &ffi_type_longdouble;
+       arg_types[3] = &ffi_type_longdouble;
+       arg_types[4] = &ffi_type_longdouble;
+       arg_types[5] = &ffi_type_longdouble;
+       arg_types[6] = &ffi_type_longdouble;
+       arg_types[7] = &ffi_type_longdouble;
+       arg_types[8] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 8, &ffi_type_longdouble,
+               arg_types) == FFI_OK);
+
+       args[0] = &arg1;
+       args[1] = &arg2;
+       args[2] = &arg3;
+       args[3] = &arg4;
+       args[4] = &arg5;
+       args[5] = &arg6;
+       args[6] = &arg7;
+       args[7] = &arg8;
+       args[8] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_ldouble_fn), &res, args);
+       /* { dg-output "1 2 3 4 5 6 7 8: 36" } */
+       printf("res: %Lg\n", res);
+       /* { dg-output "\nres: 36" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_ldouble_gn, NULL) == FFI_OK);
+
+       res = ((long double(*)(long double, long double, long double, long double,
+               long double, long double, long double, long double))(pcl))(arg1, arg2,
+               arg3, arg4, arg5, arg6, arg7, arg8);
+       /* { dg-output "\n1 2 3 4 5 6 7 8: 36" } */
+       printf("res: %Lg\n", res);
+       /* { dg-output "\nres: 36" } */
+
+       return 0;
+}
diff --git a/libffi/testsuite/libffi.call/cls_longdouble_va.c b/libffi/testsuite/libffi.call/cls_longdouble_va.c
new file mode 100644 (file)
index 0000000..d5a7fe5
--- /dev/null
@@ -0,0 +1,64 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Test long doubles passed in variable argument lists.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/6/2007   */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* x86_64-*-mingw* x86_64-*-cygwin* } } */
+#include "ffitest.h"
+
+static void
+cls_longdouble_va_fn(ffi_cif* cif __UNUSED__, void* resp, 
+                    void** args, void* userdata __UNUSED__)
+{
+       char*           format  = *(char**)args[0];
+       long double     ldValue = *(long double*)args[1];
+
+       *(ffi_arg*)resp = printf(format, ldValue);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args[3];
+       ffi_type* arg_types[3];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       char*           format  = "%L.1f\n";
+       long double     ldArg   = 7;
+       ffi_arg         res             = 0;
+
+       arg_types[0] = &ffi_type_pointer;
+       arg_types[1] = &ffi_type_longdouble;
+       arg_types[2] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
+               arg_types) == FFI_OK);
+
+       args[0] = &format;
+       args[1] = &ldArg;
+       args[2] = NULL;
+
+       ffi_call(&cif, FFI_FN(printf), &res, args);
+       // { dg-output "7.0" { xfail i*86-*-linux-* x86_64-*-linux-* } }
+       printf("res: %d\n", (int) res);
+       // { dg-output "\nres: 4" { xfail i*86-*-linux-* x86_64-*-linux-* } }
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_longdouble_va_fn, NULL) == FFI_OK);
+
+       res     = ((int(*)(char*, long double))(pcl))(format, ldArg);
+       // { dg-output "\n7.0" }
+       printf("res: %d\n", (int) res);
+       // { dg-output "\nres: 4" }
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/cls_pointer.c b/libffi/testsuite/libffi.call/cls_pointer.c
new file mode 100644 (file)
index 0000000..ffc1f6a
--- /dev/null
@@ -0,0 +1,82 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check pointer arguments.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/6/2007  */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+void* cls_pointer_fn(void* a1, void* a2)
+{
+       void*   result  = (void*)((intptr_t)a1 + (intptr_t)a2);
+
+       printf("0x%08x 0x%08x: 0x%08x\n", 
+              (unsigned int)(uintptr_t) a1,
+               (unsigned int)(uintptr_t) a2,
+               (unsigned int)(uintptr_t) result);
+
+       return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
+              void** args, void* userdata __UNUSED__)
+{
+       void*   a1      = *(void**)(args[0]);
+       void*   a2      = *(void**)(args[1]);
+
+       *(void**)resp = cls_pointer_fn(a1, a2);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure      cl;
+#endif
+       ffi_closure*    pcl;
+       void*                   args[3];
+//     ffi_type                cls_pointer_type;
+       ffi_type*               arg_types[3];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap(sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+/*     cls_pointer_type.size = sizeof(void*);
+       cls_pointer_type.alignment = 0;
+       cls_pointer_type.type = FFI_TYPE_POINTER;
+       cls_pointer_type.elements = NULL;*/
+
+       void*   arg1    = (void*)0x12345678;
+       void*   arg2    = (void*)0x89abcdef;
+       ffi_arg res             = 0;
+
+       arg_types[0] = &ffi_type_pointer;
+       arg_types[1] = &ffi_type_pointer;
+       arg_types[2] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
+               arg_types) == FFI_OK);
+
+       args[0] = &arg1;
+       args[1] = &arg2;
+       args[2] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_pointer_fn), &res, args);
+       /* { dg-output "0x12345678 0x89abcdef: 0x9be02467" } */
+       printf("res: 0x%08x\n", (unsigned int) res);
+       /* { dg-output "\nres: 0x9be02467" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_pointer_gn, NULL) == FFI_OK);
+
+       res = (ffi_arg)((void*(*)(void*, void*))(pcl))(arg1, arg2);
+       /* { dg-output "\n0x12345678 0x89abcdef: 0x9be02467" } */
+       printf("res: 0x%08x\n", (unsigned int) res);
+       /* { dg-output "\nres: 0x9be02467" } */
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/cls_pointer_stack.c b/libffi/testsuite/libffi.call/cls_pointer_stack.c
new file mode 100644 (file)
index 0000000..c7ab55b
--- /dev/null
@@ -0,0 +1,148 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check pointer arguments across multiple hideous stack frames.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/7/2007  */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+static long dummyVar;
+
+long dummy_func(
+       long double a1, char b1,
+       long double a2, char b2,
+       long double a3, char b3,
+       long double a4, char b4)
+{
+       return a1 + b1 + a2 + b2 + a3 + b3 + a4 + b4;
+}
+
+void* cls_pointer_fn2(void* a1, void* a2)
+{
+       long double     trample1        = (intptr_t)a1 + (intptr_t)a2;
+       char            trample2        = ((char*)&a1)[0] + ((char*)&a2)[0];
+       long double     trample3        = (intptr_t)trample1 + (intptr_t)a1;
+       char            trample4        = trample2 + ((char*)&a1)[1];
+       long double     trample5        = (intptr_t)trample3 + (intptr_t)a2;
+       char            trample6        = trample4 + ((char*)&a2)[1];
+       long double     trample7        = (intptr_t)trample5 + (intptr_t)trample1;
+       char            trample8        = trample6 + trample2;
+
+       dummyVar        = dummy_func(trample1, trample2, trample3, trample4,
+               trample5, trample6, trample7, trample8);
+
+       void*   result  = (void*)((intptr_t)a1 + (intptr_t)a2);
+
+       printf("0x%08x 0x%08x: 0x%08x\n", 
+              (unsigned int)(uintptr_t) a1,
+               (unsigned int)(uintptr_t) a2,
+               (unsigned int)(uintptr_t) result);
+
+       return result;
+}
+
+void* cls_pointer_fn1(void* a1, void* a2)
+{
+       long double     trample1        = (intptr_t)a1 + (intptr_t)a2;
+       char            trample2        = ((char*)&a1)[0] + ((char*)&a2)[0];
+       long double     trample3        = (intptr_t)trample1 + (intptr_t)a1;
+       char            trample4        = trample2 + ((char*)&a1)[1];
+       long double     trample5        = (intptr_t)trample3 + (intptr_t)a2;
+       char            trample6        = trample4 + ((char*)&a2)[1];
+       long double     trample7        = (intptr_t)trample5 + (intptr_t)trample1;
+       char            trample8        = trample6 + trample2;
+
+       dummyVar        = dummy_func(trample1, trample2, trample3, trample4,
+               trample5, trample6, trample7, trample8);
+
+       void*   result  = (void*)((intptr_t)a1 + (intptr_t)a2);
+
+       printf("0x%08x 0x%08x: 0x%08x\n",
+               (unsigned int)(intptr_t) a1,
+               (unsigned int)(intptr_t) a2,
+               (unsigned int)(intptr_t) result);
+
+       result  = cls_pointer_fn2(result, a1);
+
+       return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp, 
+              void** args, void* userdata __UNUSED__)
+{
+       void*   a1      = *(void**)(args[0]);
+       void*   a2      = *(void**)(args[1]);
+
+       long double     trample1        = (intptr_t)a1 + (intptr_t)a2;
+       char            trample2        = ((char*)&a1)[0] + ((char*)&a2)[0];
+       long double     trample3        = (intptr_t)trample1 + (intptr_t)a1;
+       char            trample4        = trample2 + ((char*)&a1)[1];
+       long double     trample5        = (intptr_t)trample3 + (intptr_t)a2;
+       char            trample6        = trample4 + ((char*)&a2)[1];
+       long double     trample7        = (intptr_t)trample5 + (intptr_t)trample1;
+       char            trample8        = trample6 + trample2;
+
+       dummyVar        = dummy_func(trample1, trample2, trample3, trample4,
+               trample5, trample6, trample7, trample8);
+
+       *(void**)resp = cls_pointer_fn1(a1, a2);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure      cl;
+#endif
+       ffi_closure*    pcl;
+       void*                   args[3];
+//     ffi_type                cls_pointer_type;
+       ffi_type*               arg_types[3];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap(sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+/*     cls_pointer_type.size = sizeof(void*);
+       cls_pointer_type.alignment = 0;
+       cls_pointer_type.type = FFI_TYPE_POINTER;
+       cls_pointer_type.elements = NULL;*/
+
+       void*   arg1    = (void*)0x01234567;
+       void*   arg2    = (void*)0x89abcdef;
+       ffi_arg res             = 0;
+
+       arg_types[0] = &ffi_type_pointer;
+       arg_types[1] = &ffi_type_pointer;
+       arg_types[2] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
+               arg_types) == FFI_OK);
+
+       args[0] = &arg1;
+       args[1] = &arg2;
+       args[2] = NULL;
+
+       printf("\n");
+       ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args);
+
+       printf("res: 0x%08x\n", (unsigned int) res);
+       // { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
+       // { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
+       // { dg-output "\nres: 0x8bf258bd" }
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_pointer_gn, NULL) == FFI_OK);
+
+       res = (ffi_arg)((void*(*)(void*, void*))(pcl))(arg1, arg2);
+
+       printf("res: 0x%08x\n", (unsigned int) res);
+       // { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
+       // { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
+       // { dg-output "\nres: 0x8bf258bd" }
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/err_bad_abi.c b/libffi/testsuite/libffi.call/err_bad_abi.c
new file mode 100644 (file)
index 0000000..d4e5200
--- /dev/null
@@ -0,0 +1,45 @@
+/* Area:               ffi_prep_cif, ffi_prep_closure
+   Purpose:            Test error return for bad ABIs.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/6/2007   */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* i*86-*-linux-* x86_64-*-linux-* } } */
+#include "ffitest.h"
+
+static void
+dummy_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, 
+        void** args __UNUSED__, void* userdata __UNUSED__)
+{}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args[1];
+       ffi_type* arg_types[1];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       arg_types[0] = NULL;
+       args[0] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, 255, 0, &ffi_type_void,
+               arg_types) == FFI_BAD_ABI);
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_void,
+               arg_types) == FFI_OK);
+
+       cif.abi= 255;
+
+       CHECK(ffi_prep_closure(pcl, &cif, dummy_fn, NULL) == FFI_BAD_ABI);
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/err_bad_typedef.c b/libffi/testsuite/libffi.call/err_bad_typedef.c
new file mode 100644 (file)
index 0000000..2a2e301
--- /dev/null
@@ -0,0 +1,35 @@
+/* Area:               ffi_prep_cif
+   Purpose:            Test error return for bad typedefs.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin 6/6/2007   */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* i*86-*-linux-* x86_64-*-linux-* } } */
+#include "ffitest.h"
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       ffi_type* arg_types[1];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       arg_types[0] = NULL;
+
+       ffi_type        badType = ffi_type_void;
+
+       badType.size = 0;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &badType,
+               arg_types) == FFI_BAD_TYPEDEF);
+
+       exit(0);
+}
index e73f758..8a437e4 100644 (file)
@@ -2,6 +2,8 @@
 #include <stdio.h>
 #include <string.h>
 #include <fcntl.h>
+#include <stdint.h>
+#include <inttypes.h>
 #include <ffi.h>
 #include "fficonfig.h"
 
diff --git a/libffi/testsuite/libffi.call/stret_large.c b/libffi/testsuite/libffi.call/stret_large.c
new file mode 100644 (file)
index 0000000..3327ac1
--- /dev/null
@@ -0,0 +1,153 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check structure returning with different structure size.
+                               Depending on the ABI. Check bigger struct which overlaps
+                               the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin   6/21/2007       */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+// 13 FPRs: 104 bytes
+// 14 FPRs: 112 bytes
+
+typedef struct struct_108byte {
+       double a;
+       double b;
+       double c;
+       double d;
+       double e;
+       double f;
+       double g;
+       double h;
+       double i;
+       double j;
+       double k;
+       double l;
+       double m;
+       int n;
+} struct_108byte;
+
+struct_108byte cls_struct_108byte_fn(
+       struct_108byte b0,
+       struct_108byte b1,
+       struct_108byte b2,
+       struct_108byte b3)
+{
+       struct_108byte  result;
+
+       result.a = b0.a + b1.a + b2.a + b3.a;
+       result.b = b0.b + b1.b + b2.b + b3.b;
+       result.c = b0.c + b1.c + b2.c + b3.c;
+       result.d = b0.d + b1.d + b2.d + b3.d;
+       result.e = b0.e + b1.e + b2.e + b3.e;
+       result.f = b0.f + b1.f + b2.f + b3.f;
+       result.g = b0.g + b1.g + b2.g + b3.g;
+       result.h = b0.h + b1.h + b2.h + b3.h;
+       result.i = b0.i + b1.i + b2.i + b3.i;
+       result.j = b0.j + b1.j + b2.j + b3.j;
+       result.k = b0.k + b1.k + b2.k + b3.k;
+       result.l = b0.l + b1.l + b2.l + b3.l;
+       result.m = b0.m + b1.m + b2.m + b3.m;
+       result.n = b0.n + b1.n + b2.n + b3.n;
+
+       printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
+               result.d, result.e, result.f, result.g, result.h, result.i,
+               result.j, result.k, result.l, result.m, result.n);
+
+       return result;
+}
+
+static void
+cls_struct_108byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+       struct_108byte  b0, b1, b2, b3;
+
+       b0 = *(struct_108byte*)(args[0]);
+       b1 = *(struct_108byte*)(args[1]);
+       b2 = *(struct_108byte*)(args[2]);
+       b3 = *(struct_108byte*)(args[3]);
+
+       *(struct_108byte*)resp = cls_struct_108byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args_dbl[5];
+       ffi_type* cls_struct_fields[15];
+       ffi_type cls_struct_type;
+       ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       cls_struct_type.size = 0;
+       cls_struct_type.alignment = 0;
+       cls_struct_type.type = FFI_TYPE_STRUCT;
+       cls_struct_type.elements = cls_struct_fields;
+
+       struct_108byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 7 };
+       struct_108byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 4 };
+       struct_108byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 3 };
+       struct_108byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 2 };
+       struct_108byte res_dbl;
+
+       cls_struct_fields[0] = &ffi_type_double;
+       cls_struct_fields[1] = &ffi_type_double;
+       cls_struct_fields[2] = &ffi_type_double;
+       cls_struct_fields[3] = &ffi_type_double;
+       cls_struct_fields[4] = &ffi_type_double;
+       cls_struct_fields[5] = &ffi_type_double;
+       cls_struct_fields[6] = &ffi_type_double;
+       cls_struct_fields[7] = &ffi_type_double;
+       cls_struct_fields[8] = &ffi_type_double;
+       cls_struct_fields[9] = &ffi_type_double;
+       cls_struct_fields[10] = &ffi_type_double;
+       cls_struct_fields[11] = &ffi_type_double;
+       cls_struct_fields[12] = &ffi_type_double;
+       cls_struct_fields[13] = &ffi_type_sint32;
+       cls_struct_fields[14] = NULL;
+
+       dbl_arg_types[0] = &cls_struct_type;
+       dbl_arg_types[1] = &cls_struct_type;
+       dbl_arg_types[2] = &cls_struct_type;
+       dbl_arg_types[3] = &cls_struct_type;
+       dbl_arg_types[4] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+               dbl_arg_types) == FFI_OK);
+
+       args_dbl[0] = &e_dbl;
+       args_dbl[1] = &f_dbl;
+       args_dbl[2] = &g_dbl;
+       args_dbl[3] = &h_dbl;
+       args_dbl[4] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_struct_108byte_fn), &res_dbl, args_dbl);
+       /* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+               res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_struct_108byte_gn, NULL) == FFI_OK);
+
+       res_dbl = ((struct_108byte(*)(struct_108byte, struct_108byte,
+               struct_108byte, struct_108byte))(pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+       /* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+               res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/stret_large2.c b/libffi/testsuite/libffi.call/stret_large2.c
new file mode 100644 (file)
index 0000000..8550ab1
--- /dev/null
@@ -0,0 +1,156 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check structure returning with different structure size.
+                               Depending on the ABI. Check bigger struct which overlaps
+                               the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin   6/21/2007       */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+// 13 FPRs: 104 bytes
+// 14 FPRs: 112 bytes
+
+typedef struct struct_116byte {
+       double a;
+       double b;
+       double c;
+       double d;
+       double e;
+       double f;
+       double g;
+       double h;
+       double i;
+       double j;
+       double k;
+       double l;
+       double m;
+       double n;
+       int o;
+} struct_116byte;
+
+struct_116byte cls_struct_116byte_fn(
+       struct_116byte b0,
+       struct_116byte b1,
+       struct_116byte b2,
+       struct_116byte b3)
+{
+       struct_116byte  result;
+
+       result.a = b0.a + b1.a + b2.a + b3.a;
+       result.b = b0.b + b1.b + b2.b + b3.b;
+       result.c = b0.c + b1.c + b2.c + b3.c;
+       result.d = b0.d + b1.d + b2.d + b3.d;
+       result.e = b0.e + b1.e + b2.e + b3.e;
+       result.f = b0.f + b1.f + b2.f + b3.f;
+       result.g = b0.g + b1.g + b2.g + b3.g;
+       result.h = b0.h + b1.h + b2.h + b3.h;
+       result.i = b0.i + b1.i + b2.i + b3.i;
+       result.j = b0.j + b1.j + b2.j + b3.j;
+       result.k = b0.k + b1.k + b2.k + b3.k;
+       result.l = b0.l + b1.l + b2.l + b3.l;
+       result.m = b0.m + b1.m + b2.m + b3.m;
+       result.n = b0.n + b1.n + b2.n + b3.n;
+       result.o = b0.o + b1.o + b2.o + b3.o;
+
+       printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
+               result.d, result.e, result.f, result.g, result.h, result.i,
+               result.j, result.k, result.l, result.m, result.n, result.o);
+
+       return result;
+}
+
+static void
+cls_struct_116byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+       struct_116byte  b0, b1, b2, b3;
+
+       b0 = *(struct_116byte*)(args[0]);
+       b1 = *(struct_116byte*)(args[1]);
+       b2 = *(struct_116byte*)(args[2]);
+       b3 = *(struct_116byte*)(args[3]);
+
+       *(struct_116byte*)resp = cls_struct_116byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args_dbl[5];
+       ffi_type* cls_struct_fields[16];
+       ffi_type cls_struct_type;
+       ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       cls_struct_type.size = 0;
+       cls_struct_type.alignment = 0;
+       cls_struct_type.type = FFI_TYPE_STRUCT;
+       cls_struct_type.elements = cls_struct_fields;
+
+       struct_116byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 7 };
+       struct_116byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 6.0, 4 };
+       struct_116byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 7.0, 3 };
+       struct_116byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 8.0, 2 };
+       struct_116byte res_dbl;
+
+       cls_struct_fields[0] = &ffi_type_double;
+       cls_struct_fields[1] = &ffi_type_double;
+       cls_struct_fields[2] = &ffi_type_double;
+       cls_struct_fields[3] = &ffi_type_double;
+       cls_struct_fields[4] = &ffi_type_double;
+       cls_struct_fields[5] = &ffi_type_double;
+       cls_struct_fields[6] = &ffi_type_double;
+       cls_struct_fields[7] = &ffi_type_double;
+       cls_struct_fields[8] = &ffi_type_double;
+       cls_struct_fields[9] = &ffi_type_double;
+       cls_struct_fields[10] = &ffi_type_double;
+       cls_struct_fields[11] = &ffi_type_double;
+       cls_struct_fields[12] = &ffi_type_double;
+       cls_struct_fields[13] = &ffi_type_double;
+       cls_struct_fields[14] = &ffi_type_sint32;
+       cls_struct_fields[15] = NULL;
+
+       dbl_arg_types[0] = &cls_struct_type;
+       dbl_arg_types[1] = &cls_struct_type;
+       dbl_arg_types[2] = &cls_struct_type;
+       dbl_arg_types[3] = &cls_struct_type;
+       dbl_arg_types[4] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+               dbl_arg_types) == FFI_OK);
+
+       args_dbl[0] = &e_dbl;
+       args_dbl[1] = &f_dbl;
+       args_dbl[2] = &g_dbl;
+       args_dbl[3] = &h_dbl;
+       args_dbl[4] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_struct_116byte_fn), &res_dbl, args_dbl);
+       /* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+               res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_struct_116byte_gn, NULL) == FFI_OK);
+
+       res_dbl = ((struct_116byte(*)(struct_116byte, struct_116byte,
+               struct_116byte, struct_116byte))(pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+       /* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
+               res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
+               res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/stret_medium.c b/libffi/testsuite/libffi.call/stret_medium.c
new file mode 100644 (file)
index 0000000..74863d8
--- /dev/null
@@ -0,0 +1,132 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check structure returning with different structure size.
+                               Depending on the ABI. Check bigger struct which overlaps
+                               the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin   6/21/2007       */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+typedef struct struct_72byte {
+       double a;
+       double b;
+       double c;
+       double d;
+       double e;
+       double f;
+       double g;
+       double h;
+       double i;
+} struct_72byte;
+
+struct_72byte cls_struct_72byte_fn(
+       struct_72byte b0,
+       struct_72byte b1,
+       struct_72byte b2,
+       struct_72byte b3)
+{
+       struct_72byte   result;
+
+       result.a = b0.a + b1.a + b2.a + b3.a;
+       result.b = b0.b + b1.b + b2.b + b3.b;
+       result.c = b0.c + b1.c + b2.c + b3.c;
+       result.d = b0.d + b1.d + b2.d + b3.d;
+       result.e = b0.e + b1.e + b2.e + b3.e;
+       result.f = b0.f + b1.f + b2.f + b3.f;
+       result.g = b0.g + b1.g + b2.g + b3.g;
+       result.h = b0.h + b1.h + b2.h + b3.h;
+       result.i = b0.i + b1.i + b2.i + b3.i;
+
+       printf("%g %g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
+               result.d, result.e, result.f, result.g, result.h, result.i);
+
+       return result;
+}
+
+static void
+cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+       struct_72byte   b0, b1, b2, b3;
+
+       b0 = *(struct_72byte*)(args[0]);
+       b1 = *(struct_72byte*)(args[1]);
+       b2 = *(struct_72byte*)(args[2]);
+       b3 = *(struct_72byte*)(args[3]);
+
+       *(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args_dbl[5];
+       ffi_type* cls_struct_fields[10];
+       ffi_type cls_struct_type;
+       ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       cls_struct_type.size = 0;
+       cls_struct_type.alignment = 0;
+       cls_struct_type.type = FFI_TYPE_STRUCT;
+       cls_struct_type.elements = cls_struct_fields;
+
+       struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7.0 };
+       struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0 };
+       struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3.0 };
+       struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2.0 };
+       struct_72byte res_dbl;
+
+       cls_struct_fields[0] = &ffi_type_double;
+       cls_struct_fields[1] = &ffi_type_double;
+       cls_struct_fields[2] = &ffi_type_double;
+       cls_struct_fields[3] = &ffi_type_double;
+       cls_struct_fields[4] = &ffi_type_double;
+       cls_struct_fields[5] = &ffi_type_double;
+       cls_struct_fields[6] = &ffi_type_double;
+       cls_struct_fields[7] = &ffi_type_double;
+       cls_struct_fields[8] = &ffi_type_double;
+       cls_struct_fields[9] = NULL;
+
+       dbl_arg_types[0] = &cls_struct_type;
+       dbl_arg_types[1] = &cls_struct_type;
+       dbl_arg_types[2] = &cls_struct_type;
+       dbl_arg_types[3] = &cls_struct_type;
+       dbl_arg_types[4] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+               dbl_arg_types) == FFI_OK);
+
+       args_dbl[0] = &e_dbl;
+       args_dbl[1] = &f_dbl;
+       args_dbl[2] = &g_dbl;
+       args_dbl[3] = &h_dbl;
+       args_dbl[4] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
+       /* { dg-output "22 15 17 25 6 13 19 18 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+               res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_struct_72byte_gn, NULL) == FFI_OK);
+
+       res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
+               struct_72byte, struct_72byte))(pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+       /* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
+               res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+       exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/stret_medium2.c b/libffi/testsuite/libffi.call/stret_medium2.c
new file mode 100644 (file)
index 0000000..6319982
--- /dev/null
@@ -0,0 +1,132 @@
+/* Area:               ffi_call, closure_call
+   Purpose:            Check structure returning with different structure size.
+                               Depending on the ABI. Check bigger struct which overlaps
+                               the gp and fp register count on Darwin/AIX/ppc64.
+   Limitations:        none.
+   PR:                 none.
+   Originator: Blake Chaffin   6/21/2007       */
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-*  } } */
+#include "ffitest.h"
+
+typedef struct struct_72byte {
+       double a;
+       double b;
+       double c;
+       double d;
+       double e;
+       double f;
+       double g;
+       double h;
+       long long i;
+} struct_72byte;
+
+struct_72byte cls_struct_72byte_fn(
+       struct_72byte b0,
+       struct_72byte b1,
+       struct_72byte b2,
+       struct_72byte b3)
+{
+       struct_72byte   result;
+
+       result.a = b0.a + b1.a + b2.a + b3.a;
+       result.b = b0.b + b1.b + b2.b + b3.b;
+       result.c = b0.c + b1.c + b2.c + b3.c;
+       result.d = b0.d + b1.d + b2.d + b3.d;
+       result.e = b0.e + b1.e + b2.e + b3.e;
+       result.f = b0.f + b1.f + b2.f + b3.f;
+       result.g = b0.g + b1.g + b2.g + b3.g;
+       result.h = b0.h + b1.h + b2.h + b3.h;
+       result.i = b0.i + b1.i + b2.i + b3.i;
+
+       printf("%g %g %g %g %g %g %g %g %lld\n", result.a, result.b, result.c,
+               result.d, result.e, result.f, result.g, result.h, result.i);
+
+       return result;
+}
+
+static void
+cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
+{
+       struct_72byte   b0, b1, b2, b3;
+
+       b0 = *(struct_72byte*)(args[0]);
+       b1 = *(struct_72byte*)(args[1]);
+       b2 = *(struct_72byte*)(args[2]);
+       b3 = *(struct_72byte*)(args[3]);
+
+       *(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
+}
+
+int main (void)
+{
+       ffi_cif cif;
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+       void* args_dbl[5];
+       ffi_type* cls_struct_fields[10];
+       ffi_type cls_struct_type;
+       ffi_type* dbl_arg_types[5];
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap (sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       cls_struct_type.size = 0;
+       cls_struct_type.alignment = 0;
+       cls_struct_type.type = FFI_TYPE_STRUCT;
+       cls_struct_type.elements = cls_struct_fields;
+
+       struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7 };
+       struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4 };
+       struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3 };
+       struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2 };
+       struct_72byte res_dbl;
+
+       cls_struct_fields[0] = &ffi_type_double;
+       cls_struct_fields[1] = &ffi_type_double;
+       cls_struct_fields[2] = &ffi_type_double;
+       cls_struct_fields[3] = &ffi_type_double;
+       cls_struct_fields[4] = &ffi_type_double;
+       cls_struct_fields[5] = &ffi_type_double;
+       cls_struct_fields[6] = &ffi_type_double;
+       cls_struct_fields[7] = &ffi_type_double;
+       cls_struct_fields[8] = &ffi_type_sint64;
+       cls_struct_fields[9] = NULL;
+
+       dbl_arg_types[0] = &cls_struct_type;
+       dbl_arg_types[1] = &cls_struct_type;
+       dbl_arg_types[2] = &cls_struct_type;
+       dbl_arg_types[3] = &cls_struct_type;
+       dbl_arg_types[4] = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
+               dbl_arg_types) == FFI_OK);
+
+       args_dbl[0] = &e_dbl;
+       args_dbl[1] = &f_dbl;
+       args_dbl[2] = &g_dbl;
+       args_dbl[3] = &h_dbl;
+       args_dbl[4] = NULL;
+
+       ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
+       /* { dg-output "22 15 17 25 6 13 19 18 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %lld\n", res_dbl.a, res_dbl.b, res_dbl.c,
+               res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_struct_72byte_gn, NULL) == FFI_OK);
+
+       res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
+               struct_72byte, struct_72byte))(pcl))(e_dbl, f_dbl, g_dbl, h_dbl);
+       /* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
+       printf("res: %g %g %g %g %g %g %g %g %lld\n", res_dbl.a, res_dbl.b, res_dbl.c,
+               res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
+       /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
+
+       exit(0);
+}