summaryrefslogtreecommitdiff
path: root/libffi
diff options
context:
space:
mode:
authorandreast <andreast@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-16 21:03:16 +0000
committerandreast <andreast@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-16 21:03:16 +0000
commit019a3b64718b836ca6dc219c251a48536a57990f (patch)
tree47c1bfaa187a86c4f186f486eb0f9abb5da3d334 /libffi
parent911686dc1c962d2f764ca375e8112ea206166e92 (diff)
downloadgcc-019a3b64718b836ca6dc219c251a48536a57990f.tar.gz
2006-02-16 Andreas Tobler <a.tobler@schweiz.ch>
* testsuite/libffi.call/nested_struct2.c: Remove ffi_type_mylong definition. * testsuite/libffi.call/ffitest.h: Add ffi_type_mylong definition here to be used by other test cases too. * testsuite/libffi.call/nested_struct10.c: New test case. * testsuite/libffi.call/nested_struct9.c: Likewise. * testsuite/libffi.call/nested_struct8.c: Likewise. * testsuite/libffi.call/nested_struct7.c: Likewise. * testsuite/libffi.call/nested_struct6.c: Likewise. * testsuite/libffi.call/nested_struct5.c: Likewise. * testsuite/libffi.call/nested_struct4.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111151 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi')
-rw-r--r--libffi/ChangeLog15
-rw-r--r--libffi/testsuite/libffi.call/ffitest.h10
-rw-r--r--libffi/testsuite/libffi.call/nested_struct10.c141
-rw-r--r--libffi/testsuite/libffi.call/nested_struct2.c12
-rw-r--r--libffi/testsuite/libffi.call/nested_struct4.c119
-rw-r--r--libffi/testsuite/libffi.call/nested_struct5.c120
-rw-r--r--libffi/testsuite/libffi.call/nested_struct6.c139
-rw-r--r--libffi/testsuite/libffi.call/nested_struct7.c119
-rw-r--r--libffi/testsuite/libffi.call/nested_struct8.c139
-rw-r--r--libffi/testsuite/libffi.call/nested_struct9.c139
10 files changed, 942 insertions, 11 deletions
diff --git a/libffi/ChangeLog b/libffi/ChangeLog
index 9f883588a55..737b5662612 100644
--- a/libffi/ChangeLog
+++ b/libffi/ChangeLog
@@ -1,3 +1,18 @@
+2006-02-16 Andreas Tobler <a.tobler@schweiz.ch>
+
+ * testsuite/libffi.call/nested_struct2.c: Remove ffi_type_mylong
+ definition.
+ * testsuite/libffi.call/ffitest.h: Add ffi_type_mylong definition
+ here to be used by other test cases too.
+
+ * testsuite/libffi.call/nested_struct10.c: New test case.
+ * testsuite/libffi.call/nested_struct9.c: Likewise.
+ * testsuite/libffi.call/nested_struct8.c: Likewise.
+ * testsuite/libffi.call/nested_struct7.c: Likewise.
+ * testsuite/libffi.call/nested_struct6.c: Likewise.
+ * testsuite/libffi.call/nested_struct5.c: Likewise.
+ * testsuite/libffi.call/nested_struct4.c: Likewise.
+
2006-01-21 Andreas Tobler <a.tobler@schweiz.ch>
* configure.ac: Enable libffi for sparc64-*-freebsd*.
diff --git a/libffi/testsuite/libffi.call/ffitest.h b/libffi/testsuite/libffi.call/ffitest.h
index b41e14b8f84..45c0564966f 100644
--- a/libffi/testsuite/libffi.call/ffitest.h
+++ b/libffi/testsuite/libffi.call/ffitest.h
@@ -9,6 +9,16 @@
#define CHECK(x) !(x) ? abort() : 0
+/* Define our own long for easier handling on multilib targets. */
+#if LONG_MAX == 2147483647
+#define ffi_type_mylong ffi_type_uint32
+#else
+#if LONG_MAX == 9223372036854775807
+#define ffi_type_mylong ffi_type_uint64
+#else
+#error "Error, size LONG not defined as expected"
+#endif
+#endif
/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
file open. */
diff --git a/libffi/testsuite/libffi.call/nested_struct10.c b/libffi/testsuite/libffi.call/nested_struct10.c
new file mode 100644
index 00000000000..37897d018c1
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct10.c
@@ -0,0 +1,141 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ unsigned long long a;
+ unsigned char b;
+} A;
+
+typedef struct B {
+ unsigned char y;
+ struct A x;
+ unsigned int z;
+} B;
+
+typedef struct C {
+ unsigned long long d;
+ unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a + b3.z + b4.d;
+ result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+ result.y = b2.b + b3.x.b + b4.e;
+
+ printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+ (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e,
+ (int)result.x.a, result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+ struct C b2;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+ b2 = *(struct C*)(args[2]);
+
+ *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+#ifndef USING_MMAP
+ static ffi_closure cl;
+#endif
+ ffi_closure *pcl;
+ void* args_dbl[4];
+ ffi_type* cls_struct_fields[3];
+ ffi_type* cls_struct_fields1[4];
+ ffi_type* cls_struct_fields2[3];
+ ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+ ffi_type* dbl_arg_types[4];
+
+#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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ cls_struct_type2.size = 0;
+ cls_struct_type2.alignment = 0;
+ cls_struct_type2.type = FFI_TYPE_STRUCT;
+ cls_struct_type2.elements = cls_struct_fields2;
+
+ struct A e_dbl = { 1LL, 7};
+ struct B f_dbl = { 99, {12LL , 127}, 255};
+ struct C g_dbl = { 2LL, 9};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_uint64;
+ cls_struct_fields[1] = &ffi_type_uchar;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &ffi_type_uchar;
+ cls_struct_fields1[1] = &cls_struct_type;
+ cls_struct_fields1[2] = &ffi_type_uint32;
+ cls_struct_fields1[3] = NULL;
+
+ cls_struct_fields2[0] = &ffi_type_uint64;
+ cls_struct_fields2[1] = &ffi_type_uchar;
+ cls_struct_fields2[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = &cls_struct_type2;
+ dbl_arg_types[3] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = &g_dbl;
+ args_dbl[3] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99 255 2 9: 270 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+ /* { dg-output "\n1 7 12 127 99 255 2 9: 270 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/nested_struct2.c b/libffi/testsuite/libffi.call/nested_struct2.c
index 907fe897d6d..2972422ad2e 100644
--- a/libffi/testsuite/libffi.call/nested_struct2.c
+++ b/libffi/testsuite/libffi.call/nested_struct2.c
@@ -9,16 +9,6 @@
/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
#include "ffitest.h"
-#if LONG_MAX == 2147483647
-#define ffi_type_mylong ffi_type_uint32
-#else
-#if LONG_MAX == 9223372036854775807
-#define ffi_type_mylong ffi_type_uint64
-#else
-#error "Error, size LONG not defined as expected"
-#endif
-#endif
-
typedef struct A {
unsigned long a;
unsigned char b;
@@ -115,7 +105,6 @@ int main (void)
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
-
CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
@@ -123,5 +112,6 @@ int main (void)
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
exit(0);
}
diff --git a/libffi/testsuite/libffi.call/nested_struct4.c b/libffi/testsuite/libffi.call/nested_struct4.c
new file mode 100644
index 00000000000..d6e21d6c0ce
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct4.c
@@ -0,0 +1,119 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ double a;
+ unsigned char b;
+} A;
+
+typedef struct B {
+ struct A x;
+ unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a;
+ result.x.b = b2.b + b3.x.b + b3.y;
+ result.y = b2.b + b3.x.b;
+
+ printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+ (int)b3.x.a, b3.x.b, b3.y,
+ (int)result.x.a, result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+
+ *(B*)resp = B_fn(b0, b1);
+}
+
+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[3];
+ ffi_type* cls_struct_fields1[3];
+ ffi_type cls_struct_type, cls_struct_type1;
+ 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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ struct A e_dbl = { 1.0, 7};
+ struct B f_dbl = {{12.0 , 127}, 99};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_double;
+ cls_struct_fields[1] = &ffi_type_uchar;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &cls_struct_type;
+ cls_struct_fields1[1] = &ffi_type_uchar;
+ cls_struct_fields1[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99: 13 233 134" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+ /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/nested_struct5.c b/libffi/testsuite/libffi.call/nested_struct5.c
new file mode 100644
index 00000000000..79d67eedf61
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct5.c
@@ -0,0 +1,120 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ long double a;
+ unsigned char b;
+} A;
+
+typedef struct B {
+ struct A x;
+ unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a;
+ result.x.b = b2.b + b3.x.b + b3.y;
+ result.y = b2.b + b3.x.b;
+
+ printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+ (int)b3.x.a, b3.x.b, b3.y,
+ (int)result.x.a, result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+
+ *(B*)resp = B_fn(b0, b1);
+}
+
+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[3];
+ ffi_type* cls_struct_fields1[3];
+ ffi_type cls_struct_type, cls_struct_type1;
+ 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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ struct A e_dbl = { 1.0, 7};
+ struct B f_dbl = {{12.0 , 127}, 99};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_longdouble;
+ cls_struct_fields[1] = &ffi_type_uchar;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &cls_struct_type;
+ cls_struct_fields1[1] = &ffi_type_uchar;
+ cls_struct_fields1[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99: 13 233 134" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+ /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/nested_struct6.c b/libffi/testsuite/libffi.call/nested_struct6.c
new file mode 100644
index 00000000000..feb58b33234
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct6.c
@@ -0,0 +1,139 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ double a;
+ unsigned char b;
+} A;
+
+typedef struct B {
+ struct A x;
+ unsigned char y;
+} B;
+
+typedef struct C {
+ long d;
+ unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a + b4.d;
+ result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+ result.y = b2.b + b3.x.b + b4.e;
+
+ printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+ (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+ (int)result.x.a, result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+ struct C b2;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+ b2 = *(struct C*)(args[2]);
+
+ *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+#ifndef USING_MMAP
+ static ffi_closure cl;
+#endif
+ ffi_closure *pcl;
+ void* args_dbl[4];
+ ffi_type* cls_struct_fields[3];
+ ffi_type* cls_struct_fields1[3];
+ ffi_type* cls_struct_fields2[3];
+ ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+ ffi_type* dbl_arg_types[4];
+
+#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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ cls_struct_type2.size = 0;
+ cls_struct_type2.alignment = 0;
+ cls_struct_type2.type = FFI_TYPE_STRUCT;
+ cls_struct_type2.elements = cls_struct_fields2;
+
+ struct A e_dbl = { 1.0, 7};
+ struct B f_dbl = {{12.0 , 127}, 99};
+ struct C g_dbl = { 2, 9};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_double;
+ cls_struct_fields[1] = &ffi_type_uchar;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &cls_struct_type;
+ cls_struct_fields1[1] = &ffi_type_uchar;
+ cls_struct_fields1[2] = NULL;
+
+ cls_struct_fields2[0] = &ffi_type_mylong;
+ cls_struct_fields2[1] = &ffi_type_uchar;
+ cls_struct_fields2[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = &cls_struct_type2;
+ dbl_arg_types[3] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = &g_dbl;
+ args_dbl[3] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+ /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/nested_struct7.c b/libffi/testsuite/libffi.call/nested_struct7.c
new file mode 100644
index 00000000000..fa745de7380
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct7.c
@@ -0,0 +1,119 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ unsigned long long a;
+ unsigned char b;
+} A;
+
+typedef struct B {
+ struct A x;
+ unsigned char y;
+} B;
+
+static B B_fn(struct A b2, struct B b3)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a;
+ result.x.b = b2.b + b3.x.b + b3.y;
+ result.y = b2.b + b3.x.b;
+
+ printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+ (int)b3.x.a, b3.x.b, b3.y,
+ (int)result.x.a, result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+
+ *(B*)resp = B_fn(b0, b1);
+}
+
+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[3];
+ ffi_type* cls_struct_fields1[3];
+ ffi_type cls_struct_type, cls_struct_type1;
+ 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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ struct A e_dbl = { 1LL, 7};
+ struct B f_dbl = {{12.0 , 127}, 99};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_uint64;
+ cls_struct_fields[1] = &ffi_type_uchar;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &cls_struct_type;
+ cls_struct_fields1[1] = &ffi_type_uchar;
+ cls_struct_fields1[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99: 13 233 134" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B))(pcl))(e_dbl, f_dbl);
+ /* { dg-output "\n1 7 12 127 99: 13 233 134" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/nested_struct8.c b/libffi/testsuite/libffi.call/nested_struct8.c
new file mode 100644
index 00000000000..5c231dead2e
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct8.c
@@ -0,0 +1,139 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ unsigned long long a;
+ unsigned char b;
+} A;
+
+typedef struct B {
+ struct A x;
+ unsigned char y;
+} B;
+
+typedef struct C {
+ unsigned long long d;
+ unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a + b4.d;
+ result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+ result.y = b2.b + b3.x.b + b4.e;
+
+ printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
+ (int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
+ (int)result.x.a, result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+ struct C b2;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+ b2 = *(struct C*)(args[2]);
+
+ *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+#ifndef USING_MMAP
+ static ffi_closure cl;
+#endif
+ ffi_closure *pcl;
+ void* args_dbl[4];
+ ffi_type* cls_struct_fields[3];
+ ffi_type* cls_struct_fields1[3];
+ ffi_type* cls_struct_fields2[3];
+ ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+ ffi_type* dbl_arg_types[4];
+
+#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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ cls_struct_type2.size = 0;
+ cls_struct_type2.alignment = 0;
+ cls_struct_type2.type = FFI_TYPE_STRUCT;
+ cls_struct_type2.elements = cls_struct_fields2;
+
+ struct A e_dbl = { 1LL, 7};
+ struct B f_dbl = {{12LL , 127}, 99};
+ struct C g_dbl = { 2LL, 9};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_uint64;
+ cls_struct_fields[1] = &ffi_type_uchar;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &cls_struct_type;
+ cls_struct_fields1[1] = &ffi_type_uchar;
+ cls_struct_fields1[2] = NULL;
+
+ cls_struct_fields2[0] = &ffi_type_uint64;
+ cls_struct_fields2[1] = &ffi_type_uchar;
+ cls_struct_fields2[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = &cls_struct_type2;
+ dbl_arg_types[3] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = &g_dbl;
+ args_dbl[3] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+ /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ exit(0);
+}
diff --git a/libffi/testsuite/libffi.call/nested_struct9.c b/libffi/testsuite/libffi.call/nested_struct9.c
new file mode 100644
index 00000000000..4a3e9e31b03
--- /dev/null
+++ b/libffi/testsuite/libffi.call/nested_struct9.c
@@ -0,0 +1,139 @@
+/* Area: ffi_call, closure_call
+ Purpose: Check structure passing with different structure size.
+ Contains structs as parameter of the struct itself.
+ Sample taken from Alan Modras patch to src/prep_cif.c.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20051010 */
+
+/* { dg-do run { xfail mips64*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
+#include "ffitest.h"
+
+typedef struct A {
+ unsigned char a;
+ unsigned long long b;
+} A;
+
+typedef struct B {
+ struct A x;
+ unsigned char y;
+} B;
+
+typedef struct C {
+ unsigned long d;
+ unsigned char e;
+} C;
+
+static B B_fn(struct A b2, struct B b3, struct C b4)
+{
+ struct B result;
+
+ result.x.a = b2.a + b3.x.a + b4.d;
+ result.x.b = b2.b + b3.x.b + b3.y + b4.e;
+ result.y = b2.b + b3.x.b + b4.e;
+
+ printf("%d %d %d %d %d %d %d: %d %d %d\n", b2.a, (int)b2.b,
+ b3.x.a, (int)b3.x.b, b3.y, (int)b4.d, b4.e,
+ result.x.a, (int)result.x.b, result.y);
+
+ return result;
+}
+
+static void
+B_gn(ffi_cif* cif __attribute__((unused)), void* resp, void** args,
+ void* userdata __attribute__((unused)))
+{
+ struct A b0;
+ struct B b1;
+ struct C b2;
+
+ b0 = *(struct A*)(args[0]);
+ b1 = *(struct B*)(args[1]);
+ b2 = *(struct C*)(args[2]);
+
+ *(B*)resp = B_fn(b0, b1, b2);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+#ifndef USING_MMAP
+ static ffi_closure cl;
+#endif
+ ffi_closure *pcl;
+ void* args_dbl[4];
+ ffi_type* cls_struct_fields[3];
+ ffi_type* cls_struct_fields1[3];
+ ffi_type* cls_struct_fields2[3];
+ ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
+ ffi_type* dbl_arg_types[4];
+
+#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;
+
+ cls_struct_type1.size = 0;
+ cls_struct_type1.alignment = 0;
+ cls_struct_type1.type = FFI_TYPE_STRUCT;
+ cls_struct_type1.elements = cls_struct_fields1;
+
+ cls_struct_type2.size = 0;
+ cls_struct_type2.alignment = 0;
+ cls_struct_type2.type = FFI_TYPE_STRUCT;
+ cls_struct_type2.elements = cls_struct_fields2;
+
+ struct A e_dbl = { 1, 7LL};
+ struct B f_dbl = {{12.0 , 127}, 99};
+ struct C g_dbl = { 2, 9};
+
+ struct B res_dbl;
+
+ cls_struct_fields[0] = &ffi_type_uchar;
+ cls_struct_fields[1] = &ffi_type_uint64;
+ cls_struct_fields[2] = NULL;
+
+ cls_struct_fields1[0] = &cls_struct_type;
+ cls_struct_fields1[1] = &ffi_type_uchar;
+ cls_struct_fields1[2] = NULL;
+
+ cls_struct_fields2[0] = &ffi_type_mylong;
+ cls_struct_fields2[1] = &ffi_type_uchar;
+ cls_struct_fields2[2] = NULL;
+
+
+ dbl_arg_types[0] = &cls_struct_type;
+ dbl_arg_types[1] = &cls_struct_type1;
+ dbl_arg_types[2] = &cls_struct_type2;
+ dbl_arg_types[3] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
+ dbl_arg_types) == FFI_OK);
+
+ args_dbl[0] = &e_dbl;
+ args_dbl[1] = &f_dbl;
+ args_dbl[2] = &g_dbl;
+ args_dbl[3] = NULL;
+
+ ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
+ /* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ CHECK(ffi_prep_closure(pcl, &cif, B_gn, NULL) == FFI_OK);
+
+ res_dbl = ((B(*)(A, B, C))(pcl))(e_dbl, f_dbl, g_dbl);
+ /* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
+ CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
+ CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
+ CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
+
+ exit(0);
+}