2008-03-04 Anthony Green <green@redhat.com>
authorgreen <green>
Wed, 5 Mar 2008 00:07:02 +0000 (00:07 +0000)
committergreen <green>
Wed, 5 Mar 2008 00:07:02 +0000 (00:07 +0000)
            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/huge_struct.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.

16 files changed:
libffi/ChangeLog.libffi
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_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/huge_struct.c [new file with mode: 0644]
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 5c1ab7a..b4ec63f 100644 (file)
@@ -1,3 +1,23 @@
+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/huge_struct.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.
+
 2008-02-26  Jakub Jelinek  <jakub@redhat.com>
             Anthony Green  <green@redhat.com>
 
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..90ae259
--- /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*-*-* } } */
+/* { 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..55f0d85
--- /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*-*-* } } */
+/* { 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);
+}
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..8f572c0
--- /dev/null
@@ -0,0 +1,74 @@
+/* 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,void* resp,void** args, void* userdata)
+{
+       closure_test_fn(*(Dbls*)args[0]);
+}
+
+int main(int argc, char** argv)
+{
+       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" } */
+
+       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..f14f86f
--- /dev/null
@@ -0,0 +1,63 @@
+/* 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, void* resp, void** args, void* userdata)
+{
+       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", 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", 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..ae2b608
--- /dev/null
@@ -0,0 +1,110 @@
+/* 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*-*-* } } */
+/* { 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, void* resp, void** args, void* userdata)
+{
+       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..41ee034
--- /dev/null
@@ -0,0 +1,63 @@
+/* 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*-*-* } } */
+#include "ffitest.h"
+
+static void
+cls_longdouble_va_fn(ffi_cif* cif, void* resp, void** args, void* userdata)
+{
+       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" }
+       printf("res: %d\n", res);
+       // { dg-output "\nres: 4" }
+
+       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", 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..6612bbb
--- /dev/null
@@ -0,0 +1,78 @@
+/* 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*)((long)a1 + (long)a2);
+
+       printf("0x%08x 0x%08x: 0x%08x\n", a1, a2, result);
+
+       return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif, void* resp, void** args, void* userdata)
+{
+       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", 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", 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..5e3575a
--- /dev/null
@@ -0,0 +1,141 @@
+/* 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        = (long)a1 + (long)a2;
+       char            trample2        = ((char*)&a1)[0] + ((char*)&a2)[0];
+       long double     trample3        = (long)trample1 + (long)a1;
+       char            trample4        = trample2 + ((char*)&a1)[1];
+       long double     trample5        = (long)trample3 + (long)a2;
+       char            trample6        = trample4 + ((char*)&a2)[1];
+       long double     trample7        = (long)trample5 + (long)trample1;
+       char            trample8        = trample6 + trample2;
+
+       dummyVar        = dummy_func(trample1, trample2, trample3, trample4,
+               trample5, trample6, trample7, trample8);
+
+       void*   result  = (void*)((long)a1 + (long)a2);
+
+       printf("0x%08x 0x%08x: 0x%08x\n", a1, a2, result);
+
+       return result;
+}
+
+void* cls_pointer_fn1(void* a1, void* a2)
+{
+       long double     trample1        = (long)a1 + (long)a2;
+       char            trample2        = ((char*)&a1)[0] + ((char*)&a2)[0];
+       long double     trample3        = (long)trample1 + (long)a1;
+       char            trample4        = trample2 + ((char*)&a1)[1];
+       long double     trample5        = (long)trample3 + (long)a2;
+       char            trample6        = trample4 + ((char*)&a2)[1];
+       long double     trample7        = (long)trample5 + (long)trample1;
+       char            trample8        = trample6 + trample2;
+
+       dummyVar        = dummy_func(trample1, trample2, trample3, trample4,
+               trample5, trample6, trample7, trample8);
+
+       void*   result  = (void*)((long)a1 + (long)a2);
+
+       printf("0x%08x 0x%08x: 0x%08x\n", a1, a2, result);
+
+       result  = cls_pointer_fn2(result, a1);
+
+       return result;
+}
+
+static void
+cls_pointer_gn(ffi_cif* cif, void* resp, void** args, void* userdata)
+{
+       void*   a1      = *(void**)(args[0]);
+       void*   a2      = *(void**)(args[1]);
+
+       long double     trample1        = (long)a1 + (long)a2;
+       char            trample2        = ((char*)&a1)[0] + ((char*)&a2)[0];
+       long double     trample3        = (long)trample1 + (long)a1;
+       char            trample4        = trample2 + ((char*)&a1)[1];
+       long double     trample5        = (long)trample3 + (long)a2;
+       char            trample6        = trample4 + ((char*)&a2)[1];
+       long double     trample7        = (long)trample5 + (long)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", 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", 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..9e22e33
--- /dev/null
@@ -0,0 +1,44 @@
+/* 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*-*-* } } */
+#include "ffitest.h"
+
+static void
+dummy_fn(ffi_cif* cif, void* resp, void** args, void* userdata)
+{}
+
+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..97128c3
--- /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*-*-* } } */
+#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);
+}
diff --git a/libffi/testsuite/libffi.call/huge_struct.c b/libffi/testsuite/libffi.call/huge_struct.c
new file mode 100644 (file)
index 0000000..3ec4875
--- /dev/null
@@ -0,0 +1,348 @@
+/*     Area:                   ffi_call, closure_call
+       Purpose:                Check large structure returns.
+       Limitations:    none.
+       PR:                             none.
+       Originator:             Blake Chaffin   6/18/2007
+*/
+
+/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+/* { dg-options -mlong-double-128 { target powerpc64*-*-* } } */
+
+#include <stdint.h>
+
+#include "ffitest.h"
+
+typedef        struct BigStruct{
+       uint8_t         a;
+       int8_t          b;
+       uint16_t        c;
+       int16_t         d;
+       uint32_t        e;
+       int32_t         f;
+       uint64_t        g;
+       int64_t         h;
+       float           i;
+       double          j;
+       long double     k;
+       char*           l;
+       uint8_t         m;
+       int8_t          n;
+       uint16_t        o;
+       int16_t         p;
+       uint32_t        q;
+       int32_t         r;
+       uint64_t        s;
+       int64_t         t;
+       float           u;
+       double          v;
+       long double     w;
+       char*           x;
+       uint8_t         y;
+       int8_t          z;
+       uint16_t        aa;
+       int16_t         bb;
+       uint32_t        cc;
+       int32_t         dd;
+       uint64_t        ee;
+       int64_t         ff;
+       float           gg;
+       double          hh;
+       long double     ii;
+       char*           jj;
+       uint8_t         kk;
+       int8_t          ll;
+       uint16_t        mm;
+       int16_t         nn;
+       uint32_t        oo;
+       int32_t         pp;
+       uint64_t        qq;
+       int64_t         rr;
+       float           ss;
+       double          tt;
+       long double     uu;
+       char*           vv;
+       uint8_t         ww;
+       int8_t          xx;
+} BigStruct;
+
+BigStruct
+test_large_fn(
+       uint8_t         ui8_1,
+       int8_t          si8_1,
+       uint16_t        ui16_1,
+       int16_t         si16_1,
+       uint32_t        ui32_1,
+       int32_t         si32_1,
+       uint64_t        ui64_1,
+       int64_t         si64_1,
+       float           f_1,
+       double          d_1,
+       long double     ld_1,
+       char*           p_1,
+       uint8_t         ui8_2,
+       int8_t          si8_2,
+       uint16_t        ui16_2,
+       int16_t         si16_2,
+       uint32_t        ui32_2,
+       int32_t         si32_2,
+       uint64_t        ui64_2,
+       int64_t         si64_2,
+       float           f_2,
+       double          d_2,
+       long double     ld_2,
+       char*           p_2,
+       uint8_t         ui8_3,
+       int8_t          si8_3,
+       uint16_t        ui16_3,
+       int16_t         si16_3,
+       uint32_t        ui32_3,
+       int32_t         si32_3,
+       uint64_t        ui64_3,
+       int64_t         si64_3,
+       float           f_3,
+       double          d_3,
+       long double     ld_3,
+       char*           p_3,
+       uint8_t         ui8_4,
+       int8_t          si8_4,
+       uint16_t        ui16_4,
+       int16_t         si16_4,
+       uint32_t        ui32_4,
+       int32_t         si32_4,
+       uint64_t        ui64_4,
+       int64_t         si64_4,
+       float           f_4,
+       double          d_4,
+       long double     ld_4,
+       char*           p_4,
+       uint8_t         ui8_5,
+       int8_t          si8_5)
+{
+       BigStruct       retVal  = {
+               ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1, ui32_1 + 1, si32_1 + 1,
+                       ui64_1 + 1, si64_1 + 1, f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((long)p_1 + 1), 
+               ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2, ui32_2 + 2, si32_2 + 2,
+                       ui64_2 + 2, si64_2 + 2, f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((long)p_2 + 2), 
+               ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3, ui32_3 + 3, si32_3 + 3,
+                       ui64_3 + 3, si64_3 + 3, f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((long)p_3 + 3), 
+               ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4, ui32_4 + 4, si32_4 + 4,
+                       ui64_4 + 4, si64_4 + 4, f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((long)p_4 + 4), 
+               ui8_5 + 5, si8_5 + 5};
+
+       printf("%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd: "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd\n",
+               ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
+               ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
+               ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
+               ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4, ui8_5, si8_5,
+               retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+               retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, retVal.l,
+               retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+               retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, retVal.x,
+               retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+               retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, retVal.jj,
+               retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+               retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, retVal.vv, retVal.ww, retVal.xx);
+
+       return  retVal;
+}
+
+static void
+cls_large_fn(ffi_cif* cif, void* resp, void** args, void* userdata)
+{
+       uint8_t         ui8_1   = *(uint8_t*)args[0];
+       int8_t          si8_1   = *(int8_t*)args[1];
+       uint16_t        ui16_1  = *(uint16_t*)args[2];
+       int16_t         si16_1  = *(int16_t*)args[3];
+       uint32_t        ui32_1  = *(uint32_t*)args[4];
+       int32_t         si32_1  = *(int32_t*)args[5];
+       uint64_t        ui64_1  = *(uint64_t*)args[6];
+       int64_t         si64_1  = *(int64_t*)args[7];
+       float           f_1             = *(float*)args[8];
+       double          d_1             = *(double*)args[9];
+       long double     ld_1    = *(long double*)args[10];
+       char*           p_1             = *(char**)args[11];
+       uint8_t         ui8_2   = *(uint8_t*)args[12];
+       int8_t          si8_2   = *(int8_t*)args[13];
+       uint16_t        ui16_2  = *(uint16_t*)args[14];
+       int16_t         si16_2  = *(int16_t*)args[15];
+       uint32_t        ui32_2  = *(uint32_t*)args[16];
+       int32_t         si32_2  = *(int32_t*)args[17];
+       uint64_t        ui64_2  = *(uint64_t*)args[18];
+       int64_t         si64_2  = *(int64_t*)args[19];
+       float           f_2             = *(float*)args[20];
+       double          d_2             = *(double*)args[21];
+       long double     ld_2    = *(long double*)args[22];
+       char*           p_2             = *(char**)args[23];
+       uint8_t         ui8_3   = *(uint8_t*)args[24];
+       int8_t          si8_3   = *(int8_t*)args[25];
+       uint16_t        ui16_3  = *(uint16_t*)args[26];
+       int16_t         si16_3  = *(int16_t*)args[27];
+       uint32_t        ui32_3  = *(uint32_t*)args[28];
+       int32_t         si32_3  = *(int32_t*)args[29];
+       uint64_t        ui64_3  = *(uint64_t*)args[30];
+       int64_t         si64_3  = *(int64_t*)args[31];
+       float           f_3             = *(float*)args[32];
+       double          d_3             = *(double*)args[33];
+       long double     ld_3    = *(long double*)args[34];
+       char*           p_3             = *(char**)args[35];
+       uint8_t         ui8_4   = *(uint8_t*)args[36];
+       int8_t          si8_4   = *(int8_t*)args[37];
+       uint16_t        ui16_4  = *(uint16_t*)args[38];
+       int16_t         si16_4  = *(int16_t*)args[39];
+       uint32_t        ui32_4  = *(uint32_t*)args[40];
+       int32_t         si32_4  = *(int32_t*)args[41];
+       uint64_t        ui64_4  = *(uint64_t*)args[42];
+       int64_t         si64_4  = *(int64_t*)args[43];
+       float           f_4             = *(float*)args[44];
+       double          d_4             = *(double*)args[45];
+       long double     ld_4    = *(long double*)args[46];
+       char*           p_4             = *(char**)args[47];
+       uint8_t         ui8_5   = *(uint8_t*)args[48];
+       int8_t          si8_5   = *(int8_t*)args[49];
+
+       *(BigStruct*)resp = test_large_fn(
+               ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
+               ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
+               ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
+               ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4,
+               ui8_5, si8_5);
+}
+
+int
+main(int argc, const char** argv)
+{
+#ifndef USING_MMAP
+       static ffi_closure cl;
+#endif
+       ffi_closure *pcl;
+
+#ifdef USING_MMAP
+       pcl = allocate_mmap(sizeof(ffi_closure));
+#else
+       pcl = &cl;
+#endif
+
+       ffi_cif         cif;
+       ffi_type*       argTypes[51];
+       void*           argValues[51];
+
+       ffi_type        ret_struct_type;
+       ffi_type*       st_fields[51];
+       BigStruct       retVal  = {0};
+
+       ret_struct_type.size = 0;
+       ret_struct_type.alignment = 0;
+       ret_struct_type.type = FFI_TYPE_STRUCT;
+       ret_struct_type.elements = st_fields;
+
+       st_fields[0]    = st_fields[12] = st_fields[24] = st_fields[36] = st_fields[48] = &ffi_type_uint8;
+       st_fields[1]    = st_fields[13] = st_fields[25] = st_fields[37] = st_fields[49] = &ffi_type_sint8;
+       st_fields[2]    = st_fields[14] = st_fields[26] = st_fields[38] = &ffi_type_uint16;
+       st_fields[3]    = st_fields[15] = st_fields[27] = st_fields[39] = &ffi_type_sint16;
+       st_fields[4]    = st_fields[16] = st_fields[28] = st_fields[40] = &ffi_type_uint32;
+       st_fields[5]    = st_fields[17] = st_fields[29] = st_fields[41] = &ffi_type_sint32;
+       st_fields[6]    = st_fields[18] = st_fields[30] = st_fields[42] = &ffi_type_uint64;
+       st_fields[7]    = st_fields[19] = st_fields[31] = st_fields[43] = &ffi_type_sint64;
+       st_fields[8]    = st_fields[20] = st_fields[32] = st_fields[44] = &ffi_type_float;
+       st_fields[9]    = st_fields[21] = st_fields[33] = st_fields[45] = &ffi_type_double;
+       st_fields[10]   = st_fields[22] = st_fields[34] = st_fields[46] = &ffi_type_longdouble;
+       st_fields[11]   = st_fields[23] = st_fields[35] = st_fields[47] = &ffi_type_pointer;
+
+       st_fields[50] = NULL;
+
+       uint8_t         ui8             = 1;
+       int8_t          si8             = 2;
+       uint16_t        ui16    = 3;
+       int16_t         si16    = 4;
+       uint32_t        ui32    = 5;
+       int32_t         si32    = 6;
+       uint64_t        ui64    = 7;
+       int64_t         si64    = 8;
+       float           f               = 9;
+       double          d               = 10;
+       long double     ld              = 11;
+       char*           p               = (char*)0x12345678;
+
+       argTypes[0]             = argTypes[12]  = argTypes[24]  = argTypes[36]  = argTypes[48]  = &ffi_type_uint8;
+       argValues[0]    = argValues[12] = argValues[24] = argValues[36] = argValues[48] = &ui8;
+       argTypes[1]             = argTypes[13]  = argTypes[25]  = argTypes[37]  = argTypes[49]  = &ffi_type_sint8;
+       argValues[1]    = argValues[13] = argValues[25] = argValues[37] = argValues[49] = &si8;
+       argTypes[2]             = argTypes[14]  = argTypes[26]  = argTypes[38]  = &ffi_type_uint16;
+       argValues[2]    = argValues[14] = argValues[26] = argValues[38] = &ui16;
+       argTypes[3]             = argTypes[15]  = argTypes[27]  = argTypes[39]  = &ffi_type_sint16;
+       argValues[3]    = argValues[15] = argValues[27] = argValues[39] = &si16;
+       argTypes[4]             = argTypes[16]  = argTypes[28]  = argTypes[40]  = &ffi_type_uint32;
+       argValues[4]    = argValues[16] = argValues[28] = argValues[40] = &ui32;
+       argTypes[5]             = argTypes[17]  = argTypes[29]  = argTypes[41]  = &ffi_type_sint32;
+       argValues[5]    = argValues[17] = argValues[29] = argValues[41] = &si32;
+       argTypes[6]             = argTypes[18]  = argTypes[30]  = argTypes[42]  = &ffi_type_uint64;
+       argValues[6]    = argValues[18] = argValues[30] = argValues[42] = &ui64;
+       argTypes[7]             = argTypes[19]  = argTypes[31]  = argTypes[43]  = &ffi_type_sint64;
+       argValues[7]    = argValues[19] = argValues[31] = argValues[43] = &si64;
+       argTypes[8]             = argTypes[20]  = argTypes[32]  = argTypes[44]  = &ffi_type_float;
+       argValues[8]    = argValues[20] = argValues[32] = argValues[44] = &f;
+       argTypes[9]             = argTypes[21]  = argTypes[33]  = argTypes[45]  = &ffi_type_double;
+       argValues[9]    = argValues[21] = argValues[33] = argValues[45] = &d;
+       argTypes[10]    = argTypes[22]  = argTypes[34]  = argTypes[46]  = &ffi_type_longdouble;
+       argValues[10]   = argValues[22] = argValues[34] = argValues[46] = &ld;
+       argTypes[11]    = argTypes[23]  = argTypes[35]  = argTypes[47]  = &ffi_type_pointer;
+       argValues[11]   = argValues[23] = argValues[35] = argValues[47] = &p;
+
+       argTypes[50]    = NULL;
+       argValues[50]   = NULL;
+
+       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 50, &ret_struct_type, argTypes) == FFI_OK);
+
+       ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues);
+       // { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+       printf("res: %hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd\n",
+               retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+               retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, retVal.l,
+               retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+               retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, retVal.x,
+               retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+               retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, retVal.jj,
+               retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+               retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, retVal.vv, retVal.ww, retVal.xx);
+       // { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+
+       CHECK(ffi_prep_closure(pcl, &cif, cls_large_fn, NULL) == FFI_OK);
+
+       retVal  = ((BigStruct(*)(
+               uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+               uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+               uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+               uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
+               uint8_t, int8_t))(pcl))(
+               ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+               ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+               ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+               ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
+               ui8, si8);
+       // { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+       printf("res: %hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
+               "%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd\n",
+               retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
+               retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, retVal.l,
+               retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
+               retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, retVal.x,
+               retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
+               retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, retVal.jj,
+               retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
+               retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, retVal.vv, retVal.ww, retVal.xx);
+       // { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
+
+    return 0;
+}
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..f8e04b8
--- /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, void* resp, void** args, void* userdata)
+{
+       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..6ad0151
--- /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, void* resp, void** args, void* userdata)
+{
+       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..fc0a5ef
--- /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, void* resp, void** args, void* userdata)
+{
+       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..73cf826
--- /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, void* resp, void** args, void* userdata)
+{
+       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);
+}