summaryrefslogtreecommitdiff
path: root/testsuite/libffi.special
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/libffi.special')
-rw-r--r--testsuite/libffi.special/ffitestcxx.h96
-rw-r--r--testsuite/libffi.special/special.exp37
-rw-r--r--testsuite/libffi.special/unwindtest.cc124
-rw-r--r--testsuite/libffi.special/unwindtest_ffi_call.cc53
4 files changed, 310 insertions, 0 deletions
diff --git a/testsuite/libffi.special/ffitestcxx.h b/testsuite/libffi.special/ffitestcxx.h
new file mode 100644
index 0000000..e300cce
--- /dev/null
+++ b/testsuite/libffi.special/ffitestcxx.h
@@ -0,0 +1,96 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <ffi.h>
+#include "fficonfig.h"
+
+#define MAX_ARGS 256
+
+
+/* Define __UNUSED__ that also other compilers than gcc can run the tests. */
+#undef __UNUSED__
+#if defined(__GNUC__)
+#define __UNUSED__ __attribute__((__unused__))
+#else
+#define __UNUSED__
+#endif
+
+#define CHECK(x) (!(x) ? abort() : (void)0)
+
+/* 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. */
+#ifdef _WIN64
+#define PRIdLL "I64d"
+#define PRIuLL "I64u"
+#else
+#define PRIdLL "lld"
+#define PRIuLL "llu"
+#endif
+
+#ifdef USING_MMAP
+static inline void *
+allocate_mmap (size_t size)
+{
+ void *page;
+#if defined (HAVE_MMAP_DEV_ZERO)
+ static int dev_zero_fd = -1;
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+ if (dev_zero_fd == -1)
+ {
+ dev_zero_fd = open ("/dev/zero", O_RDONLY);
+ if (dev_zero_fd == -1)
+ {
+ perror ("open /dev/zero: %m");
+ exit (1);
+ }
+ }
+#endif
+
+
+#ifdef HAVE_MMAP_ANON
+ page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+#ifdef HAVE_MMAP_DEV_ZERO
+ page = mmap (NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE, dev_zero_fd, 0);
+#endif
+
+ if (page == MAP_FAILED)
+ {
+ perror ("virtual memory exhausted");
+ exit (1);
+ }
+
+ return page;
+}
+
+#endif
diff --git a/testsuite/libffi.special/special.exp b/testsuite/libffi.special/special.exp
new file mode 100644
index 0000000..e167e86
--- /dev/null
+++ b/testsuite/libffi.special/special.exp
@@ -0,0 +1,37 @@
+# Copyright (C) 2003, 2006, 2009 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/>.
+
+load_lib libffi-dg.exp
+
+dg-init
+libffi-init
+
+global srcdir subdir
+
+global cxx_options
+
+set cxx_options " -shared-libgcc -lstdc++"
+
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O0 -W -Wall"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O2"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-O3"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] $cxx_options "-Os"
+
+dg-finish
+
+# Local Variables:
+# tcl-indent-level:4
+# End:
diff --git a/testsuite/libffi.special/unwindtest.cc b/testsuite/libffi.special/unwindtest.cc
new file mode 100644
index 0000000..d7ffd4a
--- /dev/null
+++ b/testsuite/libffi.special/unwindtest.cc
@@ -0,0 +1,124 @@
+/* Area: ffi_closure, unwind info
+ Purpose: Check if the unwind information is passed correctly.
+ Limitations: none.
+ PR: none.
+ Originator: Jeff Sturm <jsturm@one-point.com> */
+
+/* { dg-do run } */
+#include "ffitestcxx.h"
+
+#if defined HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#if defined HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+void
+closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
+ void** args __UNUSED__, void* userdata __UNUSED__)
+{
+ throw 9;
+}
+
+typedef void (*closure_test_type)();
+
+void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp,
+ void** args, void* userdata __UNUSED__)
+ {
+ *(ffi_arg*)resp =
+ (int)*(float *)args[0] +(int)(*(float *)args[1]) +
+ (int)(*(float *)args[2]) + (int)*(float *)args[3] +
+ (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
+ (int)*(float *)args[6] + (int)(*(int *)args[7]) +
+ (int)(*(double*)args[8]) + (int)*(int *)args[9] +
+ (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
+ (int)*(int *)args[12] + (int)(*(int *)args[13]) +
+ (int)(*(int *)args[14]) + *(int *)args[15] + (int)(intptr_t)userdata;
+
+ printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
+ (int)*(float *)args[0], (int)(*(float *)args[1]),
+ (int)(*(float *)args[2]), (int)*(float *)args[3],
+ (int)(*(signed short *)args[4]), (int)(*(float *)args[5]),
+ (int)*(float *)args[6], (int)(*(int *)args[7]),
+ (int)(*(double *)args[8]), (int)*(int *)args[9],
+ (int)(*(int *)args[10]), (int)(*(float *)args[11]),
+ (int)*(int *)args[12], (int)(*(int *)args[13]),
+ (int)(*(int *)args[14]), *(int *)args[15],
+ (int)(intptr_t)userdata, (int)*(ffi_arg*)resp);
+
+ throw (int)*(ffi_arg*)resp;
+}
+
+typedef int (*closure_test_type1)(float, float, float, float, signed short,
+ float, float, int, double, int, int, float,
+ int, int, int, int);
+
+int main (void)
+{
+ ffi_cif cif;
+ void *code;
+ ffi_closure *pcl = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure), &code);
+ ffi_type * cl_arg_types[17];
+
+ {
+ cl_arg_types[1] = NULL;
+
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0,
+ &ffi_type_void, cl_arg_types) == FFI_OK);
+ CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn, NULL, code) == FFI_OK);
+
+ try
+ {
+ (*((closure_test_type)(code)))();
+ } catch (int exception_code)
+ {
+ CHECK(exception_code == 9);
+ }
+
+ printf("part one OK\n");
+ /* { dg-output "part one OK" } */
+ }
+
+ {
+
+ cl_arg_types[0] = &ffi_type_float;
+ cl_arg_types[1] = &ffi_type_float;
+ cl_arg_types[2] = &ffi_type_float;
+ cl_arg_types[3] = &ffi_type_float;
+ cl_arg_types[4] = &ffi_type_sshort;
+ cl_arg_types[5] = &ffi_type_float;
+ cl_arg_types[6] = &ffi_type_float;
+ cl_arg_types[7] = &ffi_type_uint;
+ cl_arg_types[8] = &ffi_type_double;
+ cl_arg_types[9] = &ffi_type_uint;
+ cl_arg_types[10] = &ffi_type_uint;
+ cl_arg_types[11] = &ffi_type_float;
+ cl_arg_types[12] = &ffi_type_uint;
+ cl_arg_types[13] = &ffi_type_uint;
+ cl_arg_types[14] = &ffi_type_uint;
+ cl_arg_types[15] = &ffi_type_uint;
+ cl_arg_types[16] = NULL;
+
+ /* Initialize the cif */
+ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
+ &ffi_type_sint, cl_arg_types) == FFI_OK);
+
+ CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn1,
+ (void *) 3 /* userdata */, code) == FFI_OK);
+ try
+ {
+ (*((closure_test_type1)code))
+ (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
+ 19, 21, 1);
+ /* { dg-output "\n1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */
+ } catch (int exception_code)
+ {
+ CHECK(exception_code == 255);
+ }
+ printf("part two OK\n");
+ /* { dg-output "\npart two OK" } */
+ }
+ exit(0);
+}
diff --git a/testsuite/libffi.special/unwindtest_ffi_call.cc b/testsuite/libffi.special/unwindtest_ffi_call.cc
new file mode 100644
index 0000000..29739cd
--- /dev/null
+++ b/testsuite/libffi.special/unwindtest_ffi_call.cc
@@ -0,0 +1,53 @@
+/* Area: ffi_call, unwind info
+ Purpose: Check if the unwind information is passed correctly.
+ Limitations: none.
+ PR: none.
+ Originator: Andreas Tobler <andreast@gcc.gnu.org> 20061213 */
+
+/* { dg-do run } */
+#include "ffitestcxx.h"
+
+static int checking(int a __UNUSED__, short b __UNUSED__,
+ signed char c __UNUSED__)
+{
+ throw 9;
+}
+
+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;
+ {
+ try
+ {
+ ffi_call(&cif, FFI_FN(checking), &rint, values);
+ } catch (int exception_code)
+ {
+ CHECK(exception_code == 9);
+ }
+ printf("part one OK\n");
+ /* { dg-output "part one OK" } */
+ }
+ exit(0);
+}