summaryrefslogtreecommitdiffstats
path: root/js/src/ctypes/libffi/testsuite/libffi.call
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /js/src/ctypes/libffi/testsuite/libffi.call
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/ctypes/libffi/testsuite/libffi.call')
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/align_mixed.c46
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/align_stdcall.c46
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/call.exp54
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/err_bad_typedef.c26
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/ffitest.h138
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/float.c59
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/float1.c60
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/float2.c61
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/float3.c74
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/float4.c62
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/float_va.c107
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/many.c59
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/many2.c57
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/many_double.c70
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/many_mixed.c78
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/negint.c52
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/offsets.c46
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/pr1172638.c127
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/promotion.c59
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/pyobjc-tc.c114
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_dbl.c36
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_dbl1.c43
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_dbl2.c42
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_fl.c35
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_fl1.c36
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_fl2.c49
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_fl3.c42
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_ldl.c34
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_ll.c41
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_ll1.c43
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_sc.c36
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_sl.c38
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_uc.c38
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/return_ul.c38
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/strlen.c44
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/strlen2.c49
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/strlen3.c49
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/strlen4.c55
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct1.c67
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct10.c57
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct2.c67
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct3.c60
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct4.c64
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct5.c66
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct6.c64
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct7.c74
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct8.c81
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/struct9.c68
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/uninitialized.c61
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/va_1.c196
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/va_struct1.c121
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/va_struct2.c123
-rw-r--r--js/src/ctypes/libffi/testsuite/libffi.call/va_struct3.c125
53 files changed, 3437 insertions, 0 deletions
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/align_mixed.c b/js/src/ctypes/libffi/testsuite/libffi.call/align_mixed.c
new file mode 100644
index 0000000000..5d4959ce97
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/align_mixed.c
@@ -0,0 +1,46 @@
+/* Area: ffi_call
+ Purpose: Check for proper argument alignment.
+ Limitations: none.
+ PR: none.
+ Originator: <twalljava@java.net> (from many_win32.c) */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static float ABI_ATTR align_arguments(int i1,
+ double f2,
+ int i3,
+ double f4)
+{
+ return i1+f2+i3+f4;
+}
+
+int main(void)
+{
+ ffi_cif cif;
+ ffi_type *args[4] = {
+ &ffi_type_sint,
+ &ffi_type_double,
+ &ffi_type_sint,
+ &ffi_type_double
+ };
+ double fa[2] = {1,2};
+ int ia[2] = {1,2};
+ void *values[4] = {&ia[0], &fa[0], &ia[1], &fa[1]};
+ float f, ff;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 4,
+ &ffi_type_float, args) == FFI_OK);
+
+ ff = align_arguments(ia[0], fa[0], ia[1], fa[1]);
+
+ ffi_call(&cif, FFI_FN(align_arguments), &f, values);
+
+ if (f == ff)
+ printf("align arguments tests ok!\n");
+ else
+ CHECK(0);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/align_stdcall.c b/js/src/ctypes/libffi/testsuite/libffi.call/align_stdcall.c
new file mode 100644
index 0000000000..5e5cb860cc
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/align_stdcall.c
@@ -0,0 +1,46 @@
+/* Area: ffi_call
+ Purpose: Check for proper argument alignment.
+ Limitations: none.
+ PR: none.
+ Originator: <twalljava@java.net> (from many_win32.c) */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static float ABI_ATTR align_arguments(int i1,
+ double f2,
+ int i3,
+ double f4)
+{
+ return i1+f2+i3+f4;
+}
+
+int main(void)
+{
+ ffi_cif cif;
+ ffi_type *args[4] = {
+ &ffi_type_sint,
+ &ffi_type_double,
+ &ffi_type_sint,
+ &ffi_type_double
+ };
+ double fa[2] = {1,2};
+ int ia[2] = {1,2};
+ void *values[4] = {&ia[0], &fa[0], &ia[1], &fa[1]};
+ float f, ff;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 4,
+ &ffi_type_float, args) == FFI_OK);
+
+ ff = align_arguments(ia[0], fa[0], ia[1], fa[1]);;
+
+ ffi_call(&cif, FFI_FN(align_arguments), &f, values);
+
+ if (f == ff)
+ printf("align arguments tests ok!\n");
+ else
+ CHECK(0);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/call.exp b/js/src/ctypes/libffi/testsuite/libffi.call/call.exp
new file mode 100644
index 0000000000..256f237c4c
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/call.exp
@@ -0,0 +1,54 @@
+# Copyright (C) 2003, 2006, 2009, 2010, 2014, 2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+dg-init
+libffi-init
+
+global srcdir subdir
+
+if { [string match $compiler_vendor "microsoft"] } {
+ # -wd4005 macro redefinition
+ # -wd4244 implicit conversion to type of smaller size
+ # -wd4305 truncation to smaller type
+ # -wd4477 printf %lu of uintptr_t
+ # -wd4312 implicit conversion to type of greater size
+ # -wd4311 pointer truncation to unsigned long
+ # -EHsc C++ Exception Handling (no SEH exceptions)
+ set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc";
+} else {
+ set additional_options "";
+}
+
+set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]]
+
+run-many-tests $tlist $additional_options
+
+set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.cc]]
+
+# No C++ for or1k
+if { [istarget "or1k-*-*"] } {
+ foreach test $tlist {
+ unsupported "$test"
+ }
+} else {
+ run-many-tests $tlist $additional_options
+}
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/err_bad_typedef.c b/js/src/ctypes/libffi/testsuite/libffi.call/err_bad_typedef.c
new file mode 100644
index 0000000000..bf60161861
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/err_bad_typedef.c
@@ -0,0 +1,26 @@
+/* Area: ffi_prep_cif
+ Purpose: Test error return for bad typedefs.
+ Limitations: none.
+ PR: none.
+ Originator: Blake Chaffin 6/6/2007 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type* arg_types[1];
+
+ ffi_type badType = ffi_type_void;
+
+ arg_types[0] = NULL;
+
+ badType.size = 0;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &badType,
+ arg_types) == FFI_BAD_TYPEDEF);
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/ffitest.h b/js/src/ctypes/libffi/testsuite/libffi.call/ffitest.h
new file mode 100644
index 0000000000..cfce1ad589
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/ffitest.h
@@ -0,0 +1,138 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#define MAX_ARGS 256
+
+#define CHECK(x) (void)(!(x) ? (abort(), 1) : 0)
+
+/* Define macros so that compilers other than gcc can run the tests. */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#define __STDCALL__ __attribute__((stdcall))
+#define __THISCALL__ __attribute__((thiscall))
+#define __FASTCALL__ __attribute__((fastcall))
+#define __MSABI__ __attribute__((ms_abi))
+#else
+#define __UNUSED__
+#define __STDCALL__ __stdcall
+#define __THISCALL__ __thiscall
+#define __FASTCALL__ __fastcall
+#endif
+
+#ifndef ABI_NUM
+#define ABI_NUM FFI_DEFAULT_ABI
+#define ABI_ATTR
+#endif
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+ file open. */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+# define MAP_FAILED -1
+# endif
+# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+# define USING_MMAP
+
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+
+# include <sys/mman.h>
+# ifndef MAP_FAILED
+# define MAP_FAILED -1
+# endif
+# define USING_MMAP
+
+#endif
+
+/* MinGW kludge. */
+#if defined(_WIN64) | defined(_WIN32)
+#define PRIdLL "I64d"
+#define PRIuLL "I64u"
+#else
+#define PRIdLL "lld"
+#define PRIuLL "llu"
+#endif
+
+/* Tru64 UNIX kludge. */
+#if defined(__alpha__) && defined(__osf__)
+/* Tru64 UNIX V4.0 doesn't support %lld/%lld, but long is 64-bit. */
+#undef PRIdLL
+#define PRIdLL "ld"
+#undef PRIuLL
+#define PRIuLL "lu"
+#define PRId8 "hd"
+#define PRIu8 "hu"
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#define PRIuPTR "lu"
+#endif
+
+/* PA HP-UX kludge. */
+#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR)
+#define PRIuPTR "lu"
+#endif
+
+/* IRIX kludge. */
+#if defined(__sgi)
+/* IRIX 6.5 <inttypes.h> provides all definitions, but only for C99
+ compilations. */
+#define PRId8 "hhd"
+#define PRIu8 "hhu"
+#if (_MIPS_SZLONG == 32)
+#define PRId64 "lld"
+#define PRIu64 "llu"
+#endif
+/* This doesn't match <inttypes.h>, which always has "lld" here, but the
+ arguments are uint64_t, int64_t, which are unsigned long, long for
+ 64-bit in <sgidefs.h>. */
+#if (_MIPS_SZLONG == 64)
+#define PRId64 "ld"
+#define PRIu64 "lu"
+#endif
+/* This doesn't match <inttypes.h>, which has "u" here, but the arguments
+ are uintptr_t, which is always unsigned long. */
+#define PRIuPTR "lu"
+#endif
+
+/* Solaris < 10 kludge. */
+#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR)
+#if defined(__arch64__) || defined (__x86_64__)
+#define PRIuPTR "lu"
+#else
+#define PRIuPTR "u"
+#endif
+#endif
+
+/* MSVC kludge. */
+#if defined _MSC_VER
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
+#define PRIuPTR "lu"
+#define PRIu8 "u"
+#define PRId8 "d"
+#define PRIu64 "I64u"
+#define PRId64 "I64d"
+#endif
+#endif
+
+#ifndef PRIuPTR
+#define PRIuPTR "u"
+#endif
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/float.c b/js/src/ctypes/libffi/testsuite/libffi.call/float.c
new file mode 100644
index 0000000000..fbc272d84f
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/float.c
@@ -0,0 +1,59 @@
+/* Area: ffi_call
+ Purpose: Check return value float.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int floating(int a, float b, double c, long double d)
+{
+ int i;
+
+ i = (int) ((float)a/b + ((float)c/(float)d));
+
+ return i;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+
+ float f;
+ signed int si1;
+ double d;
+ long double ld;
+
+ args[0] = &ffi_type_sint;
+ values[0] = &si1;
+ args[1] = &ffi_type_float;
+ values[1] = &f;
+ args[2] = &ffi_type_double;
+ values[2] = &d;
+ args[3] = &ffi_type_longdouble;
+ values[3] = &ld;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_sint, args) == FFI_OK);
+
+ si1 = 6;
+ f = 3.14159;
+ d = (double)1.0/(double)3.0;
+ ld = 2.71828182846L;
+
+ floating (si1, f, d, ld);
+
+ ffi_call(&cif, FFI_FN(floating), &rint, values);
+
+ printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld));
+
+ CHECK((int)rint == floating(si1, f, d, ld));
+
+ exit (0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/float1.c b/js/src/ctypes/libffi/testsuite/libffi.call/float1.c
new file mode 100644
index 0000000000..c48493c6b2
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/float1.c
@@ -0,0 +1,60 @@
+/* Area: ffi_call
+ Purpose: Check return value double.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include "float.h"
+
+#include <math.h>
+
+typedef union
+{
+ double d;
+ unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(float f)
+{
+ return f/3.0;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ float f;
+ value_type result[2];
+ unsigned int i;
+
+ args[0] = &ffi_type_float;
+ values[0] = &f;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_double, args) == FFI_OK);
+
+ f = 3.14159;
+
+ /* Put a canary in the return array. This is a regression test for
+ a buffer overrun. */
+ memset(result[1].c, CANARY, sizeof (double));
+
+ ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+
+ /* These are not always the same!! Check for a reasonable delta */
+
+ CHECK(fabs(result[0].d - dblit(f)) < DBL_EPSILON);
+
+ /* Check the canary. */
+ for (i = 0; i < sizeof (double); ++i)
+ CHECK(result[1].c[i] == CANARY);
+
+ exit(0);
+
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/float2.c b/js/src/ctypes/libffi/testsuite/libffi.call/float2.c
new file mode 100644
index 0000000000..57cd9e30f9
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/float2.c
@@ -0,0 +1,61 @@
+/* Area: ffi_call
+ Purpose: Check return value long double.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "float.h"
+
+#include <math.h>
+
+static long double ldblit(float f)
+{
+ return (long double) (((long double) f)/ (long double) 3.0);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ float f;
+ long double ld;
+ long double original;
+
+ args[0] = &ffi_type_float;
+ values[0] = &f;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_longdouble, args) == FFI_OK);
+
+ f = 3.14159;
+
+#if defined(__sun) && defined(__GNUC__)
+ /* long double support under SunOS/gcc is pretty much non-existent.
+ You'll get the odd bus error in library routines like printf() */
+#else
+ printf ("%Lf\n", ldblit(f));
+#endif
+
+ ld = 666;
+ ffi_call(&cif, FFI_FN(ldblit), &ld, values);
+
+#if defined(__sun) && defined(__GNUC__)
+ /* long double support under SunOS/gcc is pretty much non-existent.
+ You'll get the odd bus error in library routines like printf() */
+#else
+ printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
+#endif
+
+ /* These are not always the same!! Check for a reasonable delta */
+ original = ldblit(f);
+ if (((ld > original) ? (ld - original) : (original - ld)) < LDBL_EPSILON)
+ puts("long double return value tests ok!");
+ else
+ CHECK(0);
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/float3.c b/js/src/ctypes/libffi/testsuite/libffi.call/float3.c
new file mode 100644
index 0000000000..bab3206a17
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/float3.c
@@ -0,0 +1,74 @@
+/* Area: ffi_call
+ Purpose: Check float arguments with different orders.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+#include "float.h"
+
+#include <math.h>
+
+static double floating_1(float a, double b, long double c)
+{
+ return (double) a + b + (double) c;
+}
+
+static double floating_2(long double a, double b, float c)
+{
+ return (double) a + b + (double) c;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ double rd;
+
+ float f;
+ double d;
+ long double ld;
+
+ args[0] = &ffi_type_float;
+ values[0] = &f;
+ args[1] = &ffi_type_double;
+ values[1] = &d;
+ args[2] = &ffi_type_longdouble;
+ values[2] = &ld;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+ &ffi_type_double, args) == FFI_OK);
+
+ f = 3.14159;
+ d = (double)1.0/(double)3.0;
+ ld = 2.71828182846L;
+
+ floating_1 (f, d, ld);
+
+ ffi_call(&cif, FFI_FN(floating_1), &rd, values);
+
+ CHECK(fabs(rd - floating_1(f, d, ld)) < DBL_EPSILON);
+
+ args[0] = &ffi_type_longdouble;
+ values[0] = &ld;
+ args[1] = &ffi_type_double;
+ values[1] = &d;
+ args[2] = &ffi_type_float;
+ values[2] = &f;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+ &ffi_type_double, args) == FFI_OK);
+
+ floating_2 (ld, d, f);
+
+ ffi_call(&cif, FFI_FN(floating_2), &rd, values);
+
+ CHECK(fabs(rd - floating_2(ld, d, f)) < DBL_EPSILON);
+
+ exit (0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/float4.c b/js/src/ctypes/libffi/testsuite/libffi.call/float4.c
new file mode 100644
index 0000000000..0dd6d85e7a
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/float4.c
@@ -0,0 +1,62 @@
+/* Area: ffi_call
+ Purpose: Check denorm double value.
+ Limitations: none.
+ PR: PR26483.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+/* { dg-options "-mieee" { target alpha*-*-* } } */
+
+#include "ffitest.h"
+#include "float.h"
+
+typedef union
+{
+ double d;
+ unsigned char c[sizeof (double)];
+} value_type;
+
+#define CANARY 0xba
+
+static double dblit(double d)
+{
+ return d;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ double d;
+ value_type result[2];
+ unsigned int i;
+
+ args[0] = &ffi_type_double;
+ values[0] = &d;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_double, args) == FFI_OK);
+
+ d = DBL_MIN / 2;
+
+ /* Put a canary in the return array. This is a regression test for
+ a buffer overrun. */
+ memset(result[1].c, CANARY, sizeof (double));
+
+ ffi_call(&cif, FFI_FN(dblit), &result[0].d, values);
+
+ /* The standard delta check doesn't work for denorms. Since we didn't do
+ any arithmetic, we should get the original result back, and hence an
+ exact check should be OK here. */
+
+ CHECK(result[0].d == dblit(d));
+
+ /* Check the canary. */
+ for (i = 0; i < sizeof (double); ++i)
+ CHECK(result[1].c[i] == CANARY);
+
+ exit(0);
+
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/float_va.c b/js/src/ctypes/libffi/testsuite/libffi.call/float_va.c
new file mode 100644
index 0000000000..5acff91f66
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/float_va.c
@@ -0,0 +1,107 @@
+/* Area: fp and variadics
+ Purpose: check fp inputs and returns work on variadics, even the fixed params
+ Limitations: None
+ PR: none
+ Originator: <david.gilbert@linaro.org> 2011-01-25
+
+ Intended to stress the difference in ABI on ARM vfp
+*/
+
+/* { dg-do run } */
+
+#include <stdarg.h>
+
+#include "ffitest.h"
+
+/* prints out all the parameters, and returns the sum of them all.
+ * 'x' is the number of variadic parameters all of which are double in this test
+ */
+double float_va_fn(unsigned int x, double y,...)
+{
+ double total=0.0;
+ va_list ap;
+ unsigned int i;
+
+ total+=(double)x;
+ total+=y;
+
+ printf("%u: %.1f :", x, y);
+
+ va_start(ap, y);
+ for(i=0;i<x;i++)
+ {
+ double arg=va_arg(ap, double);
+ total+=arg;
+ printf(" %d:%.1f ", i, arg);
+ }
+ va_end(ap);
+
+ printf(" total: %.1f\n", total);
+
+ return total;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+
+ ffi_type *arg_types[5];
+ void *values[5];
+ double doubles[5];
+ unsigned int firstarg;
+ double resfp;
+
+ /* First test, pass float_va_fn(0,2.0) - note there are no actual
+ * variadic parameters, but it's declared variadic so the ABI may be
+ * different. */
+ /* Call it statically and then via ffi */
+ resfp=float_va_fn(0,2.0);
+ /* { dg-output "0: 2.0 : total: 2.0" } */
+ printf("compiled: %.1f\n", resfp);
+ /* { dg-output "\ncompiled: 2.0" } */
+
+ arg_types[0] = &ffi_type_uint;
+ arg_types[1] = &ffi_type_double;
+ arg_types[2] = NULL;
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 2,
+ &ffi_type_double, arg_types) == FFI_OK);
+
+ firstarg = 0;
+ doubles[0] = 2.0;
+ values[0] = &firstarg;
+ values[1] = &doubles[0];
+ ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+ /* { dg-output "\n0: 2.0 : total: 2.0" } */
+ printf("ffi: %.1f\n", resfp);
+ /* { dg-output "\nffi: 2.0" } */
+
+ /* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
+ /* Call it statically and then via ffi */
+ resfp=float_va_fn(2,2.0,3.0,4.0);
+ /* { dg-output "\n2: 2.0 : 0:3.0 1:4.0 total: 11.0" } */
+ printf("compiled: %.1f\n", resfp);
+ /* { dg-output "\ncompiled: 11.0" } */
+
+ arg_types[0] = &ffi_type_uint;
+ arg_types[1] = &ffi_type_double;
+ arg_types[2] = &ffi_type_double;
+ arg_types[3] = &ffi_type_double;
+ arg_types[4] = NULL;
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 4,
+ &ffi_type_double, arg_types) == FFI_OK);
+
+ firstarg = 2;
+ doubles[0] = 2.0;
+ doubles[1] = 3.0;
+ doubles[2] = 4.0;
+ values[0] = &firstarg;
+ values[1] = &doubles[0];
+ values[2] = &doubles[1];
+ values[3] = &doubles[2];
+ ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
+ /* { dg-output "\n2: 2.0 : 0:3.0 1:4.0 total: 11.0" } */
+ printf("ffi: %.1f\n", resfp);
+ /* { dg-output "\nffi: 11.0" } */
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/many.c b/js/src/ctypes/libffi/testsuite/libffi.call/many.c
new file mode 100644
index 0000000000..336968c77a
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/many.c
@@ -0,0 +1,59 @@
+/* Area: ffi_call
+ Purpose: Check return value float, with many arguments
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static float ABI_ATTR many(float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13)
+{
+#if 0
+ printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+ (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
+ (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+ (double) f11, (double) f12, (double) f13);
+#endif
+
+ return f1+f2+f3+f4+f5+f6+f7+f8+f9+f10+f11+f12+f13;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[13];
+ void *values[13];
+ float fa[13];
+ float f, ff;
+ int i;
+
+ for (i = 0; i < 13; i++)
+ {
+ args[i] = &ffi_type_float;
+ values[i] = &fa[i];
+ fa[i] = (float) i;
+ }
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 13,
+ &ffi_type_float, args) == FFI_OK);
+
+ ffi_call(&cif, FFI_FN(many), &f, values);
+
+ ff = many(fa[0], fa[1],
+ fa[2], fa[3],
+ fa[4], fa[5],
+ fa[6], fa[7],
+ fa[8], fa[9],
+ fa[10],fa[11],fa[12]);
+
+ if (fabs(f - ff) < FLT_EPSILON)
+ exit(0);
+ else
+ abort();
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/many2.c b/js/src/ctypes/libffi/testsuite/libffi.call/many2.c
new file mode 100644
index 0000000000..1c85746e4c
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/many2.c
@@ -0,0 +1,57 @@
+/* Area: ffi_call
+ Purpose: Check uint8_t arguments.
+ Limitations: none.
+ PR: PR45677.
+ Originator: Dan Witte <dwitte@gmail.com> 20100916 */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+#define NARGS 7
+
+typedef unsigned char u8;
+
+#ifdef __GNUC__
+__attribute__((noinline))
+#endif
+uint8_t
+foo (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+ uint8_t e, uint8_t f, uint8_t g)
+{
+ return a + b + c + d + e + f + g;
+}
+
+uint8_t ABI_ATTR
+bar (uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+ uint8_t e, uint8_t f, uint8_t g)
+{
+ return foo (a, b, c, d, e, f, g);
+}
+
+int
+main (void)
+{
+ ffi_type *ffitypes[NARGS];
+ int i;
+ ffi_cif cif;
+ ffi_arg result = 0;
+ uint8_t args[NARGS];
+ void *argptrs[NARGS];
+
+ for (i = 0; i < NARGS; ++i)
+ ffitypes[i] = &ffi_type_uint8;
+
+ CHECK (ffi_prep_cif (&cif, ABI_NUM, NARGS,
+ &ffi_type_uint8, ffitypes) == FFI_OK);
+
+ for (i = 0; i < NARGS; ++i)
+ {
+ args[i] = i;
+ argptrs[i] = &args[i];
+ }
+ ffi_call (&cif, FFI_FN (bar), &result, argptrs);
+
+ CHECK (result == 21);
+ return 0;
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/many_double.c b/js/src/ctypes/libffi/testsuite/libffi.call/many_double.c
new file mode 100644
index 0000000000..4ef8c8ab28
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/many_double.c
@@ -0,0 +1,70 @@
+/* Area: ffi_call
+ Purpose: Check return value double, with many arguments
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static double many(double f1,
+ double f2,
+ double f3,
+ double f4,
+ double f5,
+ double f6,
+ double f7,
+ double f8,
+ double f9,
+ double f10,
+ double f11,
+ double f12,
+ double f13)
+{
+#if 0
+ printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
+ (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
+ (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
+ (double) f11, (double) f12, (double) f13);
+#endif
+
+ return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[13];
+ void *values[13];
+ double fa[13];
+ double f, ff;
+ int i;
+
+ for (i = 0; i < 13; i++)
+ {
+ args[i] = &ffi_type_double;
+ values[i] = &fa[i];
+ fa[i] = (double) i;
+ }
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
+ &ffi_type_double, args) == FFI_OK);
+
+ ffi_call(&cif, FFI_FN(many), &f, values);
+
+ ff = many(fa[0], fa[1],
+ fa[2], fa[3],
+ fa[4], fa[5],
+ fa[6], fa[7],
+ fa[8], fa[9],
+ fa[10],fa[11],fa[12]);
+ if (fabs(f - ff) < FLT_EPSILON)
+ exit(0);
+ else
+ abort();
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/many_mixed.c b/js/src/ctypes/libffi/testsuite/libffi.call/many_mixed.c
new file mode 100644
index 0000000000..85ec36ecbe
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/many_mixed.c
@@ -0,0 +1,78 @@
+/* Area: ffi_call
+ Purpose: Check return value double, with many arguments
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+static double many(double f1,
+ double f2,
+ long int i1,
+ double f3,
+ double f4,
+ long int i2,
+ double f5,
+ double f6,
+ long int i3,
+ double f7,
+ double f8,
+ long int i4,
+ double f9,
+ double f10,
+ long int i5,
+ double f11,
+ double f12,
+ long int i6,
+ double f13)
+{
+ return ((double) (i1 + i2 + i3 + i4 + i5 + i6) + (f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[19];
+ void *values[19];
+ double fa[19];
+ long int la[19];
+ double f, ff;
+ int i;
+
+ for (i = 0; i < 19; i++)
+ {
+ if( (i - 2) % 3 == 0) {
+ args[i] = &ffi_type_slong;
+ la[i] = (long int) i;
+ values[i] = &la[i];
+ }
+ else {
+ args[i] = &ffi_type_double;
+ fa[i] = (double) i;
+ values[i] = &fa[i];
+ }
+ }
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 19,
+ &ffi_type_double, args) == FFI_OK);
+
+ ffi_call(&cif, FFI_FN(many), &f, values);
+
+ ff = many(fa[0], fa[1], la[2],
+ fa[3], fa[4], la[5],
+ fa[6], fa[7], la[8],
+ fa[9], fa[10], la[11],
+ fa[12], fa[13], la[14],
+ fa[15], fa[16], la[17],
+ fa[18]);
+ if (fabs(f - ff) < FLT_EPSILON)
+ exit(0);
+ else
+ abort();
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/negint.c b/js/src/ctypes/libffi/testsuite/libffi.call/negint.c
new file mode 100644
index 0000000000..6e2f26fc10
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/negint.c
@@ -0,0 +1,52 @@
+/* Area: ffi_call
+ Purpose: Check that negative integers are passed correctly.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static int checking(int a, short b, signed char c)
+{
+
+ return (a < 0 && b < 0 && c < 0);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+
+ signed int si;
+ signed short ss;
+ signed char sc;
+
+ args[0] = &ffi_type_sint;
+ values[0] = &si;
+ args[1] = &ffi_type_sshort;
+ values[1] = &ss;
+ args[2] = &ffi_type_schar;
+ values[2] = &sc;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+ &ffi_type_sint, args) == FFI_OK);
+
+ si = -6;
+ ss = -12;
+ sc = -1;
+
+ checking (si, ss, sc);
+
+ ffi_call(&cif, FFI_FN(checking), &rint, values);
+
+ printf ("%d vs %d\n", (int)rint, checking (si, ss, sc));
+
+ CHECK(rint != 0);
+
+ exit (0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/offsets.c b/js/src/ctypes/libffi/testsuite/libffi.call/offsets.c
new file mode 100644
index 0000000000..23d88b35d5
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/offsets.c
@@ -0,0 +1,46 @@
+/* Area: Struct layout
+ Purpose: Test ffi_get_struct_offsets
+ Limitations: none.
+ PR: none.
+ Originator: Tom Tromey. */
+
+/* { dg-do run } */
+#include "ffitest.h"
+#include <stddef.h>
+
+struct test_1
+{
+ char c;
+ float f;
+ char c2;
+ int i;
+};
+
+int
+main (void)
+{
+ ffi_type test_1_type;
+ ffi_type *test_1_elements[5];
+ size_t test_1_offsets[4];
+
+ test_1_elements[0] = &ffi_type_schar;
+ test_1_elements[1] = &ffi_type_float;
+ test_1_elements[2] = &ffi_type_schar;
+ test_1_elements[3] = &ffi_type_sint;
+ test_1_elements[4] = NULL;
+
+ test_1_type.size = 0;
+ test_1_type.alignment = 0;
+ test_1_type.type = FFI_TYPE_STRUCT;
+ test_1_type.elements = test_1_elements;
+
+ CHECK (ffi_get_struct_offsets (FFI_DEFAULT_ABI, &test_1_type, test_1_offsets)
+ == FFI_OK);
+ CHECK (test_1_type.size == sizeof (struct test_1));
+ CHECK (offsetof (struct test_1, c) == test_1_offsets[0]);
+ CHECK (offsetof (struct test_1, f) == test_1_offsets[1]);
+ CHECK (offsetof (struct test_1, c2) == test_1_offsets[2]);
+ CHECK (offsetof (struct test_1, i) == test_1_offsets[3]);
+
+ return 0;
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/pr1172638.c b/js/src/ctypes/libffi/testsuite/libffi.call/pr1172638.c
new file mode 100644
index 0000000000..7da1621cd6
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/pr1172638.c
@@ -0,0 +1,127 @@
+/* Area: ffi_call
+ Purpose: Reproduce bug found in python ctypes
+ Limitations: none.
+ PR: Fedora 1174037 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct {
+ long x;
+ long y;
+} POINT;
+
+typedef struct {
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECT;
+
+static RECT ABI_ATTR pr_test(int i __UNUSED__, RECT ar __UNUSED__,
+ RECT* br __UNUSED__, POINT cp __UNUSED__,
+ RECT dr __UNUSED__, RECT *er __UNUSED__,
+ POINT fp, RECT gr __UNUSED__)
+{
+ RECT result;
+
+ result.left = fp.x;
+ result.right = fp.y;
+ result.top = fp.x;
+ result.bottom = fp.y;
+
+ return result;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type point_type, rect_type;
+ ffi_type *point_type_elements[3];
+ ffi_type *rect_type_elements[5];
+
+ int i;
+ POINT cp, fp;
+ RECT ar, br, dr, er, gr;
+ RECT *p1, *p2;
+
+ /* This is a hack to get a properly aligned result buffer */
+ RECT *rect_result =
+ (RECT *) malloc (sizeof(RECT));
+
+ point_type.size = 0;
+ point_type.alignment = 0;
+ point_type.type = FFI_TYPE_STRUCT;
+ point_type.elements = point_type_elements;
+ point_type_elements[0] = &ffi_type_slong;
+ point_type_elements[1] = &ffi_type_slong;
+ point_type_elements[2] = NULL;
+
+ rect_type.size = 0;
+ rect_type.alignment = 0;
+ rect_type.type = FFI_TYPE_STRUCT;
+ rect_type.elements = rect_type_elements;
+ rect_type_elements[0] = &ffi_type_slong;
+ rect_type_elements[1] = &ffi_type_slong;
+ rect_type_elements[2] = &ffi_type_slong;
+ rect_type_elements[3] = &ffi_type_slong;
+ rect_type_elements[4] = NULL;
+
+ args[0] = &ffi_type_sint;
+ args[1] = &rect_type;
+ args[2] = &ffi_type_pointer;
+ args[3] = &point_type;
+ args[4] = &rect_type;
+ args[5] = &ffi_type_pointer;
+ args[6] = &point_type;
+ args[7] = &rect_type;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 8, &rect_type, args) == FFI_OK);
+
+ i = 1;
+ ar.left = 2;
+ ar.right = 3;
+ ar.top = 4;
+ ar.bottom = 5;
+ br.left = 6;
+ br.right = 7;
+ br.top = 8;
+ br.bottom = 9;
+ cp.x = 10;
+ cp.y = 11;
+ dr.left = 12;
+ dr.right = 13;
+ dr.top = 14;
+ dr.bottom = 15;
+ er.left = 16;
+ er.right = 17;
+ er.top = 18;
+ er.bottom = 19;
+ fp.x = 20;
+ fp.y = 21;
+ gr.left = 22;
+ gr.right = 23;
+ gr.top = 24;
+ gr.bottom = 25;
+
+ values[0] = &i;
+ values[1] = &ar;
+ p1 = &br;
+ values[2] = &p1;
+ values[3] = &cp;
+ values[4] = &dr;
+ p2 = &er;
+ values[5] = &p2;
+ values[6] = &fp;
+ values[7] = &gr;
+
+ ffi_call (&cif, FFI_FN(pr_test), rect_result, values);
+
+ CHECK(rect_result->top == 20);
+
+ free (rect_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/promotion.c b/js/src/ctypes/libffi/testsuite/libffi.call/promotion.c
new file mode 100644
index 0000000000..44561615dd
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/promotion.c
@@ -0,0 +1,59 @@
+/* Area: ffi_call
+ Purpose: Promotion test.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static int promotion(signed char sc, signed short ss,
+ unsigned char uc, unsigned short us)
+{
+ int r = (int) sc + (int) ss + (int) uc + (int) us;
+
+ return r;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+ signed char sc;
+ unsigned char uc;
+ signed short ss;
+ unsigned short us;
+ unsigned long ul;
+
+ args[0] = &ffi_type_schar;
+ args[1] = &ffi_type_sshort;
+ args[2] = &ffi_type_uchar;
+ args[3] = &ffi_type_ushort;
+ values[0] = &sc;
+ values[1] = &ss;
+ values[2] = &uc;
+ values[3] = &us;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_sint, args) == FFI_OK);
+
+ us = 0;
+ ul = 0;
+
+ for (sc = (signed char) -127;
+ sc <= (signed char) 120; sc += 1)
+ for (ss = -30000; ss <= 30000; ss += 10000)
+ for (uc = (unsigned char) 0;
+ uc <= (unsigned char) 200; uc += 20)
+ for (us = 0; us <= 60000; us += 10000)
+ {
+ ul++;
+ ffi_call(&cif, FFI_FN(promotion), &rint, values);
+ CHECK((int)rint == (signed char) sc + (signed short) ss +
+ (unsigned char) uc + (unsigned short) us);
+ }
+ printf("%lu promotion tests run\n", ul);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/pyobjc-tc.c b/js/src/ctypes/libffi/testsuite/libffi.call/pyobjc-tc.c
new file mode 100644
index 0000000000..e29bd6c283
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/pyobjc-tc.c
@@ -0,0 +1,114 @@
+/* Area: ffi_call
+ Purpose: Check different structures.
+ Limitations: none.
+ PR: none.
+ Originator: Ronald Oussoren <oussoren@cistron.nl> 20030824 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct Point {
+ float x;
+ float y;
+} Point;
+
+typedef struct Size {
+ float h;
+ float w;
+} Size;
+
+typedef struct Rect {
+ Point o;
+ Size s;
+} Rect;
+
+int doit(int o, char* s, Point p, Rect r, int last)
+{
+ printf("CALLED WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+ o, s, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, last);
+ return 42;
+}
+
+
+int main(void)
+{
+ ffi_type point_type;
+ ffi_type size_type;
+ ffi_type rect_type;
+ ffi_cif cif;
+ ffi_type* arglist[6];
+ void* values[6];
+ int r;
+
+ /*
+ * First set up FFI types for the 3 struct types
+ */
+
+ point_type.size = 0; /*sizeof(Point);*/
+ point_type.alignment = 0; /*__alignof__(Point);*/
+ point_type.type = FFI_TYPE_STRUCT;
+ point_type.elements = malloc(3 * sizeof(ffi_type*));
+ point_type.elements[0] = &ffi_type_float;
+ point_type.elements[1] = &ffi_type_float;
+ point_type.elements[2] = NULL;
+
+ size_type.size = 0;/* sizeof(Size);*/
+ size_type.alignment = 0;/* __alignof__(Size);*/
+ size_type.type = FFI_TYPE_STRUCT;
+ size_type.elements = malloc(3 * sizeof(ffi_type*));
+ size_type.elements[0] = &ffi_type_float;
+ size_type.elements[1] = &ffi_type_float;
+ size_type.elements[2] = NULL;
+
+ rect_type.size = 0;/*sizeof(Rect);*/
+ rect_type.alignment =0;/* __alignof__(Rect);*/
+ rect_type.type = FFI_TYPE_STRUCT;
+ rect_type.elements = malloc(3 * sizeof(ffi_type*));
+ rect_type.elements[0] = &point_type;
+ rect_type.elements[1] = &size_type;
+ rect_type.elements[2] = NULL;
+
+ /*
+ * Create a CIF
+ */
+ arglist[0] = &ffi_type_sint;
+ arglist[1] = &ffi_type_pointer;
+ arglist[2] = &point_type;
+ arglist[3] = &rect_type;
+ arglist[4] = &ffi_type_sint;
+ arglist[5] = NULL;
+
+ r = ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
+ 5, &ffi_type_sint, arglist);
+ if (r != FFI_OK) {
+ abort();
+ }
+
+
+ /* And call the function through the CIF */
+
+ {
+ Point p = { 1.0, 2.0 };
+ Rect r = { { 9.0, 10.0}, { -1.0, -2.0 } };
+ int o = 0;
+ int l = 42;
+ char* m = "myMethod";
+ ffi_arg result;
+
+ values[0] = &o;
+ values[1] = &m;
+ values[2] = &p;
+ values[3] = &r;
+ values[4] = &l;
+ values[5] = NULL;
+
+ printf("CALLING WITH %d %s {%f %f} {{%f %f} {%f %f}} %d\n",
+ o, m, p.x, p.y, r.o.x, r.o.y, r.s.h, r.s.w, l);
+
+ ffi_call(&cif, FFI_FN(doit), &result, values);
+
+ printf ("The result is %d\n", (int)result);
+
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl.c
new file mode 100644
index 0000000000..fd07e50179
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl.c
@@ -0,0 +1,36 @@
+/* Area: ffi_call
+ Purpose: Check return value double.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl)
+{
+ printf ("%f\n", dbl);
+ return 2 * dbl;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ double dbl, rdbl;
+
+ args[0] = &ffi_type_double;
+ values[0] = &dbl;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_double, args) == FFI_OK);
+
+ for (dbl = -127.3; dbl < 127; dbl++)
+ {
+ ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+ printf ("%f vs %f\n", rdbl, return_dbl(dbl));
+ CHECK(rdbl == 2 * dbl);
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl1.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl1.c
new file mode 100644
index 0000000000..0ea5d50551
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl1.c
@@ -0,0 +1,43 @@
+/* Area: ffi_call
+ Purpose: Check return value double.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, float fl2, unsigned int in3, double dbl4)
+{
+ return dbl1 + fl2 + in3 + dbl4;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ double dbl1, dbl4, rdbl;
+ float fl2;
+ unsigned int in3;
+ args[0] = &ffi_type_double;
+ args[1] = &ffi_type_float;
+ args[2] = &ffi_type_uint;
+ args[3] = &ffi_type_double;
+ values[0] = &dbl1;
+ values[1] = &fl2;
+ values[2] = &in3;
+ values[3] = &dbl4;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_double, args) == FFI_OK);
+ dbl1 = 127.0;
+ fl2 = 128.0;
+ in3 = 255;
+ dbl4 = 512.7;
+
+ ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+ printf ("%f vs %f\n", rdbl, return_dbl(dbl1, fl2, in3, dbl4));
+ CHECK(rdbl == dbl1 + fl2 + in3 + dbl4);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl2.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl2.c
new file mode 100644
index 0000000000..b3818f866b
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_dbl2.c
@@ -0,0 +1,42 @@
+/* Area: ffi_call
+ Purpose: Check return value double.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static double return_dbl(double dbl1, double dbl2, unsigned int in3, double dbl4)
+{
+ return dbl1 + dbl2 + in3 + dbl4;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ double dbl1, dbl2, dbl4, rdbl;
+ unsigned int in3;
+ args[0] = &ffi_type_double;
+ args[1] = &ffi_type_double;
+ args[2] = &ffi_type_uint;
+ args[3] = &ffi_type_double;
+ values[0] = &dbl1;
+ values[1] = &dbl2;
+ values[2] = &in3;
+ values[3] = &dbl4;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_double, args) == FFI_OK);
+ dbl1 = 127.0;
+ dbl2 = 128.0;
+ in3 = 255;
+ dbl4 = 512.7;
+
+ ffi_call(&cif, FFI_FN(return_dbl), &rdbl, values);
+ printf ("%f vs %f\n", rdbl, return_dbl(dbl1, dbl2, in3, dbl4));
+ CHECK(rdbl == dbl1 + dbl2 + in3 + dbl4);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_fl.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl.c
new file mode 100644
index 0000000000..fb8a09e32a
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl.c
@@ -0,0 +1,35 @@
+/* Area: ffi_call
+ Purpose: Check return value float.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl)
+{
+ return 2 * fl;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ float fl, rfl;
+
+ args[0] = &ffi_type_float;
+ values[0] = &fl;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_float, args) == FFI_OK);
+
+ for (fl = -127.0; fl < 127; fl++)
+ {
+ ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+ printf ("%f vs %f\n", rfl, return_fl(fl));
+ CHECK(rfl == 2 * fl);
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_fl1.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl1.c
new file mode 100644
index 0000000000..c3d92c283d
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl1.c
@@ -0,0 +1,36 @@
+/* Area: ffi_call
+ Purpose: Check return value float.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2)
+{
+ return fl1 + fl2;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ float fl1, fl2, rfl;
+
+ args[0] = &ffi_type_float;
+ args[1] = &ffi_type_float;
+ values[0] = &fl1;
+ values[1] = &fl2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+ &ffi_type_float, args) == FFI_OK);
+ fl1 = 127.0;
+ fl2 = 128.0;
+
+ ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+ printf ("%f vs %f\n", rfl, return_fl(fl1, fl2));
+ CHECK(rfl == fl1 + fl2);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_fl2.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl2.c
new file mode 100644
index 0000000000..ddb976cc2b
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl2.c
@@ -0,0 +1,49 @@
+/* Area: ffi_call
+ Purpose: Check return value float.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+/* Use volatile float to avoid false negative on ix86. See PR target/323. */
+static float return_fl(float fl1, float fl2, float fl3, float fl4)
+{
+ volatile float sum;
+
+ sum = fl1 + fl2 + fl3 + fl4;
+ return sum;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ float fl1, fl2, fl3, fl4, rfl;
+ volatile float sum;
+
+ args[0] = &ffi_type_float;
+ args[1] = &ffi_type_float;
+ args[2] = &ffi_type_float;
+ args[3] = &ffi_type_float;
+ values[0] = &fl1;
+ values[1] = &fl2;
+ values[2] = &fl3;
+ values[3] = &fl4;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_float, args) == FFI_OK);
+ fl1 = 127.0;
+ fl2 = 128.0;
+ fl3 = 255.1;
+ fl4 = 512.7;
+
+ ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+ printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, fl3, fl4));
+
+ sum = fl1 + fl2 + fl3 + fl4;
+ CHECK(rfl == sum);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_fl3.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl3.c
new file mode 100644
index 0000000000..c37877b18e
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_fl3.c
@@ -0,0 +1,42 @@
+/* Area: ffi_call
+ Purpose: Check return value float.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20050212 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static float return_fl(float fl1, float fl2, unsigned int in3, float fl4)
+{
+ return fl1 + fl2 + in3 + fl4;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ float fl1, fl2, fl4, rfl;
+ unsigned int in3;
+ args[0] = &ffi_type_float;
+ args[1] = &ffi_type_float;
+ args[2] = &ffi_type_uint;
+ args[3] = &ffi_type_float;
+ values[0] = &fl1;
+ values[1] = &fl2;
+ values[2] = &in3;
+ values[3] = &fl4;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
+ &ffi_type_float, args) == FFI_OK);
+ fl1 = 127.0;
+ fl2 = 128.0;
+ in3 = 255;
+ fl4 = 512.7;
+
+ ffi_call(&cif, FFI_FN(return_fl), &rfl, values);
+ printf ("%f vs %f\n", rfl, return_fl(fl1, fl2, in3, fl4));
+ CHECK(rfl == fl1 + fl2 + in3 + fl4);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_ldl.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_ldl.c
new file mode 100644
index 0000000000..52a92fe071
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_ldl.c
@@ -0,0 +1,34 @@
+/* Area: ffi_call
+ Purpose: Check return value long double.
+ Limitations: none.
+ PR: none.
+ Originator: <andreast@gcc.gnu.org> 20071113 */
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static long double return_ldl(long double ldl)
+{
+ return 2*ldl;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ long double ldl, rldl;
+
+ args[0] = &ffi_type_longdouble;
+ values[0] = &ldl;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_longdouble, args) == FFI_OK);
+
+ for (ldl = -127.0; ldl < 127.0; ldl++)
+ {
+ ffi_call(&cif, FFI_FN(return_ldl), &rldl, values);
+ CHECK(rldl == 2 * ldl);
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_ll.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_ll.c
new file mode 100644
index 0000000000..ea4a1e4478
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_ll.c
@@ -0,0 +1,41 @@
+/* Area: ffi_call
+ Purpose: Check return value long long.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long long return_ll(long long ll)
+{
+ return ll;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ long long rlonglong;
+ long long ll;
+
+ args[0] = &ffi_type_sint64;
+ values[0] = &ll;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_sint64, args) == FFI_OK);
+
+ for (ll = 0LL; ll < 100LL; ll++)
+ {
+ ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+ CHECK(rlonglong == ll);
+ }
+
+ for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
+ {
+ ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+ CHECK(rlonglong == ll);
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_ll1.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_ll1.c
new file mode 100644
index 0000000000..593e8a307c
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_ll1.c
@@ -0,0 +1,43 @@
+/* Area: ffi_call
+ Purpose: Check if long long are passed in the corresponding regs on ppc.
+ Limitations: none.
+ PR: 20104.
+ Originator: <andreast@gcc.gnu.org> 20050222 */
+
+/* { dg-do run } */
+/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
+#include "ffitest.h"
+static long long return_ll(int ll0, long long ll1, int ll2)
+{
+ return ll0 + ll1 + ll2;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ long long rlonglong;
+ long long ll1;
+ unsigned ll0, ll2;
+
+ args[0] = &ffi_type_sint;
+ args[1] = &ffi_type_sint64;
+ args[2] = &ffi_type_sint;
+ values[0] = &ll0;
+ values[1] = &ll1;
+ values[2] = &ll2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3,
+ &ffi_type_sint64, args) == FFI_OK);
+
+ ll0 = 11111111;
+ ll1 = 11111111111000LL;
+ ll2 = 11111111;
+
+ ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
+ printf("res: %" PRIdLL ", %" PRIdLL "\n", rlonglong, ll0 + ll1 + ll2);
+ /* { dg-output "res: 11111133333222, 11111133333222" } */
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_sc.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_sc.c
new file mode 100644
index 0000000000..a36cf3eb88
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_sc.c
@@ -0,0 +1,36 @@
+/* Area: ffi_call
+ Purpose: Check return value signed char.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static signed char return_sc(signed char sc)
+{
+ return sc;
+}
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+ signed char sc;
+
+ args[0] = &ffi_type_schar;
+ values[0] = &sc;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_schar, args) == FFI_OK);
+
+ for (sc = (signed char) -127;
+ sc < (signed char) 127; sc++)
+ {
+ ffi_call(&cif, FFI_FN(return_sc), &rint, values);
+ CHECK((signed char)rint == sc);
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_sl.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_sl.c
new file mode 100644
index 0000000000..f0fd345f7a
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_sl.c
@@ -0,0 +1,38 @@
+/* Area: ffi_call
+ Purpose: Check if long as return type is handled correctly.
+ Limitations: none.
+ PR: none.
+ */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static long return_sl(long l1, long l2)
+{
+ return l1 - l2;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg res;
+ unsigned long l1, l2;
+
+ args[0] = &ffi_type_slong;
+ args[1] = &ffi_type_slong;
+ values[0] = &l1;
+ values[1] = &l2;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+ &ffi_type_slong, args) == FFI_OK);
+
+ l1 = 1073741823L;
+ l2 = 1073741824L;
+
+ ffi_call(&cif, FFI_FN(return_sl), &res, values);
+ printf("res: %ld, %ld\n", (long)res, l1 - l2);
+ /* { dg-output "res: -1, -1" } */
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_uc.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_uc.c
new file mode 100644
index 0000000000..6fe554619d
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_uc.c
@@ -0,0 +1,38 @@
+/* Area: ffi_call
+ Purpose: Check return value unsigned char.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static unsigned char return_uc(unsigned char uc)
+{
+ return uc;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+
+ unsigned char uc;
+
+ args[0] = &ffi_type_uchar;
+ values[0] = &uc;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ffi_type_uchar, args) == FFI_OK);
+
+ for (uc = (unsigned char) '\x00';
+ uc < (unsigned char) '\xff'; uc++)
+ {
+ ffi_call(&cif, FFI_FN(return_uc), &rint, values);
+ CHECK((unsigned char)rint == uc);
+ }
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/return_ul.c b/js/src/ctypes/libffi/testsuite/libffi.call/return_ul.c
new file mode 100644
index 0000000000..12b266f037
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/return_ul.c
@@ -0,0 +1,38 @@
+/* Area: ffi_call
+ Purpose: Check if unsigned long as return type is handled correctly.
+ Limitations: none.
+ PR: none.
+ Originator: <kaffeetisch at gmx dot de> 20060724 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+static unsigned long return_ul(unsigned long ul1, unsigned long ul2)
+{
+ return ul1 + ul2;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg res;
+ unsigned long ul1, ul2;
+
+ args[0] = &ffi_type_ulong;
+ args[1] = &ffi_type_ulong;
+ values[0] = &ul1;
+ values[1] = &ul2;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
+ &ffi_type_ulong, args) == FFI_OK);
+
+ ul1 = 1073741823L;
+ ul2 = 1073741824L;
+
+ ffi_call(&cif, FFI_FN(return_ul), &res, values);
+ printf("res: %lu, %lu\n", (unsigned long)res, ul1 + ul2);
+ /* { dg-output "res: 2147483647, 2147483647" } */
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/strlen.c b/js/src/ctypes/libffi/testsuite/libffi.call/strlen.c
new file mode 100644
index 0000000000..35b70ea4e2
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/strlen.c
@@ -0,0 +1,44 @@
+/* Area: ffi_call
+ Purpose: Check strlen function call.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_strlen(char *s)
+{
+ return (strlen(s));
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+ char *s;
+
+ args[0] = &ffi_type_pointer;
+ values[0] = (void*) &s;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
+ &ffi_type_sint, args) == FFI_OK);
+
+ s = "a";
+ ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+ CHECK(rint == 1);
+
+ s = "1234567";
+ ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+ CHECK(rint == 7);
+
+ s = "1234567890123456789012345";
+ ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
+ CHECK(rint == 25);
+
+ exit (0);
+}
+
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/strlen2.c b/js/src/ctypes/libffi/testsuite/libffi.call/strlen2.c
new file mode 100644
index 0000000000..96282bc0a1
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/strlen2.c
@@ -0,0 +1,49 @@
+/* Area: ffi_call
+ Purpose: Check strlen function call with additional arguments.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_f(char *s, float a)
+{
+ return (size_t) ((int) strlen(s) + (int) a);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+ char *s;
+ float v2;
+ args[0] = &ffi_type_pointer;
+ args[1] = &ffi_type_float;
+ values[0] = (void*) &s;
+ values[1] = (void*) &v2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 2,
+ &ffi_type_sint, args) == FFI_OK);
+
+ s = "a";
+ v2 = 0.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 1);
+
+ s = "1234567";
+ v2 = -1.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 6);
+
+ s = "1234567890123456789012345";
+ v2 = 1.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 26);
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/strlen3.c b/js/src/ctypes/libffi/testsuite/libffi.call/strlen3.c
new file mode 100644
index 0000000000..beba86e9ea
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/strlen3.c
@@ -0,0 +1,49 @@
+/* Area: ffi_call
+ Purpose: Check strlen function call with additional arguments.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_f(float a, char *s)
+{
+ return (size_t) ((int) strlen(s) + (int) a);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+ char *s;
+ float v2;
+ args[1] = &ffi_type_pointer;
+ args[0] = &ffi_type_float;
+ values[1] = (void*) &s;
+ values[0] = (void*) &v2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 2,
+ &ffi_type_sint, args) == FFI_OK);
+
+ s = "a";
+ v2 = 0.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 1);
+
+ s = "1234567";
+ v2 = -1.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 6);
+
+ s = "1234567890123456789012345";
+ v2 = 1.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 26);
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/strlen4.c b/js/src/ctypes/libffi/testsuite/libffi.call/strlen4.c
new file mode 100644
index 0000000000..d5d42b4f6d
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/strlen4.c
@@ -0,0 +1,55 @@
+/* Area: ffi_call
+ Purpose: Check strlen function call with additional arguments.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+
+#include "ffitest.h"
+
+static size_t ABI_ATTR my_f(float a, char *s, int i)
+{
+ return (size_t) ((int) strlen(s) + (int) a + i);
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_arg rint;
+ char *s;
+ int v1;
+ float v2;
+ args[2] = &ffi_type_sint;
+ args[1] = &ffi_type_pointer;
+ args[0] = &ffi_type_float;
+ values[2] = (void*) &v1;
+ values[1] = (void*) &s;
+ values[0] = (void*) &v2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 3,
+ &ffi_type_sint, args) == FFI_OK);
+
+ s = "a";
+ v1 = 1;
+ v2 = 0.0;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 2);
+
+ s = "1234567";
+ v2 = -1.0;
+ v1 = -2;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 4);
+
+ s = "1234567890123456789012345";
+ v2 = 1.0;
+ v1 = 2;
+ ffi_call(&cif, FFI_FN(my_f), &rint, values);
+ CHECK(rint == 28);
+
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct1.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct1.c
new file mode 100644
index 0000000000..c13e23f872
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct1.c
@@ -0,0 +1,67 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ unsigned char uc;
+ double d;
+ unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 ABI_ATTR struct1(test_structure_1 ts)
+{
+ ts.uc++;
+ ts.d--;
+ ts.ui++;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts1_type;
+ ffi_type *ts1_type_elements[4];
+
+ test_structure_1 ts1_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_1 *ts1_result =
+ (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+ 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_uchar;
+ ts1_type_elements[1] = &ffi_type_double;
+ ts1_type_elements[2] = &ffi_type_uint;
+ ts1_type_elements[3] = NULL;
+
+ args[0] = &ts1_type;
+ values[0] = &ts1_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
+ &ts1_type, args) == FFI_OK);
+
+ ts1_arg.uc = '\x01';
+ ts1_arg.d = 3.14159;
+ ts1_arg.ui = 555;
+
+ ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+ CHECK(ts1_result->ui == 556);
+ CHECK(ts1_result->d == 3.14159 - 1);
+
+ free (ts1_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct10.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct10.c
new file mode 100644
index 0000000000..17b1377424
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct10.c
@@ -0,0 +1,57 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: Sergei Trofimovich <slyfox@gentoo.org>
+
+ The test originally discovered in ruby's bindings
+ for ffi in https://bugs.gentoo.org/634190 */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+struct s {
+ int s32;
+ float f32;
+ signed char s8;
+};
+
+struct s make_s(void) {
+ struct s r;
+ r.s32 = 0x1234;
+ r.f32 = 7.0;
+ r.s8 = 0x78;
+ return r;
+}
+
+int main() {
+ ffi_cif cif;
+ struct s r;
+ ffi_type rtype;
+ ffi_type* s_fields[] = {
+ &ffi_type_sint,
+ &ffi_type_float,
+ &ffi_type_schar,
+ NULL,
+ };
+
+ rtype.size = 0;
+ rtype.alignment = 0,
+ rtype.type = FFI_TYPE_STRUCT,
+ rtype.elements = s_fields,
+
+ r.s32 = 0xbad;
+ r.f32 = 999.999;
+ r.s8 = 0x51;
+
+ // Here we emulate the following call:
+ //r = make_s();
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &rtype, NULL) == FFI_OK);
+ ffi_call(&cif, FFI_FN(make_s), &r, NULL);
+
+ CHECK(r.s32 == 0x1234);
+ CHECK(r.f32 == 7.0);
+ CHECK(r.s8 == 0x78);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct2.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct2.c
new file mode 100644
index 0000000000..5077a5ee45
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct2.c
@@ -0,0 +1,67 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ double d1;
+ double d2;
+} test_structure_2;
+
+static test_structure_2 ABI_ATTR struct2(test_structure_2 ts)
+{
+ ts.d1--;
+ ts.d2--;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ test_structure_2 ts2_arg;
+ ffi_type ts2_type;
+ ffi_type *ts2_type_elements[3];
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_2 *ts2_result =
+ (test_structure_2 *) malloc (sizeof(test_structure_2));
+
+ ts2_type.size = 0;
+ ts2_type.alignment = 0;
+ ts2_type.type = FFI_TYPE_STRUCT;
+ ts2_type.elements = ts2_type_elements;
+ ts2_type_elements[0] = &ffi_type_double;
+ ts2_type_elements[1] = &ffi_type_double;
+ ts2_type_elements[2] = NULL;
+
+ args[0] = &ts2_type;
+ values[0] = &ts2_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts2_type, args) == FFI_OK);
+
+ ts2_arg.d1 = 5.55;
+ ts2_arg.d2 = 6.66;
+
+ printf ("%g\n", ts2_arg.d1);
+ printf ("%g\n", ts2_arg.d2);
+
+ ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
+
+ printf ("%g\n", ts2_result->d1);
+ printf ("%g\n", ts2_result->d2);
+
+ CHECK(ts2_result->d1 == 5.55 - 1);
+ CHECK(ts2_result->d2 == 6.66 - 1);
+
+ free (ts2_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct3.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct3.c
new file mode 100644
index 0000000000..7eba0ead6d
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct3.c
@@ -0,0 +1,60 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ int si;
+} test_structure_3;
+
+static test_structure_3 ABI_ATTR struct3(test_structure_3 ts)
+{
+ ts.si = -(ts.si*2);
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ int compare_value;
+ ffi_type ts3_type;
+ ffi_type *ts3_type_elements[2];
+
+ test_structure_3 ts3_arg;
+ test_structure_3 *ts3_result =
+ (test_structure_3 *) malloc (sizeof(test_structure_3));
+
+ ts3_type.size = 0;
+ ts3_type.alignment = 0;
+ ts3_type.type = FFI_TYPE_STRUCT;
+ ts3_type.elements = ts3_type_elements;
+ ts3_type_elements[0] = &ffi_type_sint;
+ ts3_type_elements[1] = NULL;
+
+ args[0] = &ts3_type;
+ values[0] = &ts3_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1,
+ &ts3_type, args) == FFI_OK);
+
+ ts3_arg.si = -123;
+ compare_value = ts3_arg.si;
+
+ ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
+
+ printf ("%d %d\n", ts3_result->si, -(compare_value*2));
+
+ CHECK(ts3_result->si == -(compare_value*2));
+
+ free (ts3_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct4.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct4.c
new file mode 100644
index 0000000000..66a9551dd6
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct4.c
@@ -0,0 +1,64 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ unsigned ui1;
+ unsigned ui2;
+ unsigned ui3;
+} test_structure_4;
+
+static test_structure_4 ABI_ATTR struct4(test_structure_4 ts)
+{
+ ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts4_type;
+ ffi_type *ts4_type_elements[4];
+
+ test_structure_4 ts4_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_4 *ts4_result =
+ (test_structure_4 *) malloc (sizeof(test_structure_4));
+
+ ts4_type.size = 0;
+ ts4_type.alignment = 0;
+ ts4_type.type = FFI_TYPE_STRUCT;
+ ts4_type.elements = ts4_type_elements;
+ ts4_type_elements[0] = &ffi_type_uint;
+ ts4_type_elements[1] = &ffi_type_uint;
+ ts4_type_elements[2] = &ffi_type_uint;
+ ts4_type_elements[3] = NULL;
+
+ args[0] = &ts4_type;
+ values[0] = &ts4_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts4_type, args) == FFI_OK);
+
+ ts4_arg.ui1 = 2;
+ ts4_arg.ui2 = 3;
+ ts4_arg.ui3 = 4;
+
+ ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
+
+ CHECK(ts4_result->ui3 == 2U * 3U * 4U);
+
+
+ free (ts4_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct5.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct5.c
new file mode 100644
index 0000000000..23e2a3f745
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct5.c
@@ -0,0 +1,66 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+ char c1;
+ char c2;
+} test_structure_5;
+
+static test_structure_5 ABI_ATTR struct5(test_structure_5 ts1, test_structure_5 ts2)
+{
+ ts1.c1 += ts2.c1;
+ ts1.c2 -= ts2.c2;
+
+ return ts1;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts5_type;
+ ffi_type *ts5_type_elements[3];
+
+ test_structure_5 ts5_arg1, ts5_arg2;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_5 *ts5_result =
+ (test_structure_5 *) malloc (sizeof(test_structure_5));
+
+ ts5_type.size = 0;
+ ts5_type.alignment = 0;
+ ts5_type.type = FFI_TYPE_STRUCT;
+ ts5_type.elements = ts5_type_elements;
+ ts5_type_elements[0] = &ffi_type_schar;
+ ts5_type_elements[1] = &ffi_type_schar;
+ ts5_type_elements[2] = NULL;
+
+ args[0] = &ts5_type;
+ args[1] = &ts5_type;
+ values[0] = &ts5_arg1;
+ values[1] = &ts5_arg2;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 2, &ts5_type, args) == FFI_OK);
+
+ ts5_arg1.c1 = 2;
+ ts5_arg1.c2 = 6;
+ ts5_arg2.c1 = 5;
+ ts5_arg2.c2 = 3;
+
+ ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
+
+ CHECK(ts5_result->c1 == 7);
+ CHECK(ts5_result->c2 == 3);
+
+
+ free (ts5_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct6.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct6.c
new file mode 100644
index 0000000000..173c66eb4d
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct6.c
@@ -0,0 +1,64 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+ float f;
+ double d;
+} test_structure_6;
+
+static test_structure_6 ABI_ATTR struct6 (test_structure_6 ts)
+{
+ ts.f += 1;
+ ts.d += 1;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts6_type;
+ ffi_type *ts6_type_elements[3];
+
+ test_structure_6 ts6_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_6 *ts6_result =
+ (test_structure_6 *) malloc (sizeof(test_structure_6));
+
+ ts6_type.size = 0;
+ ts6_type.alignment = 0;
+ ts6_type.type = FFI_TYPE_STRUCT;
+ ts6_type.elements = ts6_type_elements;
+ ts6_type_elements[0] = &ffi_type_float;
+ ts6_type_elements[1] = &ffi_type_double;
+ ts6_type_elements[2] = NULL;
+
+ args[0] = &ts6_type;
+ values[0] = &ts6_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts6_type, args) == FFI_OK);
+
+ ts6_arg.f = 5.55f;
+ ts6_arg.d = 6.66;
+
+ printf ("%g\n", ts6_arg.f);
+ printf ("%g\n", ts6_arg.d);
+
+ ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
+
+ CHECK(ts6_result->f == 5.55f + 1);
+ CHECK(ts6_result->d == 6.66 + 1);
+
+ free (ts6_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct7.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct7.c
new file mode 100644
index 0000000000..badc7e0556
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct7.c
@@ -0,0 +1,74 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+ float f1;
+ float f2;
+ double d;
+} test_structure_7;
+
+static test_structure_7 ABI_ATTR struct7 (test_structure_7 ts)
+{
+ ts.f1 += 1;
+ ts.f2 += 1;
+ ts.d += 1;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts7_type;
+ ffi_type *ts7_type_elements[4];
+
+ test_structure_7 ts7_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_7 *ts7_result =
+ (test_structure_7 *) malloc (sizeof(test_structure_7));
+
+ ts7_type.size = 0;
+ ts7_type.alignment = 0;
+ ts7_type.type = FFI_TYPE_STRUCT;
+ ts7_type.elements = ts7_type_elements;
+ ts7_type_elements[0] = &ffi_type_float;
+ ts7_type_elements[1] = &ffi_type_float;
+ ts7_type_elements[2] = &ffi_type_double;
+ ts7_type_elements[3] = NULL;
+
+ args[0] = &ts7_type;
+ values[0] = &ts7_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts7_type, args) == FFI_OK);
+
+ ts7_arg.f1 = 5.55f;
+ ts7_arg.f2 = 55.5f;
+ ts7_arg.d = 6.66;
+
+ printf ("%g\n", ts7_arg.f1);
+ printf ("%g\n", ts7_arg.f2);
+ printf ("%g\n", ts7_arg.d);
+
+ ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
+
+ printf ("%g\n", ts7_result->f1);
+ printf ("%g\n", ts7_result->f2);
+ printf ("%g\n", ts7_result->d);
+
+ CHECK(ts7_result->f1 == 5.55f + 1);
+ CHECK(ts7_result->f2 == 55.5f + 1);
+ CHECK(ts7_result->d == 6.66 + 1);
+
+ free (ts7_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct8.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct8.c
new file mode 100644
index 0000000000..ef204ecbbc
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct8.c
@@ -0,0 +1,81 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+typedef struct
+{
+ float f1;
+ float f2;
+ float f3;
+ float f4;
+} test_structure_8;
+
+static test_structure_8 ABI_ATTR struct8 (test_structure_8 ts)
+{
+ ts.f1 += 1;
+ ts.f2 += 1;
+ ts.f3 += 1;
+ ts.f4 += 1;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts8_type;
+ ffi_type *ts8_type_elements[5];
+
+ test_structure_8 ts8_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_8 *ts8_result =
+ (test_structure_8 *) malloc (sizeof(test_structure_8));
+
+ ts8_type.size = 0;
+ ts8_type.alignment = 0;
+ ts8_type.type = FFI_TYPE_STRUCT;
+ ts8_type.elements = ts8_type_elements;
+ ts8_type_elements[0] = &ffi_type_float;
+ ts8_type_elements[1] = &ffi_type_float;
+ ts8_type_elements[2] = &ffi_type_float;
+ ts8_type_elements[3] = &ffi_type_float;
+ ts8_type_elements[4] = NULL;
+
+ args[0] = &ts8_type;
+ values[0] = &ts8_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts8_type, args) == FFI_OK);
+
+ ts8_arg.f1 = 5.55f;
+ ts8_arg.f2 = 55.5f;
+ ts8_arg.f3 = -5.55f;
+ ts8_arg.f4 = -55.5f;
+
+ printf ("%g\n", ts8_arg.f1);
+ printf ("%g\n", ts8_arg.f2);
+ printf ("%g\n", ts8_arg.f3);
+ printf ("%g\n", ts8_arg.f4);
+
+ ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
+
+ printf ("%g\n", ts8_result->f1);
+ printf ("%g\n", ts8_result->f2);
+ printf ("%g\n", ts8_result->f3);
+ printf ("%g\n", ts8_result->f4);
+
+ CHECK(ts8_result->f1 == 5.55f + 1);
+ CHECK(ts8_result->f2 == 55.5f + 1);
+ CHECK(ts8_result->f3 == -5.55f + 1);
+ CHECK(ts8_result->f4 == -55.5f + 1);
+
+ free (ts8_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/struct9.c b/js/src/ctypes/libffi/testsuite/libffi.call/struct9.c
new file mode 100644
index 0000000000..4a13b818c4
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/struct9.c
@@ -0,0 +1,68 @@
+/* Area: ffi_call
+ Purpose: Check structures.
+ Limitations: none.
+ PR: none.
+ Originator: From the original ffitest.c */
+
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ float f;
+ int i;
+} test_structure_9;
+
+static test_structure_9 ABI_ATTR struct9 (test_structure_9 ts)
+{
+ ts.f += 1;
+ ts.i += 1;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts9_type;
+ ffi_type *ts9_type_elements[3];
+
+ test_structure_9 ts9_arg;
+
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_9 *ts9_result =
+ (test_structure_9 *) malloc (sizeof(test_structure_9));
+
+ ts9_type.size = 0;
+ ts9_type.alignment = 0;
+ ts9_type.type = FFI_TYPE_STRUCT;
+ ts9_type.elements = ts9_type_elements;
+ ts9_type_elements[0] = &ffi_type_float;
+ ts9_type_elements[1] = &ffi_type_sint;
+ ts9_type_elements[2] = NULL;
+
+ args[0] = &ts9_type;
+ values[0] = &ts9_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, ABI_NUM, 1, &ts9_type, args) == FFI_OK);
+
+ ts9_arg.f = 5.55f;
+ ts9_arg.i = 5;
+
+ printf ("%g\n", ts9_arg.f);
+ printf ("%d\n", ts9_arg.i);
+
+ ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
+
+ printf ("%g\n", ts9_result->f);
+ printf ("%d\n", ts9_result->i);
+
+ CHECK(ts9_result->f == 5.55f + 1);
+ CHECK(ts9_result->i == 5 + 1);
+
+ free (ts9_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/uninitialized.c b/js/src/ctypes/libffi/testsuite/libffi.call/uninitialized.c
new file mode 100644
index 0000000000..f00d830234
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/uninitialized.c
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+#include "ffitest.h"
+
+typedef struct
+{
+ unsigned char uc;
+ double d;
+ unsigned int ui;
+} test_structure_1;
+
+static test_structure_1 struct1(test_structure_1 ts)
+{
+ ts.uc++;
+ ts.d--;
+ ts.ui++;
+
+ return ts;
+}
+
+int main (void)
+{
+ ffi_cif cif;
+ ffi_type *args[MAX_ARGS];
+ void *values[MAX_ARGS];
+ ffi_type ts1_type;
+ ffi_type *ts1_type_elements[4];
+
+ memset(&cif, 1, sizeof(cif));
+ 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_uchar;
+ ts1_type_elements[1] = &ffi_type_double;
+ ts1_type_elements[2] = &ffi_type_uint;
+ ts1_type_elements[3] = NULL;
+
+ test_structure_1 ts1_arg;
+ /* This is a hack to get a properly aligned result buffer */
+ test_structure_1 *ts1_result =
+ (test_structure_1 *) malloc (sizeof(test_structure_1));
+
+ args[0] = &ts1_type;
+ values[0] = &ts1_arg;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ &ts1_type, args) == FFI_OK);
+
+ ts1_arg.uc = '\x01';
+ ts1_arg.d = 3.14159;
+ ts1_arg.ui = 555;
+
+ ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
+
+ CHECK(ts1_result->ui == 556);
+ CHECK(ts1_result->d == 3.14159 - 1);
+
+ free (ts1_result);
+ exit(0);
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/va_1.c b/js/src/ctypes/libffi/testsuite/libffi.call/va_1.c
new file mode 100644
index 0000000000..59d085c832
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/va_1.c
@@ -0,0 +1,196 @@
+/* Area: ffi_call
+ Purpose: Test passing struct in variable argument lists.
+ Limitations: none.
+ PR: none.
+ Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* m68k-*-* alpha-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+ unsigned char a;
+ unsigned char b;
+};
+
+struct large_tag
+{
+ unsigned a;
+ unsigned b;
+ unsigned c;
+ unsigned d;
+ unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+ va_list ap;
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l;
+ unsigned char uc;
+ signed char sc;
+ unsigned short us;
+ signed short ss;
+ unsigned int ui;
+ signed int si;
+ unsigned long ul;
+ signed long sl;
+ float f;
+ double d;
+
+ va_start (ap, n);
+ s1 = va_arg (ap, struct small_tag);
+ l = va_arg (ap, struct large_tag);
+ s2 = va_arg (ap, struct small_tag);
+
+ uc = va_arg (ap, unsigned);
+ sc = va_arg (ap, signed);
+
+ us = va_arg (ap, unsigned);
+ ss = va_arg (ap, signed);
+
+ ui = va_arg (ap, unsigned int);
+ si = va_arg (ap, signed int);
+
+ ul = va_arg (ap, unsigned long);
+ sl = va_arg (ap, signed long);
+
+ f = va_arg (ap, double); /* C standard promotes float->double
+ when anonymous */
+ d = va_arg (ap, double);
+
+ printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
+ s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+ s2.a, s2.b,
+ uc, sc,
+ us, ss,
+ ui, si,
+ ul, sl,
+ f, d);
+ va_end (ap);
+ return n + 1;
+}
+
+int
+main (void)
+{
+ ffi_cif cif;
+ void* args[15];
+ ffi_type* arg_types[15];
+
+ ffi_type s_type;
+ ffi_type *s_type_elements[3];
+
+ ffi_type l_type;
+ ffi_type *l_type_elements[6];
+
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l1;
+
+ int n;
+ ffi_arg res;
+
+ unsigned char uc;
+ signed char sc;
+ unsigned short us;
+ signed short ss;
+ unsigned int ui;
+ signed int si;
+ unsigned long ul;
+ signed long sl;
+ double d1;
+ double f1;
+
+ s_type.size = 0;
+ s_type.alignment = 0;
+ s_type.type = FFI_TYPE_STRUCT;
+ s_type.elements = s_type_elements;
+
+ s_type_elements[0] = &ffi_type_uchar;
+ s_type_elements[1] = &ffi_type_uchar;
+ s_type_elements[2] = NULL;
+
+ l_type.size = 0;
+ l_type.alignment = 0;
+ l_type.type = FFI_TYPE_STRUCT;
+ l_type.elements = l_type_elements;
+
+ l_type_elements[0] = &ffi_type_uint;
+ l_type_elements[1] = &ffi_type_uint;
+ l_type_elements[2] = &ffi_type_uint;
+ l_type_elements[3] = &ffi_type_uint;
+ l_type_elements[4] = &ffi_type_uint;
+ l_type_elements[5] = NULL;
+
+ arg_types[0] = &ffi_type_sint;
+ arg_types[1] = &s_type;
+ arg_types[2] = &l_type;
+ arg_types[3] = &s_type;
+ arg_types[4] = &ffi_type_uchar;
+ arg_types[5] = &ffi_type_schar;
+ arg_types[6] = &ffi_type_ushort;
+ arg_types[7] = &ffi_type_sshort;
+ arg_types[8] = &ffi_type_uint;
+ arg_types[9] = &ffi_type_sint;
+ arg_types[10] = &ffi_type_ulong;
+ arg_types[11] = &ffi_type_slong;
+ arg_types[12] = &ffi_type_double;
+ arg_types[13] = &ffi_type_double;
+ arg_types[14] = NULL;
+
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
+
+ s1.a = 5;
+ s1.b = 6;
+
+ l1.a = 10;
+ l1.b = 11;
+ l1.c = 12;
+ l1.d = 13;
+ l1.e = 14;
+
+ s2.a = 7;
+ s2.b = 8;
+
+ n = 41;
+
+ uc = 9;
+ sc = 10;
+ us = 11;
+ ss = 12;
+ ui = 13;
+ si = 14;
+ ul = 15;
+ sl = 16;
+ f1 = 2.12;
+ d1 = 3.13;
+
+ args[0] = &n;
+ args[1] = &s1;
+ args[2] = &l1;
+ args[3] = &s2;
+ args[4] = &uc;
+ args[5] = &sc;
+ args[6] = &us;
+ args[7] = &ss;
+ args[8] = &ui;
+ args[9] = &si;
+ args[10] = &ul;
+ args[11] = &sl;
+ args[12] = &f1;
+ args[13] = &d1;
+ args[14] = NULL;
+
+ ffi_call(&cif, FFI_FN(test_fn), &res, args);
+ /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
+ printf("res: %d\n", (int) res);
+ /* { dg-output "\nres: 42" } */
+
+ return 0;
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/va_struct1.c b/js/src/ctypes/libffi/testsuite/libffi.call/va_struct1.c
new file mode 100644
index 0000000000..e6452061c1
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/va_struct1.c
@@ -0,0 +1,121 @@
+/* Area: ffi_call
+ Purpose: Test passing struct in variable argument lists.
+ Limitations: none.
+ PR: none.
+ Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+ unsigned char a;
+ unsigned char b;
+};
+
+struct large_tag
+{
+ unsigned a;
+ unsigned b;
+ unsigned c;
+ unsigned d;
+ unsigned e;
+};
+
+static int
+test_fn (int n, ...)
+{
+ va_list ap;
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l;
+
+ va_start (ap, n);
+ s1 = va_arg (ap, struct small_tag);
+ l = va_arg (ap, struct large_tag);
+ s2 = va_arg (ap, struct small_tag);
+ printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+ s2.a, s2.b);
+ va_end (ap);
+ return n + 1;
+}
+
+int
+main (void)
+{
+ ffi_cif cif;
+ void* args[5];
+ ffi_type* arg_types[5];
+
+ ffi_type s_type;
+ ffi_type *s_type_elements[3];
+
+ ffi_type l_type;
+ ffi_type *l_type_elements[6];
+
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l1;
+
+ int n;
+ ffi_arg res;
+
+ s_type.size = 0;
+ s_type.alignment = 0;
+ s_type.type = FFI_TYPE_STRUCT;
+ s_type.elements = s_type_elements;
+
+ s_type_elements[0] = &ffi_type_uchar;
+ s_type_elements[1] = &ffi_type_uchar;
+ s_type_elements[2] = NULL;
+
+ l_type.size = 0;
+ l_type.alignment = 0;
+ l_type.type = FFI_TYPE_STRUCT;
+ l_type.elements = l_type_elements;
+
+ l_type_elements[0] = &ffi_type_uint;
+ l_type_elements[1] = &ffi_type_uint;
+ l_type_elements[2] = &ffi_type_uint;
+ l_type_elements[3] = &ffi_type_uint;
+ l_type_elements[4] = &ffi_type_uint;
+ l_type_elements[5] = NULL;
+
+ arg_types[0] = &ffi_type_sint;
+ arg_types[1] = &s_type;
+ arg_types[2] = &l_type;
+ arg_types[3] = &s_type;
+ arg_types[4] = NULL;
+
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK);
+
+ s1.a = 5;
+ s1.b = 6;
+
+ l1.a = 10;
+ l1.b = 11;
+ l1.c = 12;
+ l1.d = 13;
+ l1.e = 14;
+
+ s2.a = 7;
+ s2.b = 8;
+
+ n = 41;
+
+ args[0] = &n;
+ args[1] = &s1;
+ args[2] = &l1;
+ args[3] = &s2;
+ args[4] = NULL;
+
+ ffi_call(&cif, FFI_FN(test_fn), &res, args);
+ /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+ printf("res: %d\n", (int) res);
+ /* { dg-output "\nres: 42" } */
+
+ return 0;
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/va_struct2.c b/js/src/ctypes/libffi/testsuite/libffi.call/va_struct2.c
new file mode 100644
index 0000000000..56f5b9c75f
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/va_struct2.c
@@ -0,0 +1,123 @@
+/* Area: ffi_call
+ Purpose: Test passing struct in variable argument lists.
+ Limitations: none.
+ PR: none.
+ Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+ unsigned char a;
+ unsigned char b;
+};
+
+struct large_tag
+{
+ unsigned a;
+ unsigned b;
+ unsigned c;
+ unsigned d;
+ unsigned e;
+};
+
+static struct small_tag
+test_fn (int n, ...)
+{
+ va_list ap;
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l;
+
+ va_start (ap, n);
+ s1 = va_arg (ap, struct small_tag);
+ l = va_arg (ap, struct large_tag);
+ s2 = va_arg (ap, struct small_tag);
+ printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+ s2.a, s2.b);
+ va_end (ap);
+ s1.a += s2.a;
+ s1.b += s2.b;
+ return s1;
+}
+
+int
+main (void)
+{
+ ffi_cif cif;
+ void* args[5];
+ ffi_type* arg_types[5];
+
+ ffi_type s_type;
+ ffi_type *s_type_elements[3];
+
+ ffi_type l_type;
+ ffi_type *l_type_elements[6];
+
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l1;
+
+ int n;
+ struct small_tag res;
+
+ s_type.size = 0;
+ s_type.alignment = 0;
+ s_type.type = FFI_TYPE_STRUCT;
+ s_type.elements = s_type_elements;
+
+ s_type_elements[0] = &ffi_type_uchar;
+ s_type_elements[1] = &ffi_type_uchar;
+ s_type_elements[2] = NULL;
+
+ l_type.size = 0;
+ l_type.alignment = 0;
+ l_type.type = FFI_TYPE_STRUCT;
+ l_type.elements = l_type_elements;
+
+ l_type_elements[0] = &ffi_type_uint;
+ l_type_elements[1] = &ffi_type_uint;
+ l_type_elements[2] = &ffi_type_uint;
+ l_type_elements[3] = &ffi_type_uint;
+ l_type_elements[4] = &ffi_type_uint;
+ l_type_elements[5] = NULL;
+
+ arg_types[0] = &ffi_type_sint;
+ arg_types[1] = &s_type;
+ arg_types[2] = &l_type;
+ arg_types[3] = &s_type;
+ arg_types[4] = NULL;
+
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &s_type, arg_types) == FFI_OK);
+
+ s1.a = 5;
+ s1.b = 6;
+
+ l1.a = 10;
+ l1.b = 11;
+ l1.c = 12;
+ l1.d = 13;
+ l1.e = 14;
+
+ s2.a = 7;
+ s2.b = 8;
+
+ n = 41;
+
+ args[0] = &n;
+ args[1] = &s1;
+ args[2] = &l1;
+ args[3] = &s2;
+ args[4] = NULL;
+
+ ffi_call(&cif, FFI_FN(test_fn), &res, args);
+ /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+ printf("res: %d %d\n", res.a, res.b);
+ /* { dg-output "\nres: 12 14" } */
+
+ return 0;
+}
diff --git a/js/src/ctypes/libffi/testsuite/libffi.call/va_struct3.c b/js/src/ctypes/libffi/testsuite/libffi.call/va_struct3.c
new file mode 100644
index 0000000000..9a27e7fd4a
--- /dev/null
+++ b/js/src/ctypes/libffi/testsuite/libffi.call/va_struct3.c
@@ -0,0 +1,125 @@
+/* Area: ffi_call
+ Purpose: Test passing struct in variable argument lists.
+ Limitations: none.
+ PR: none.
+ Originator: ARM Ltd. */
+
+/* { dg-do run } */
+/* { dg-output "" { xfail avr32*-*-* } } */
+
+#include "ffitest.h"
+#include <stdarg.h>
+
+struct small_tag
+{
+ unsigned char a;
+ unsigned char b;
+};
+
+struct large_tag
+{
+ unsigned a;
+ unsigned b;
+ unsigned c;
+ unsigned d;
+ unsigned e;
+};
+
+static struct large_tag
+test_fn (int n, ...)
+{
+ va_list ap;
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l;
+
+ va_start (ap, n);
+ s1 = va_arg (ap, struct small_tag);
+ l = va_arg (ap, struct large_tag);
+ s2 = va_arg (ap, struct small_tag);
+ printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
+ s2.a, s2.b);
+ va_end (ap);
+ l.a += s1.a;
+ l.b += s1.b;
+ l.c += s2.a;
+ l.d += s2.b;
+ return l;
+}
+
+int
+main (void)
+{
+ ffi_cif cif;
+ void* args[5];
+ ffi_type* arg_types[5];
+
+ ffi_type s_type;
+ ffi_type *s_type_elements[3];
+
+ ffi_type l_type;
+ ffi_type *l_type_elements[6];
+
+ struct small_tag s1;
+ struct small_tag s2;
+ struct large_tag l1;
+
+ int n;
+ struct large_tag res;
+
+ s_type.size = 0;
+ s_type.alignment = 0;
+ s_type.type = FFI_TYPE_STRUCT;
+ s_type.elements = s_type_elements;
+
+ s_type_elements[0] = &ffi_type_uchar;
+ s_type_elements[1] = &ffi_type_uchar;
+ s_type_elements[2] = NULL;
+
+ l_type.size = 0;
+ l_type.alignment = 0;
+ l_type.type = FFI_TYPE_STRUCT;
+ l_type.elements = l_type_elements;
+
+ l_type_elements[0] = &ffi_type_uint;
+ l_type_elements[1] = &ffi_type_uint;
+ l_type_elements[2] = &ffi_type_uint;
+ l_type_elements[3] = &ffi_type_uint;
+ l_type_elements[4] = &ffi_type_uint;
+ l_type_elements[5] = NULL;
+
+ arg_types[0] = &ffi_type_sint;
+ arg_types[1] = &s_type;
+ arg_types[2] = &l_type;
+ arg_types[3] = &s_type;
+ arg_types[4] = NULL;
+
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK);
+
+ s1.a = 5;
+ s1.b = 6;
+
+ l1.a = 10;
+ l1.b = 11;
+ l1.c = 12;
+ l1.d = 13;
+ l1.e = 14;
+
+ s2.a = 7;
+ s2.b = 8;
+
+ n = 41;
+
+ args[0] = &n;
+ args[1] = &s1;
+ args[2] = &l1;
+ args[3] = &s2;
+ args[4] = NULL;
+
+ ffi_call(&cif, FFI_FN(test_fn), &res, args);
+ /* { dg-output "5 6 10 11 12 13 14 7 8" } */
+ printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e);
+ /* { dg-output "\nres: 15 17 19 21 14" } */
+
+ return 0;
+}