* Bug #680. Don't accept floats or small ints as var args.
* Bug #680. Don't accept floats or small ints as var args.
* Bug #680. Don't accept floats or small ints as var args.
The libffi library provides a portable, high level programming
interface to various calling conventions. This allows a programmer to
call any function specified by a call interface description at run
-time.
+time.
FFI stands for Foreign Function Interface. A foreign function
interface is the popular name for the interface that allows code
You may want to tell configure where to install the libffi library and
header files. To do that, use the ``--prefix`` configure switch. Libffi
-will install under /usr/local by default.
+will install under /usr/local by default.
If you want to enable extra run-time debugging checks use the the
``--enable-debug`` configure switch. This is useful when your program dies
-mysteriously while using libffi.
+mysteriously while using libffi.
Another useful configure switch is ``--enable-purify-safety``. Using this
will add some extra code which will suppress certain warnings when you
-are using Purify with libffi. Only use this switch when using
+are using Purify with libffi. Only use this switch when using
Purify, as it will slow down the library.
If you don't want to build documentation, use the ``--disable-docs``
It is also possible to build libffi on Windows platforms with the LLVM
project's clang-cl compiler, like below:
- path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
+ path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP"
When building with MSVC under a MingW environment, you may need to
remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath'
See the git log for details at http://github.com/libffi/libffi.
3.4 TBD
+ Add static trampoline support for Linux on x86_64 and ARM64.
Add support for Alibaba's CSKY architecture.
Add support for Intel Control-flow Enforcement Technology (CET).
- Add support for ARM Pointer Authentication (PA).
- Fix 32-bit PPC regression.
- Fix MIPS soft-float problem.
+ Add support for ARM Pointer Authentication (PA).
+ Fix 32-bit PPC regression.
+ Fix MIPS soft-float problem.
+ Reject float and small integer argument in ffi_prep_cif_var().
+ Callers must promote these types themselves.
3.3 Nov-23-19
Add RISC-V support.
Raw java (gcj) API deprecated.
Add pre-built PDF documentation to source distribution.
Many new test cases and bug fixes.
-
+
3.2.1 Nov-12-14
Build fix for non-iOS AArch64 targets.
-
+
3.2 Nov-11-14
Add C99 Complex Type support (currently only supported on
s390).
Windows/Linux.
Add OpenRISC and Cygwin-64 support.
Bug fixes.
-
+
3.1 May-19-14
Add AArch64 (ARM64) iOS support.
Add Nios II support.
failures, and respect the $CC and $CXX environment variables.
Archive off the manually maintained ChangeLog in favor of git
log.
-
+
3.0.13 Mar-17-13
Add Meta support.
Add missing Moxie bits.
Fix the install dir location for some platforms when building
with GCC (OS X, Solaris).
Fix Cygwin regression.
-
+
3.0.12 Feb-11-13
Add Moxie support.
Add AArch64 support.
Add support for native vendor compilers on
Solaris and AIX.
Work around LLVM/GCC interoperability issue on x86_64.
-
+
3.0.11 Apr-11-12
Lots of build fixes.
Add support for variadic functions (ffi_prep_cif_var).
Integration with iOS' xcode build tools.
Fix Octeon and MC68881 support.
Fix code pessimizations.
-
+
3.0.10 Aug-23-11
Add support for Apple's iOS.
Add support for ARM VFP ABI.
Solaris compiler.
Testsuite fixes for Tru64 Unix.
Additional platform support.
-
+
3.0.9 Dec-31-09
Add AVR32 and win64 ports. Add ARM softfp support.
Many fixes for AIX, Solaris, HP-UX, *BSD.
Several PowerPC and x86-64 bug fixes.
Build DLL for windows.
-
+
3.0.8 Dec-19-08
Add *BSD, BeOS, and PA-Linux support.
-
+
3.0.7 Nov-11-08
Fix for ppc FreeBSD.
(thanks to Andreas Tobler)
-
+
3.0.6 Jul-17-08
Fix for closures on sh.
Mark the sh/sh64 stack as non-executable.
(both thanks to Kaz Kojima)
-
+
3.0.5 Apr-3-08
Fix libffi.pc file.
Fix #define ARM for IcedTea users.
Fix x86 closure bug.
-
+
3.0.4 Feb-24-08
Fix x86 OpenBSD configury.
-
+
3.0.3 Feb-22-08
Enable x86 OpenBSD thanks to Thomas Heller, and
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
Clean up test instruction in README.
-
+
3.0.2 Feb-21-08
Improved x86 FreeBSD support.
Thanks to Björn König.
-
+
3.0.1 Feb-15-08
Fix instruction cache flushing bug on MIPS.
Thanks to David Daney.
-
+
3.0.0 Feb-15-08
Many changes, mostly thanks to the GCC project.
Cygnus Solutions is now Red Hat.
-
+
[10 years go by...]
-
+
1.20 Oct-5-98
Raffaele Sena produces ARM port.
-
+
1.19 Oct-5-98
Fixed x86 long double and long long return support.
m68k bug fixes from Andreas Schwab.
Patch for DU assembler compatibility for the Alpha from Richard
Henderson.
-
+
1.18 Apr-17-98
Bug fixes and MIPS configuration changes.
-
+
1.17 Feb-24-98
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
-
+
1.16 Feb-11-98
Richard Henderson produces Alpha port.
-
+
1.15 Dec-4-97
Fixed an n32 ABI bug. New libtool, auto* support.
-
+
1.14 May-13-97
libtool is now used to generate shared and static libraries.
Fixed a minor portability problem reported by Russ McManus
<mcmanr@eq.gs.com>.
-
+
1.13 Dec-2-96
Added --enable-purify-safety to keep Purify from complaining
about certain low level code.
Sparc fix for calling functions with < 6 args.
Linux x86 a.out fix.
-
+
1.12 Nov-22-96
- Added missing ffi_type_void, needed for supporting void return
- types. Fixed test case for non MIPS machines. Cygnus Support
- is now Cygnus Solutions.
-
+ Added missing ffi_type_void, needed for supporting void return
+ types. Fixed test case for non MIPS machines. Cygnus Support
+ is now Cygnus Solutions.
+
1.11 Oct-30-96
Added notes about GNU make.
-
+
1.10 Oct-29-96
Added configuration fix for non GNU compilers.
-
+
1.09 Oct-29-96
- Added --enable-debug configure switch. Clean-ups based on LCLint
- feedback. ffi_mips.h is always installed. Many configuration
+ Added --enable-debug configure switch. Clean-ups based on LCLint
+ feedback. ffi_mips.h is always installed. Many configuration
fixes. Fixed ffitest.c for sparc builds.
-
+
1.08 Oct-15-96
Fixed n32 problem. Many clean-ups.
-
+
1.07 Oct-14-96
Gordon Irlam rewrites v8.S again. Bug fixes.
-
+
1.06 Oct-14-96
- Gordon Irlam improved the sparc port.
-
+ Gordon Irlam improved the sparc port.
+
1.05 Oct-14-96
Interface changes based on feedback.
-
+
1.04 Oct-11-96
Sparc port complete (modulo struct passing bug).
-
+
1.03 Oct-10-96
Passing struct args, and returning struct values works for
all architectures/calling conventions. Expanded tests.
-
+
1.02 Oct-9-96
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
Added "make test".
-
+
1.01 Oct-8-96
Fixed float passing bug in mips version. Restructured some
of the code. Builds cleanly with SGI tools.
-
+
1.00 Oct-7-96
First release. No public announcement.
This manual is for libffi, a portable foreign function interface
library.
-Copyright @copyright{} 2008--2019 Anthony Green and Red Hat, Inc.
+Copyright @copyright{} 2008--2019, 2021 Anthony Green and Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@var{ntotalargs} the total number of arguments, including variadic
and fixed arguments. @var{argtypes} must have this many elements.
+@code{ffi_prep_cif_var} will return @code{FFI_BAD_ARGTYPE} if any of
+the variable argument types are @code{ffi_type_float} (promote to
+@code{ffi_type_double} first), or any integer type small than an int
+(promote to an int-sized type first).
+
Note that, different cif's must be prepped for calls to the same
function when different numbers of arguments are passed.
void *values[1];
char *s;
ffi_arg rc;
-
- /* Initialize the argument info vectors */
+
+ /* Initialize the argument info vectors */
args[0] = &ffi_type_pointer;
values[0] = &s;
-
+
/* Initialize the cif */
- if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_sint, args) == FFI_OK)
@{
s = "Hello World!";
ffi_call(&cif, puts, &rc, values);
/* rc now holds the result of the call to puts */
-
- /* values holds a pointer to the function's arg, so to
- call puts() again all we need to do is change the
+
+ /* values holds a pointer to the function's arg, so to
+ call puts() again all we need to do is change the
value of s */
s = "This is cool!";
ffi_call(&cif, puts, &rc, values);
@}
-
+
return 0;
@}
@end example
tm_type.size = tm_type.alignment = 0;
tm_type.type = FFI_TYPE_STRUCT;
tm_type.elements = &tm_type_elements;
-
+
for (i = 0; i < 9; i++)
tm_type_elements[i] = &ffi_type_sint;
@node Closure Example
@section Closure Example
-A trivial example that creates a new @code{puts} by binding
+A trivial example that creates a new @code{puts} by binding
@code{fputs} with @code{stdout}.
@example
/* -----------------------------------------------------------------*-C-*-
- libffi @VERSION@ - Copyright (c) 2011, 2014, 2019 Anthony Green
- - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
+ libffi @VERSION@
+ - Copyright (c) 2011, 2014, 2019, 2021 Anthony Green
+ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
- FFI_BAD_ABI
+ FFI_BAD_ABI,
+ FFI_BAD_ARGTYPE
} ffi_status;
typedef struct {
#endif
-FFI_API
+FFI_API
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
#if !FFI_NATIVE_RAW_API
- /* If this is enabled, then a raw closure has the same layout
- as a regular closure. We use this to install an intermediate
+ /* If this is enabled, then a raw closure has the same layout
+ as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
#if !FFI_NATIVE_RAW_API
- /* If this is enabled, then a raw closure has the same layout
- as a regular closure. We use this to install an intermediate
+ /* If this is enabled, then a raw closure has the same layout
+ as a regular closure. We use this to install an intermediate
handler to do the translation, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
/* ---- Public interface definition -------------------------------------- */
-FFI_API
+FFI_API
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
#endif
/* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID 0
+#define FFI_TYPE_VOID 0
#define FFI_TYPE_INT 1
-#define FFI_TYPE_FLOAT 2
+#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if @HAVE_LONG_DOUBLE@
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
#endif
-#define FFI_TYPE_UINT8 5
+#define FFI_TYPE_UINT8 5
#define FFI_TYPE_SINT8 6
-#define FFI_TYPE_UINT16 7
+#define FFI_TYPE_UINT16 7
#define FFI_TYPE_SINT16 8
#define FFI_TYPE_UINT32 9
#define FFI_TYPE_SINT32 10
/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
+ prep_cif.c - Copyright (c) 2011, 2012, 2021 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
ffi_type *rtype,
ffi_type **atypes)
{
- return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+ ffi_status rc;
+ size_t int_size = ffi_type_sint.size;
+ int i;
+
+ rc = ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
+
+ if (rc != FFI_OK)
+ return rc;
+
+ for (i = 1; i < ntotalargs; i++)
+ {
+ ffi_type *arg_type = atypes[i];
+ if (arg_type == &ffi_type_float
+ || ((arg_type->type != FFI_TYPE_STRUCT
+ && arg_type->type != FFI_TYPE_COMPLEX)
+ && arg_type->size < int_size))
+ return FFI_BAD_ARGTYPE;
+ }
+
+ return FFI_OK;
}
#if FFI_CLOSURES
Originator: ARM Ltd. */
/* { dg-do run } */
-/* { dg-output "" { xfail avr32*-*-* m68k-*-* alpha-*-* } } */
#include "ffitest.h"
#include <stdarg.h>
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 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;
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] = ≻
- 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" } */
-
+ CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_BAD_ARGTYPE);
return 0;
}
--- /dev/null
+/* 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 int uc;
+ signed int sc;
+ unsigned int us;
+ signed int 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_uint;
+ arg_types[5] = &ffi_type_sint;
+ arg_types[6] = &ffi_type_uint;
+ arg_types[7] = &ffi_type_sint;
+ 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] = ≻
+ 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;
+}
+++ /dev/null
-/* Area: closure_call
- Purpose: Test anonymous unsigned char argument.
- Limitations: none.
- PR: none.
- Originator: ARM Ltd. */
-
-/* { dg-do run } */
-#include "ffitest.h"
-
-typedef unsigned char T;
-
-static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
- void* userdata __UNUSED__)
- {
- *(ffi_arg *)resp = *(T *)args[0];
-
- printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
- }
-
-typedef T (*cls_ret_T)(T, ...);
-
-int main (void)
-{
- ffi_cif cif;
- void *code;
- ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
- ffi_type * cl_arg_types[3];
- T res;
-
- cl_arg_types[0] = &ffi_type_uchar;
- cl_arg_types[1] = &ffi_type_uchar;
- cl_arg_types[2] = NULL;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
- &ffi_type_uchar, cl_arg_types) == FFI_OK);
-
- CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK);
- res = ((((cls_ret_T)code)(67, 4)));
- /* { dg-output "67: 67 4" } */
- printf("res: %d\n", res);
- /* { dg-output "\nres: 67" } */
- exit(0);
-}
+++ /dev/null
-/* Area: closure_call
- Purpose: Test anonymous unsigned short argument.
- Limitations: none.
- PR: none.
- Originator: ARM Ltd. */
-
-/* { dg-do run } */
-#include "ffitest.h"
-
-typedef unsigned short T;
-
-static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
- void* userdata __UNUSED__)
- {
- *(ffi_arg *)resp = *(T *)args[0];
-
- printf("%d: %d %d\n", (int)(*(ffi_arg *)resp), *(T *)args[0], *(T *)args[1]);
- }
-
-typedef T (*cls_ret_T)(T, ...);
-
-int main (void)
-{
- ffi_cif cif;
- void *code;
- ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
- ffi_type * cl_arg_types[3];
- T res;
-
- cl_arg_types[0] = &ffi_type_ushort;
- cl_arg_types[1] = &ffi_type_ushort;
- cl_arg_types[2] = NULL;
-
- /* Initialize the cif */
- CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
- &ffi_type_ushort, cl_arg_types) == FFI_OK);
-
- CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code) == FFI_OK);
- res = ((((cls_ret_T)code)(67, 4)));
- /* { dg-output "67: 67 4" } */
- printf("res: %d\n", res);
- /* { dg-output "\nres: 67" } */
- exit(0);
-}