Various MSVC-related changes.
This commit is contained in:
committed by
Anthony Green
parent
e1539266e6
commit
0a1ab12a8d
@@ -5,3 +5,4 @@ win32
|
||||
win32_tests
|
||||
vararg_float_test_fix
|
||||
vfp-eabi
|
||||
msvc-changes
|
||||
|
||||
0
.pc/msvc-changes/.timestamp
Normal file
0
.pc/msvc-changes/.timestamp
Normal file
4857
.pc/msvc-changes/ChangeLog
Normal file
4857
.pc/msvc-changes/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
203
.pc/msvc-changes/Makefile.am
Normal file
203
.pc/msvc-changes/Makefile.am
Normal file
@@ -0,0 +1,203 @@
|
||||
## Process this with automake to create Makefile.in
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign subdir-objects
|
||||
|
||||
SUBDIRS = include testsuite man
|
||||
|
||||
EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj configure.host \
|
||||
src/alpha/ffi.c src/alpha/osf.S src/alpha/ffitarget.h \
|
||||
src/arm/ffi.c src/arm/sysv.S src/arm/ffitarget.h \
|
||||
src/avr32/ffi.c src/avr32/sysv.S src/avr32/ffitarget.h \
|
||||
src/cris/ffi.c src/cris/sysv.S src/cris/ffitarget.h \
|
||||
src/ia64/ffi.c src/ia64/ffitarget.h src/ia64/ia64_flags.h \
|
||||
src/ia64/unix.S src/mips/ffi.c src/mips/n32.S src/mips/o32.S \
|
||||
src/mips/ffitarget.h src/m32r/ffi.c src/m32r/sysv.S \
|
||||
src/m32r/ffitarget.h src/m68k/ffi.c src/m68k/sysv.S \
|
||||
src/m68k/ffitarget.h src/powerpc/ffi.c src/powerpc/sysv.S \
|
||||
src/powerpc/linux64.S src/powerpc/linux64_closure.S \
|
||||
src/powerpc/ppc_closure.S src/powerpc/asm.h src/powerpc/aix.S \
|
||||
src/powerpc/darwin.S src/powerpc/aix_closure.S \
|
||||
src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \
|
||||
src/powerpc/ffitarget.h src/s390/ffi.c src/s390/sysv.S \
|
||||
src/s390/ffitarget.h src/sh/ffi.c src/sh/sysv.S \
|
||||
src/sh/ffitarget.h src/sh64/ffi.c src/sh64/sysv.S \
|
||||
src/sh64/ffitarget.h src/sparc/v8.S src/sparc/v9.S \
|
||||
src/sparc/ffitarget.h src/sparc/ffi.c src/x86/darwin64.S \
|
||||
src/x86/ffi.c src/x86/sysv.S src/x86/win32.S src/x86/darwin.S \
|
||||
src/x86/win64.S src/x86/freebsd.S src/x86/ffi64.c \
|
||||
src/x86/unix64.S src/x86/ffitarget.h src/pa/ffitarget.h \
|
||||
src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S src/frv/ffi.c \
|
||||
src/frv/eabi.S src/frv/ffitarget.h src/dlmalloc.c \
|
||||
src/moxie/ffi.c src/moxie/eabi.S libtool-version \
|
||||
ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4 \
|
||||
m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 build-ios.sh \
|
||||
m4/ltversion.m4 build-ios.sh src/arm/gentramp.sh src/debug.c \
|
||||
msvcc.sh
|
||||
|
||||
|
||||
info_TEXINFOS = doc/libffi.texi
|
||||
|
||||
## ################################################################
|
||||
|
||||
##
|
||||
## This section is for make and multilib madness.
|
||||
##
|
||||
|
||||
# Work around what appears to be a GNU make bug handling MAKEFLAGS
|
||||
# values defined in terms of make variables, as is the case for CC and
|
||||
# friends when we are called from the top level Makefile.
|
||||
AM_MAKEFLAGS = \
|
||||
"AR_FLAGS=$(AR_FLAGS)" \
|
||||
"CC_FOR_BUILD=$(CC_FOR_BUILD)" \
|
||||
"CFLAGS=$(CFLAGS)" \
|
||||
"CXXFLAGS=$(CXXFLAGS)" \
|
||||
"CFLAGS_FOR_BUILD=$(CFLAGS_FOR_BUILD)" \
|
||||
"CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
|
||||
"INSTALL=$(INSTALL)" \
|
||||
"INSTALL_DATA=$(INSTALL_DATA)" \
|
||||
"INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
|
||||
"INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
|
||||
"JC1FLAGS=$(JC1FLAGS)" \
|
||||
"LDFLAGS=$(LDFLAGS)" \
|
||||
"LIBCFLAGS=$(LIBCFLAGS)" \
|
||||
"LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
|
||||
"MAKE=$(MAKE)" \
|
||||
"MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
|
||||
"PICFLAG=$(PICFLAG)" \
|
||||
"PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
|
||||
"RUNTESTFLAGS=$(RUNTESTFLAGS)" \
|
||||
"SHELL=$(SHELL)" \
|
||||
"exec_prefix=$(exec_prefix)" \
|
||||
"infodir=$(infodir)" \
|
||||
"libdir=$(libdir)" \
|
||||
"mandir=$(mandir)" \
|
||||
"prefix=$(prefix)" \
|
||||
"AR=$(AR)" \
|
||||
"AS=$(AS)" \
|
||||
"CC=$(CC)" \
|
||||
"CXX=$(CXX)" \
|
||||
"LD=$(LD)" \
|
||||
"NM=$(NM)" \
|
||||
"RANLIB=$(RANLIB)" \
|
||||
"DESTDIR=$(DESTDIR)"
|
||||
|
||||
MAKEOVERRIDES=
|
||||
|
||||
ACLOCAL_AMFLAGS=$(ACLOCAL_AMFLAGS) -I m4
|
||||
|
||||
lib_LTLIBRARIES = libffi.la
|
||||
noinst_LTLIBRARIES = libffi_convenience.la
|
||||
|
||||
libffi_la_SOURCES = src/prep_cif.c src/types.c \
|
||||
src/raw_api.c src/java_raw_api.c src/closures.c
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libffi.pc
|
||||
|
||||
nodist_libffi_la_SOURCES =
|
||||
|
||||
if FFI_DEBUG
|
||||
nodist_libffi_la_SOURCES += src/debug.c
|
||||
endif
|
||||
|
||||
if MIPS
|
||||
nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S
|
||||
endif
|
||||
if X86
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if X86_FREEBSD
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/freebsd.S
|
||||
endif
|
||||
if X86_WIN32
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win32.S
|
||||
endif
|
||||
if X86_WIN64
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/win64.S
|
||||
endif
|
||||
if X86_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi.c src/x86/darwin.S src/x86/ffi64.c src/x86/darwin64.S
|
||||
endif
|
||||
if SPARC
|
||||
nodist_libffi_la_SOURCES += src/sparc/ffi.c src/sparc/v8.S src/sparc/v9.S
|
||||
endif
|
||||
if ALPHA
|
||||
nodist_libffi_la_SOURCES += src/alpha/ffi.c src/alpha/osf.S
|
||||
endif
|
||||
if IA64
|
||||
nodist_libffi_la_SOURCES += src/ia64/ffi.c src/ia64/unix.S
|
||||
endif
|
||||
if M32R
|
||||
nodist_libffi_la_SOURCES += src/m32r/sysv.S src/m32r/ffi.c
|
||||
endif
|
||||
if M68K
|
||||
nodist_libffi_la_SOURCES += src/m68k/ffi.c src/m68k/sysv.S
|
||||
endif
|
||||
if POWERPC
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S src/powerpc/linux64.S src/powerpc/linux64_closure.S
|
||||
endif
|
||||
if POWERPC_AIX
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closure.S
|
||||
endif
|
||||
if POWERPC_DARWIN
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S
|
||||
endif
|
||||
if POWERPC_FREEBSD
|
||||
nodist_libffi_la_SOURCES += src/powerpc/ffi.c src/powerpc/sysv.S src/powerpc/ppc_closure.S
|
||||
endif
|
||||
if ARM
|
||||
nodist_libffi_la_SOURCES += src/arm/sysv.S src/arm/ffi.c
|
||||
if FFI_EXEC_TRAMPOLINE_TABLE
|
||||
nodist_libffi_la_SOURCES += src/arm/trampoline.S
|
||||
endif
|
||||
endif
|
||||
if AVR32
|
||||
nodist_libffi_la_SOURCES += src/avr32/sysv.S src/avr32/ffi.c
|
||||
endif
|
||||
if LIBFFI_CRIS
|
||||
nodist_libffi_la_SOURCES += src/cris/sysv.S src/cris/ffi.c
|
||||
endif
|
||||
if FRV
|
||||
nodist_libffi_la_SOURCES += src/frv/eabi.S src/frv/ffi.c
|
||||
endif
|
||||
if MOXIE
|
||||
nodist_libffi_la_SOURCES += src/moxie/eabi.S src/moxie/ffi.c
|
||||
endif
|
||||
if S390
|
||||
nodist_libffi_la_SOURCES += src/s390/sysv.S src/s390/ffi.c
|
||||
endif
|
||||
if X86_64
|
||||
nodist_libffi_la_SOURCES += src/x86/ffi64.c src/x86/unix64.S src/x86/ffi.c src/x86/sysv.S
|
||||
endif
|
||||
if SH
|
||||
nodist_libffi_la_SOURCES += src/sh/sysv.S src/sh/ffi.c
|
||||
endif
|
||||
if SH64
|
||||
nodist_libffi_la_SOURCES += src/sh64/sysv.S src/sh64/ffi.c
|
||||
endif
|
||||
if PA_LINUX
|
||||
nodist_libffi_la_SOURCES += src/pa/linux.S src/pa/ffi.c
|
||||
endif
|
||||
if PA_HPUX
|
||||
nodist_libffi_la_SOURCES += src/pa/hpux32.S src/pa/ffi.c
|
||||
endif
|
||||
|
||||
libffi_convenience_la_SOURCES = $(libffi_la_SOURCES)
|
||||
nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES)
|
||||
|
||||
AM_CFLAGS = -g
|
||||
if FFI_DEBUG
|
||||
# Build debug. Define FFI_DEBUG on the commandline so that, when building with
|
||||
# MSVC, it can link against the debug CRT.
|
||||
AM_CFLAGS += -DFFI_DEBUG
|
||||
endif
|
||||
|
||||
libffi_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS)
|
||||
|
||||
AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src
|
||||
AM_CCASFLAGS = $(AM_CPPFLAGS) -g
|
||||
|
||||
# No install-html or install-pdf support in automake yet
|
||||
.PHONY: install-html install-pdf
|
||||
install-html:
|
||||
install-pdf:
|
||||
1846
.pc/msvc-changes/Makefile.in
Normal file
1846
.pc/msvc-changes/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
443
.pc/msvc-changes/include/ffi.h.in
Normal file
443
.pc/msvc-changes/include/ffi.h.in
Normal file
@@ -0,0 +1,443 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
libffi @VERSION@ - Copyright (c) 2011 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
|
||||
files (the ``Software''), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------------------------------
|
||||
The basic API is described in the README file.
|
||||
|
||||
The raw API is designed to bypass some of the argument packing
|
||||
and unpacking on architectures for which it can be avoided.
|
||||
|
||||
The closure API allows interpreted functions to be packaged up
|
||||
inside a C function pointer, so that they can be called as C functions,
|
||||
with no understanding on the client side that they are interpreted.
|
||||
It can also be used in other cases in which it is necessary to package
|
||||
up a user specified parameter and a function pointer as a single
|
||||
function pointer.
|
||||
|
||||
The closure API must be implemented in order to get its functionality,
|
||||
e.g. for use by gij. Routines are provided to emulate the raw API
|
||||
if the underlying platform doesn't allow faster implementation.
|
||||
|
||||
More details on the raw and cloure API can be found in:
|
||||
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
|
||||
|
||||
and
|
||||
|
||||
http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
|
||||
-------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#define LIBFFI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Specify which architecture libffi is configured for. */
|
||||
#ifndef @TARGET@
|
||||
#define @TARGET@
|
||||
#endif
|
||||
|
||||
/* ---- System configuration information --------------------------------- */
|
||||
|
||||
#include <ffitarget.h>
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __attribute__(X)
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
|
||||
But we can find it either under the correct ANSI name, or under GNU
|
||||
C's internal name. */
|
||||
|
||||
#define FFI_64_BIT_MAX 9223372036854775807
|
||||
|
||||
#ifdef LONG_LONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LONG_LONG_MAX
|
||||
#else
|
||||
# ifdef LLONG_MAX
|
||||
# define FFI_LONG_LONG_MAX LLONG_MAX
|
||||
# ifdef _AIX52 /* or newer has C99 LLONG_MAX */
|
||||
# undef FFI_64_BIT_MAX
|
||||
# define FFI_64_BIT_MAX 9223372036854775807LL
|
||||
# endif /* _AIX52 or newer */
|
||||
# else
|
||||
# ifdef __GNUC__
|
||||
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
|
||||
# endif
|
||||
# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */
|
||||
# ifndef __PPC64__
|
||||
# if defined (__IBMC__) || defined (__IBMCPP__)
|
||||
# define FFI_LONG_LONG_MAX LONGLONG_MAX
|
||||
# endif
|
||||
# endif /* __PPC64__ */
|
||||
# undef FFI_64_BIT_MAX
|
||||
# define FFI_64_BIT_MAX 9223372036854775807LL
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The closure code assumes that this works on pointers, i.e. a size_t */
|
||||
/* can hold a pointer. */
|
||||
|
||||
typedef struct _ffi_type
|
||||
{
|
||||
size_t size;
|
||||
unsigned short alignment;
|
||||
unsigned short type;
|
||||
struct _ffi_type **elements;
|
||||
} ffi_type;
|
||||
|
||||
#ifndef LIBFFI_HIDE_BASIC_TYPES
|
||||
#if SCHAR_MAX == 127
|
||||
# define ffi_type_uchar ffi_type_uint8
|
||||
# define ffi_type_schar ffi_type_sint8
|
||||
#else
|
||||
#error "char size not supported"
|
||||
#endif
|
||||
|
||||
#if SHRT_MAX == 32767
|
||||
# define ffi_type_ushort ffi_type_uint16
|
||||
# define ffi_type_sshort ffi_type_sint16
|
||||
#elif SHRT_MAX == 2147483647
|
||||
# define ffi_type_ushort ffi_type_uint32
|
||||
# define ffi_type_sshort ffi_type_sint32
|
||||
#else
|
||||
#error "short size not supported"
|
||||
#endif
|
||||
|
||||
#if INT_MAX == 32767
|
||||
# define ffi_type_uint ffi_type_uint16
|
||||
# define ffi_type_sint ffi_type_sint16
|
||||
#elif INT_MAX == 2147483647
|
||||
# define ffi_type_uint ffi_type_uint32
|
||||
# define ffi_type_sint ffi_type_sint32
|
||||
#elif INT_MAX == 9223372036854775807
|
||||
# define ffi_type_uint ffi_type_uint64
|
||||
# define ffi_type_sint ffi_type_sint64
|
||||
#else
|
||||
#error "int size not supported"
|
||||
#endif
|
||||
|
||||
#if LONG_MAX == 2147483647
|
||||
# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
|
||||
#error "no 64-bit data type supported"
|
||||
# endif
|
||||
#elif LONG_MAX != FFI_64_BIT_MAX
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
#if LONG_MAX == 2147483647
|
||||
# define ffi_type_ulong ffi_type_uint32
|
||||
# define ffi_type_slong ffi_type_sint32
|
||||
#elif LONG_MAX == FFI_64_BIT_MAX
|
||||
# define ffi_type_ulong ffi_type_uint64
|
||||
# define ffi_type_slong ffi_type_sint64
|
||||
#else
|
||||
#error "long size not supported"
|
||||
#endif
|
||||
|
||||
/* These are defined in types.c */
|
||||
extern ffi_type ffi_type_void;
|
||||
extern ffi_type ffi_type_uint8;
|
||||
extern ffi_type ffi_type_sint8;
|
||||
extern ffi_type ffi_type_uint16;
|
||||
extern ffi_type ffi_type_sint16;
|
||||
extern ffi_type ffi_type_uint32;
|
||||
extern ffi_type ffi_type_sint32;
|
||||
extern ffi_type ffi_type_uint64;
|
||||
extern ffi_type ffi_type_sint64;
|
||||
extern ffi_type ffi_type_float;
|
||||
extern ffi_type ffi_type_double;
|
||||
extern ffi_type ffi_type_pointer;
|
||||
|
||||
#if @HAVE_LONG_DOUBLE@
|
||||
extern ffi_type ffi_type_longdouble;
|
||||
#else
|
||||
#define ffi_type_longdouble ffi_type_double
|
||||
#endif
|
||||
#endif /* LIBFFI_HIDE_BASIC_TYPES */
|
||||
|
||||
typedef enum {
|
||||
FFI_OK = 0,
|
||||
FFI_BAD_TYPEDEF,
|
||||
FFI_BAD_ABI
|
||||
} ffi_status;
|
||||
|
||||
typedef unsigned FFI_TYPE;
|
||||
|
||||
typedef struct {
|
||||
ffi_abi abi;
|
||||
unsigned nargs;
|
||||
ffi_type **arg_types;
|
||||
ffi_type *rtype;
|
||||
unsigned bytes;
|
||||
unsigned flags;
|
||||
#ifdef FFI_EXTRA_CIF_FIELDS
|
||||
FFI_EXTRA_CIF_FIELDS;
|
||||
#endif
|
||||
} ffi_cif;
|
||||
|
||||
/* Used internally, but overridden by some architectures */
|
||||
ffi_status ffi_prep_cif_core(ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int isvariadic,
|
||||
unsigned int nfixedargs,
|
||||
unsigned int ntotalargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes);
|
||||
|
||||
/* ---- Definitions for the raw API -------------------------------------- */
|
||||
|
||||
#ifndef FFI_SIZEOF_ARG
|
||||
# if LONG_MAX == 2147483647
|
||||
# define FFI_SIZEOF_ARG 4
|
||||
# elif LONG_MAX == FFI_64_BIT_MAX
|
||||
# define FFI_SIZEOF_ARG 8
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FFI_SIZEOF_JAVA_RAW
|
||||
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
|
||||
#endif
|
||||
|
||||
typedef union {
|
||||
ffi_sarg sint;
|
||||
ffi_arg uint;
|
||||
float flt;
|
||||
char data[FFI_SIZEOF_ARG];
|
||||
void* ptr;
|
||||
} ffi_raw;
|
||||
|
||||
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
|
||||
/* This is a special case for mips64/n32 ABI (and perhaps others) where
|
||||
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
|
||||
typedef union {
|
||||
signed int sint;
|
||||
unsigned int uint;
|
||||
float flt;
|
||||
char data[FFI_SIZEOF_JAVA_RAW];
|
||||
void* ptr;
|
||||
} ffi_java_raw;
|
||||
#else
|
||||
typedef ffi_raw ffi_java_raw;
|
||||
#endif
|
||||
|
||||
|
||||
void ffi_raw_call (ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
ffi_raw *avalue);
|
||||
|
||||
void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
|
||||
void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
|
||||
size_t ffi_raw_size (ffi_cif *cif);
|
||||
|
||||
/* This is analogous to the raw API, except it uses Java parameter */
|
||||
/* packing, even on 64-bit machines. I.e. on 64-bit machines */
|
||||
/* longs and doubles are followed by an empty 64-bit word. */
|
||||
|
||||
void ffi_java_raw_call (ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
ffi_java_raw *avalue);
|
||||
|
||||
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
|
||||
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
|
||||
size_t ffi_java_raw_size (ffi_cif *cif);
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#if FFI_CLOSURES
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__declspec(align(8))
|
||||
#endif
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
ffi_cif *cif;
|
||||
void (*fun)(ffi_cif*,void*,void**,void*);
|
||||
void *user_data;
|
||||
#ifdef __GNUC__
|
||||
} ffi_closure __attribute__((aligned (8)));
|
||||
#else
|
||||
} ffi_closure;
|
||||
# ifdef __sgi
|
||||
# pragma pack 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void *ffi_closure_alloc (size_t size, void **code);
|
||||
void ffi_closure_free (void *);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure (ffi_closure*,
|
||||
ffi_cif *,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure*,
|
||||
ffi_cif *,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void*codeloc);
|
||||
|
||||
#ifdef __sgi
|
||||
# pragma pack 8
|
||||
#endif
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
ffi_cif *cif;
|
||||
|
||||
#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
|
||||
handler to do the transaltion, void** -> ffi_raw*. */
|
||||
|
||||
void (*translate_args)(ffi_cif*,void*,void**,void*);
|
||||
void *this_closure;
|
||||
|
||||
#endif
|
||||
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
|
||||
void *user_data;
|
||||
|
||||
} ffi_raw_closure;
|
||||
|
||||
typedef struct {
|
||||
char tramp[FFI_TRAMPOLINE_SIZE];
|
||||
|
||||
ffi_cif *cif;
|
||||
|
||||
#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
|
||||
handler to do the transaltion, void** -> ffi_raw*. */
|
||||
|
||||
void (*translate_args)(ffi_cif*,void*,void**,void*);
|
||||
void *this_closure;
|
||||
|
||||
#endif
|
||||
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
|
||||
void *user_data;
|
||||
|
||||
} ffi_java_raw_closure;
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data);
|
||||
|
||||
ffi_status
|
||||
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
|
||||
ffi_cif *cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc);
|
||||
|
||||
#endif /* FFI_CLOSURES */
|
||||
|
||||
/* ---- Public interface definition -------------------------------------- */
|
||||
|
||||
ffi_status ffi_prep_cif(ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes);
|
||||
|
||||
ffi_status ffi_prep_cif_var(ffi_cif *cif,
|
||||
ffi_abi abi,
|
||||
unsigned int nfixedargs,
|
||||
unsigned int ntotalargs,
|
||||
ffi_type *rtype,
|
||||
ffi_type **atypes);
|
||||
|
||||
void ffi_call(ffi_cif *cif,
|
||||
void (*fn)(void),
|
||||
void *rvalue,
|
||||
void **avalue);
|
||||
|
||||
/* Useful for eliminating compiler warnings */
|
||||
#define FFI_FN(f) ((void (*)(void))f)
|
||||
|
||||
/* ---- Definitions shared with assembly code ---------------------------- */
|
||||
|
||||
#endif
|
||||
|
||||
/* If these change, update src/mips/ffitarget.h. */
|
||||
#define FFI_TYPE_VOID 0
|
||||
#define FFI_TYPE_INT 1
|
||||
#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_SINT8 6
|
||||
#define FFI_TYPE_UINT16 7
|
||||
#define FFI_TYPE_SINT16 8
|
||||
#define FFI_TYPE_UINT32 9
|
||||
#define FFI_TYPE_SINT32 10
|
||||
#define FFI_TYPE_UINT64 11
|
||||
#define FFI_TYPE_SINT64 12
|
||||
#define FFI_TYPE_STRUCT 13
|
||||
#define FFI_TYPE_POINTER 14
|
||||
|
||||
/* This should always refer to the last type code (for sanity checks) */
|
||||
#define FFI_TYPE_LAST FFI_TYPE_POINTER
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
826
.pc/msvc-changes/src/x86/ffi.c
Normal file
826
.pc/msvc-changes/src/x86/ffi.c
Normal file
@@ -0,0 +1,826 @@
|
||||
/* -----------------------------------------------------------------------
|
||||
ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
|
||||
Copyright (c) 2002 Ranjit Mathew
|
||||
Copyright (c) 2002 Bo Thorsen
|
||||
Copyright (c) 2002 Roger Sayle
|
||||
Copyright (C) 2008, 2010 Free Software Foundation, Inc.
|
||||
|
||||
x86 Foreign Function Interface
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#if !defined(__x86_64__) || defined(_WIN64)
|
||||
|
||||
#ifdef _WIN64
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
#ifdef X86_WIN32
|
||||
size_t p_stack_args[2];
|
||||
void *p_stack_data[2];
|
||||
char *argp2 = stack;
|
||||
int stack_args_count = 0;
|
||||
int cabi = ecif->cif->abi;
|
||||
#endif
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->flags == FFI_TYPE_STRUCT
|
||||
#ifdef X86_WIN64
|
||||
&& (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
|
||||
&& ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
*(void **) argp = ecif->rvalue;
|
||||
#ifdef X86_WIN32
|
||||
/* For fastcall/thiscall this is first register-passed
|
||||
argument. */
|
||||
if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
|
||||
{
|
||||
p_stack_args[stack_args_count] = sizeof (void*);
|
||||
p_stack_data[stack_args_count] = argp;
|
||||
++stack_args_count;
|
||||
}
|
||||
#endif
|
||||
argp += sizeof(void*);
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(void*) - 1) & (size_t) argp)
|
||||
argp = (char *) ALIGN(argp, sizeof(void*));
|
||||
|
||||
z = (*p_arg)->size;
|
||||
#ifdef X86_WIN64
|
||||
if (z > sizeof(ffi_arg)
|
||||
|| ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
&& (z != 1 && z != 2 && z != 4 && z != 8))
|
||||
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
|
||||
|| ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
z = sizeof(ffi_arg);
|
||||
*(void **)argp = *p_argv;
|
||||
}
|
||||
else if ((*p_arg)->type == FFI_TYPE_FLOAT)
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (z < sizeof(ffi_arg))
|
||||
{
|
||||
z = sizeof(ffi_arg);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
case FFI_TYPE_SINT8:
|
||||
*(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT8:
|
||||
*(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT16:
|
||||
*(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT16:
|
||||
*(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
/* For thiscall/fastcall convention register-passed arguments
|
||||
are the first two none-floating-point arguments with a size
|
||||
smaller or equal to sizeof (void*). */
|
||||
if ((cabi == FFI_THISCALL && stack_args_count < 1)
|
||||
|| (cabi == FFI_FASTCALL && stack_args_count < 2))
|
||||
{
|
||||
if (z <= 4
|
||||
&& ((*p_arg)->type != FFI_TYPE_FLOAT
|
||||
&& (*p_arg)->type != FFI_TYPE_STRUCT))
|
||||
{
|
||||
p_stack_args[stack_args_count] = z;
|
||||
p_stack_data[stack_args_count] = argp;
|
||||
++stack_args_count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
p_argv++;
|
||||
#ifdef X86_WIN64
|
||||
argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
#else
|
||||
argp += z;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
/* We need to move the register-passed arguments for thiscall/fastcall
|
||||
on top of stack, so that those can be moved to registers ecx/edx by
|
||||
call-handler. */
|
||||
if (stack_args_count > 0)
|
||||
{
|
||||
size_t zz = (p_stack_args[0] + 3) & ~3;
|
||||
char *h;
|
||||
|
||||
/* Move first argument to top-stack position. */
|
||||
if (p_stack_data[0] != argp2)
|
||||
{
|
||||
h = alloca (zz + 1);
|
||||
memcpy (h, p_stack_data[0], zz);
|
||||
memmove (argp2 + zz, argp2,
|
||||
(size_t) ((char *) p_stack_data[0] - (char*)argp2));
|
||||
memcpy (argp2, h, zz);
|
||||
}
|
||||
|
||||
argp2 += zz;
|
||||
--stack_args_count;
|
||||
if (zz > 4)
|
||||
stack_args_count = 0;
|
||||
|
||||
/* If we have a second argument, then move it on top
|
||||
after the first one. */
|
||||
if (stack_args_count > 0 && p_stack_data[1] != argp2)
|
||||
{
|
||||
zz = p_stack_args[1];
|
||||
zz = (zz + 3) & ~3;
|
||||
h = alloca (zz + 1);
|
||||
h = alloca (zz + 1);
|
||||
memcpy (h, p_stack_data[1], zz);
|
||||
memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
|
||||
memcpy (argp2, h, zz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
unsigned int i;
|
||||
ffi_type **ptr;
|
||||
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
#ifdef X86_WIN64
|
||||
case FFI_TYPE_UINT32:
|
||||
case FFI_TYPE_SINT32:
|
||||
#endif
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
#ifndef X86_WIN64
|
||||
#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
#endif
|
||||
#endif
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
#ifdef X86_WIN64
|
||||
case FFI_TYPE_POINTER:
|
||||
#endif
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
#ifndef X86
|
||||
if (cif->rtype->size == 1)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
|
||||
}
|
||||
else if (cif->rtype->size == 2)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
|
||||
}
|
||||
else if (cif->rtype->size == 4)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
|
||||
#else
|
||||
cif->flags = FFI_TYPE_INT; /* same as int type */
|
||||
#endif
|
||||
}
|
||||
else if (cif->rtype->size == 8)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
/* allocate space for return value pointer */
|
||||
cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef X86_WIN64
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
case FFI_TYPE_INT:
|
||||
cif->flags = FFI_TYPE_SINT32;
|
||||
#else
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
||||
{
|
||||
if (((*ptr)->alignment - 1) & cif->bytes)
|
||||
cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
|
||||
cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
/* ensure space for storing four registers */
|
||||
cif->bytes += 4 * sizeof(ffi_arg);
|
||||
#endif
|
||||
|
||||
#ifdef X86_DARWIN
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
extern int
|
||||
ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#elif defined(X86_WIN32)
|
||||
extern void
|
||||
ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#else
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)(void));
|
||||
#endif
|
||||
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
#ifdef X86_WIN64
|
||||
if (rvalue == NULL
|
||||
&& cif->flags == FFI_TYPE_STRUCT
|
||||
&& cif->rtype->size != 1 && cif->rtype->size != 2
|
||||
&& cif->rtype->size != 4 && cif->rtype->size != 8)
|
||||
{
|
||||
ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
|
||||
}
|
||||
#else
|
||||
if (rvalue == NULL
|
||||
&& cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
case FFI_WIN64:
|
||||
ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
break;
|
||||
#elif defined(X86_WIN32)
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
case FFI_THISCALL:
|
||||
case FFI_FASTCALL:
|
||||
{
|
||||
unsigned int abi = cif->abi;
|
||||
unsigned int i, passed_regs = 0;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
++passed_regs;
|
||||
|
||||
for (i=0; i < cif->nargs && passed_regs < 2;i++)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
continue;
|
||||
sz = (cif->arg_types[i]->size + 3) & ~3;
|
||||
if (sz == 0 || sz > 4)
|
||||
continue;
|
||||
++passed_regs;
|
||||
}
|
||||
if (passed_regs < 2 && abi == FFI_FASTCALL)
|
||||
abi = FFI_THISCALL;
|
||||
if (passed_regs < 1 && abi == FFI_THISCALL)
|
||||
abi = FFI_STDCALL;
|
||||
ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** private members **/
|
||||
|
||||
/* The following __attribute__((regparm(1))) decorations will have no effect
|
||||
on MSVC - standard cdecl convention applies. */
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#ifdef X86_WIN32
|
||||
void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
#endif
|
||||
#ifdef X86_WIN64
|
||||
void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
|
||||
#endif
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
|
||||
#ifdef X86_WIN64
|
||||
void * FFI_HIDDEN
|
||||
ffi_closure_win64_inner (ffi_closure *closure, void *args) {
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
void *result;
|
||||
void *resp = &result;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will change RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
||||
|
||||
/* The result is returned in rax. This does the right thing for
|
||||
result types except for floats; we have to 'mov xmm0, rax' in the
|
||||
caller to correct this.
|
||||
TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
|
||||
*/
|
||||
return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
|
||||
}
|
||||
|
||||
#else
|
||||
unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
|
||||
ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
|
||||
{
|
||||
/* our various things... */
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will change RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
#endif /* !X86_WIN64 */
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
|
||||
ffi_cif *cif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
#ifdef X86_WIN64
|
||||
if (cif->rtype->size > sizeof(ffi_arg)
|
||||
|| (cif->flags == FFI_TYPE_STRUCT
|
||||
&& (cif->rtype->size != 1 && cif->rtype->size != 2
|
||||
&& cif->rtype->size != 4 && cif->rtype->size != 8))) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += sizeof(void *);
|
||||
}
|
||||
#else
|
||||
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += sizeof(void *);
|
||||
}
|
||||
#endif
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(void*) - 1) & (size_t) argp) {
|
||||
argp = (char *) ALIGN(argp, sizeof(void*));
|
||||
}
|
||||
|
||||
#ifdef X86_WIN64
|
||||
if ((*p_arg)->size > sizeof(ffi_arg)
|
||||
|| ((*p_arg)->type == FFI_TYPE_STRUCT
|
||||
&& ((*p_arg)->size != 1 && (*p_arg)->size != 2
|
||||
&& (*p_arg)->size != 4 && (*p_arg)->size != 8)))
|
||||
{
|
||||
z = sizeof(void *);
|
||||
*p_argv = *(void **)argp;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
}
|
||||
|
||||
p_argv++;
|
||||
#ifdef X86_WIN64
|
||||
argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
|
||||
#else
|
||||
argp += z;
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
void* __fun = (void*)(FUN); \
|
||||
void* __ctx = (void*)(CTX); \
|
||||
*(unsigned char*) &__tramp[0] = 0x41; \
|
||||
*(unsigned char*) &__tramp[1] = 0xbb; \
|
||||
*(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
|
||||
*(unsigned char*) &__tramp[6] = 0x48; \
|
||||
*(unsigned char*) &__tramp[7] = 0xb8; \
|
||||
*(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
|
||||
*(unsigned char *) &__tramp[16] = 0x49; \
|
||||
*(unsigned char *) &__tramp[17] = 0xba; \
|
||||
*(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
|
||||
*(unsigned char *) &__tramp[26] = 0x41; \
|
||||
*(unsigned char *) &__tramp[27] = 0xff; \
|
||||
*(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
|
||||
}
|
||||
|
||||
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + 10); \
|
||||
*(unsigned char*) &__tramp[0] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[5] = 0xe9; \
|
||||
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
|
||||
}
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + 49); \
|
||||
unsigned short __size = (unsigned short)(SIZE); \
|
||||
*(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
|
||||
*(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
|
||||
*(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
|
||||
*(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
|
||||
*(unsigned char*) &__tramp[13] = 0xb8; \
|
||||
*(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
|
||||
*(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
|
||||
*(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
|
||||
*(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
|
||||
*(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
|
||||
*(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
|
||||
*(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
|
||||
*(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
|
||||
*(unsigned char*) &__tramp[39] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[44] = 0xe8; \
|
||||
*(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
|
||||
*(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
|
||||
*(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
|
||||
}
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
|
||||
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + 10); \
|
||||
unsigned short __size = (unsigned short)(SIZE); \
|
||||
*(unsigned char*) &__tramp[0] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[5] = 0xe8; \
|
||||
*(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
|
||||
*(unsigned char *) &__tramp[10] = 0xc2; \
|
||||
*(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
|
||||
}
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
|
||||
ffi_status
|
||||
ffi_prep_closure_loc (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
#ifdef X86_WIN64
|
||||
#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
|
||||
#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
|
||||
if (cif->abi == FFI_WIN64)
|
||||
{
|
||||
int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
|
||||
FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
|
||||
&ffi_closure_win64,
|
||||
codeloc, mask);
|
||||
/* make sure we can execute here */
|
||||
}
|
||||
#else
|
||||
if (cif->abi == FFI_SYSV)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
||||
&ffi_closure_SYSV,
|
||||
(void*)codeloc);
|
||||
}
|
||||
#ifdef X86_WIN32
|
||||
else if (cif->abi == FFI_THISCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
|
||||
&ffi_closure_THISCALL,
|
||||
(void*)codeloc,
|
||||
cif->bytes);
|
||||
}
|
||||
else if (cif->abi == FFI_STDCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
|
||||
&ffi_closure_STDCALL,
|
||||
(void*)codeloc, cif->bytes);
|
||||
}
|
||||
#endif /* X86_WIN32 */
|
||||
#endif /* !X86_WIN64 */
|
||||
else
|
||||
{
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* ------- Native raw API support -------------------------------- */
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cif->abi != FFI_SYSV) {
|
||||
#ifdef X86_WIN32
|
||||
if (cif->abi != FFI_THISCALL)
|
||||
#endif
|
||||
return FFI_BAD_ABI;
|
||||
}
|
||||
|
||||
/* we currently don't support certain kinds of arguments for raw
|
||||
closures. This should be implemented by a separate assembly
|
||||
language routine, since it would require argument processing,
|
||||
something we don't do now for performance. */
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
#ifdef X86_WIN32
|
||||
if (cif->abi == FFI_SYSV)
|
||||
{
|
||||
#endif
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||
codeloc);
|
||||
#ifdef X86_WIN32
|
||||
}
|
||||
else if (cif->abi == FFI_THISCALL)
|
||||
{
|
||||
FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
|
||||
codeloc, cif->bytes);
|
||||
}
|
||||
#endif
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_args_raw(char *stack, extended_cif *ecif)
|
||||
{
|
||||
memcpy (stack, ecif->avalue, ecif->cif->bytes);
|
||||
}
|
||||
|
||||
/* we borrow this routine from libffi (it must be changed, though, to
|
||||
* actually call the function passed in the first argument. as of
|
||||
* libffi-1.20, this is not the case.)
|
||||
*/
|
||||
|
||||
void
|
||||
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
||||
ecif.cif = cif;
|
||||
ecif.avalue = avalue;
|
||||
|
||||
/* If the return value is a struct and we don't have a return */
|
||||
/* value address then we need to make one */
|
||||
|
||||
if ((rvalue == NULL) &&
|
||||
(cif->rtype->type == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
#ifdef X86_WIN32
|
||||
case FFI_SYSV:
|
||||
case FFI_STDCALL:
|
||||
ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
case FFI_THISCALL:
|
||||
case FFI_FASTCALL:
|
||||
{
|
||||
unsigned int abi = cif->abi;
|
||||
unsigned int i, passed_regs = 0;
|
||||
|
||||
if (cif->flags == FFI_TYPE_STRUCT)
|
||||
++passed_regs;
|
||||
|
||||
for (i=0; i < cif->nargs && passed_regs < 2;i++)
|
||||
{
|
||||
size_t sz;
|
||||
|
||||
if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
|
||||
|| cif->arg_types[i]->type == FFI_TYPE_STRUCT)
|
||||
continue;
|
||||
sz = (cif->arg_types[i]->size + 3) & ~3;
|
||||
if (sz == 0 || sz > 4)
|
||||
continue;
|
||||
++passed_regs;
|
||||
}
|
||||
if (passed_regs < 2 && abi == FFI_FASTCALL)
|
||||
cif->abi = abi = FFI_THISCALL;
|
||||
if (passed_regs < 1 && abi == FFI_THISCALL)
|
||||
cif->abi = abi = FFI_STDCALL;
|
||||
ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !__x86_64__ || X86_WIN64 */
|
||||
|
||||
134
.pc/msvc-changes/src/x86/ffitarget.h
Normal file
134
.pc/msvc-changes/src/x86/ffitarget.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -----------------------------------------------------------------*-C-*-
|
||||
ffitarget.h - Copyright (c) 2012 Anthony Green
|
||||
Copyright (c) 1996-2003, 2010 Red Hat, Inc.
|
||||
Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
||||
Target configuration macros for x86 and x86-64.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
``Software''), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_TARGET_H
|
||||
#define LIBFFI_TARGET_H
|
||||
|
||||
#ifndef LIBFFI_H
|
||||
#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead."
|
||||
#endif
|
||||
|
||||
/* ---- System specific configurations ----------------------------------- */
|
||||
|
||||
/* For code common to all platforms on x86 and x86_64. */
|
||||
#define X86_ANY
|
||||
|
||||
#if defined (X86_64) && defined (__i386__)
|
||||
#undef X86_64
|
||||
#define X86
|
||||
#endif
|
||||
|
||||
#ifdef X86_WIN64
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */
|
||||
#endif
|
||||
|
||||
/* ---- Generic type definitions ----------------------------------------- */
|
||||
|
||||
#ifndef LIBFFI_ASM
|
||||
#ifdef X86_WIN64
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int64 ffi_arg;
|
||||
typedef __int64 ffi_sarg;
|
||||
#else
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef long long ffi_sarg;
|
||||
#endif
|
||||
#else
|
||||
#if defined __x86_64__ && !defined __LP64__
|
||||
#define FFI_SIZEOF_ARG 8
|
||||
typedef unsigned long long ffi_arg;
|
||||
typedef long long ffi_sarg;
|
||||
#else
|
||||
typedef unsigned long ffi_arg;
|
||||
typedef signed long ffi_sarg;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum ffi_abi {
|
||||
FFI_FIRST_ABI = 0,
|
||||
|
||||
/* ---- Intel x86 Win32 ---------- */
|
||||
#ifdef X86_WIN32
|
||||
FFI_SYSV,
|
||||
FFI_STDCALL,
|
||||
FFI_THISCALL,
|
||||
FFI_FASTCALL,
|
||||
FFI_LAST_ABI,
|
||||
/* TODO: Add fastcall support for the sake of completeness */
|
||||
FFI_DEFAULT_ABI = FFI_SYSV
|
||||
|
||||
#elif defined(X86_WIN64)
|
||||
FFI_WIN64,
|
||||
FFI_LAST_ABI,
|
||||
FFI_DEFAULT_ABI = FFI_WIN64
|
||||
|
||||
#else
|
||||
/* ---- Intel x86 and AMD x86-64 - */
|
||||
FFI_SYSV,
|
||||
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
|
||||
FFI_LAST_ABI,
|
||||
#if defined(__i386__) || defined(__i386)
|
||||
FFI_DEFAULT_ABI = FFI_SYSV
|
||||
#else
|
||||
FFI_DEFAULT_ABI = FFI_UNIX64
|
||||
#endif
|
||||
#endif
|
||||
} ffi_abi;
|
||||
#endif
|
||||
|
||||
/* ---- Definitions for closures ----------------------------------------- */
|
||||
|
||||
#define FFI_CLOSURES 1
|
||||
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
|
||||
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
|
||||
#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)
|
||||
|
||||
#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))
|
||||
#define FFI_TRAMPOLINE_SIZE 24
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#else
|
||||
#ifdef X86_WIN32
|
||||
#define FFI_TRAMPOLINE_SIZE 52
|
||||
#else
|
||||
#ifdef X86_WIN64
|
||||
#define FFI_TRAMPOLINE_SIZE 29
|
||||
#define FFI_NATIVE_RAW_API 0
|
||||
#define FFI_NO_RAW_API 1
|
||||
#else
|
||||
#define FFI_TRAMPOLINE_SIZE 10
|
||||
#endif
|
||||
#endif
|
||||
#ifndef X86_WIN64
|
||||
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
1147
.pc/msvc-changes/src/x86/win32.S
Normal file
1147
.pc/msvc-changes/src/x86/win32.S
Normal file
File diff suppressed because it is too large
Load Diff
64
.pc/msvc-changes/testsuite/libffi.call/closure_stdcall.c
Normal file
64
.pc/msvc-changes/testsuite/libffi.call/closure_stdcall.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* Area: closure_call (stdcall convention)
|
||||
Purpose: Check handling when caller expects stdcall callee
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <twalljava@dev.java.net> */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
static void
|
||||
closure_test_stdcall(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata)
|
||||
{
|
||||
*(ffi_arg*)resp =
|
||||
(int)*(int *)args[0] + (int)(*(int *)args[1])
|
||||
+ (int)(*(int *)args[2]) + (int)(*(int *)args[3])
|
||||
+ (int)(intptr_t)userdata;
|
||||
|
||||
printf("%d %d %d %d: %d\n",
|
||||
(int)*(int *)args[0], (int)(*(int *)args[1]),
|
||||
(int)(*(int *)args[2]), (int)(*(int *)args[3]),
|
||||
(int)*(ffi_arg *)resp);
|
||||
|
||||
}
|
||||
|
||||
typedef int (__stdcall *closure_test_type0)(int, int, int, int);
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
ffi_type * cl_arg_types[17];
|
||||
int res;
|
||||
void* sp_pre;
|
||||
void* sp_post;
|
||||
char buf[1024];
|
||||
|
||||
cl_arg_types[0] = &ffi_type_uint;
|
||||
cl_arg_types[1] = &ffi_type_uint;
|
||||
cl_arg_types[2] = &ffi_type_uint;
|
||||
cl_arg_types[3] = &ffi_type_uint;
|
||||
cl_arg_types[4] = NULL;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 4,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_stdcall,
|
||||
(void *) 3 /* userdata */, code) == FFI_OK);
|
||||
|
||||
asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
|
||||
res = (*(closure_test_type0)code)(0, 1, 2, 3);
|
||||
asm volatile (" movl %%esp,%0" : "=g" (sp_post));
|
||||
/* { dg-output "0 1 2 3: 9" } */
|
||||
|
||||
printf("res: %d\n",res);
|
||||
/* { dg-output "\nres: 9" } */
|
||||
|
||||
sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
|
||||
printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
|
||||
/* { dg-output "\nstack pointer match" } */
|
||||
exit(0);
|
||||
}
|
||||
64
.pc/msvc-changes/testsuite/libffi.call/closure_thiscall.c
Normal file
64
.pc/msvc-changes/testsuite/libffi.call/closure_thiscall.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/* Area: closure_call (thiscall convention)
|
||||
Purpose: Check handling when caller expects thiscall callee
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <ktietz@redhat.com> */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
static void
|
||||
closure_test_thiscall(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata)
|
||||
{
|
||||
*(ffi_arg*)resp =
|
||||
(int)*(int *)args[0] + (int)(*(int *)args[1])
|
||||
+ (int)(*(int *)args[2]) + (int)(*(int *)args[3])
|
||||
+ (int)(intptr_t)userdata;
|
||||
|
||||
printf("%d %d %d %d: %d\n",
|
||||
(int)*(int *)args[0], (int)(*(int *)args[1]),
|
||||
(int)(*(int *)args[2]), (int)(*(int *)args[3]),
|
||||
(int)*(ffi_arg *)resp);
|
||||
|
||||
}
|
||||
|
||||
typedef int (__thiscall *closure_test_type0)(int, int, int, int);
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
ffi_type * cl_arg_types[17];
|
||||
int res;
|
||||
void* sp_pre;
|
||||
void* sp_post;
|
||||
char buf[1024];
|
||||
|
||||
cl_arg_types[0] = &ffi_type_uint;
|
||||
cl_arg_types[1] = &ffi_type_uint;
|
||||
cl_arg_types[2] = &ffi_type_uint;
|
||||
cl_arg_types[3] = &ffi_type_uint;
|
||||
cl_arg_types[4] = NULL;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_THISCALL, 4,
|
||||
&ffi_type_sint, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_thiscall,
|
||||
(void *) 3 /* userdata */, code) == FFI_OK);
|
||||
|
||||
asm volatile (" movl %%esp,%0" : "=g" (sp_pre));
|
||||
res = (*(closure_test_type0)code)(0, 1, 2, 3);
|
||||
asm volatile (" movl %%esp,%0" : "=g" (sp_post));
|
||||
/* { dg-output "0 1 2 3: 9" } */
|
||||
|
||||
printf("res: %d\n",res);
|
||||
/* { dg-output "\nres: 9" } */
|
||||
|
||||
sprintf(buf, "mismatch: pre=%p vs post=%p", sp_pre, sp_post);
|
||||
printf("stack pointer %s\n", (sp_pre == sp_post ? "match" : buf));
|
||||
/* { dg-output "\nstack pointer match" } */
|
||||
exit(0);
|
||||
}
|
||||
94
.pc/msvc-changes/testsuite/libffi.call/cls_12byte.c
Normal file
94
.pc/msvc-changes/testsuite/libffi.call/cls_12byte.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_12byte {
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
} cls_struct_12byte;
|
||||
|
||||
cls_struct_12byte cls_struct_12byte_fn(struct cls_struct_12byte b1,
|
||||
struct cls_struct_12byte b2)
|
||||
{
|
||||
struct cls_struct_12byte result;
|
||||
|
||||
result.a = b1.a + b2.a;
|
||||
result.b = b1.b + b2.b;
|
||||
result.c = b1.c + b2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
|
||||
result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cls_struct_12byte_gn(ffi_cif* cif __UNUSED__, void* resp,
|
||||
void** args , void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_12byte b1, b2;
|
||||
|
||||
b1 = *(struct cls_struct_12byte*)(args[0]);
|
||||
b2 = *(struct cls_struct_12byte*)(args[1]);
|
||||
|
||||
*(cls_struct_12byte*)resp = cls_struct_12byte_fn(b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_12byte h_dbl = { 7, 4, 9 };
|
||||
struct cls_struct_12byte j_dbl = { 1, 5, 3 };
|
||||
struct cls_struct_12byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_sint;
|
||||
cls_struct_fields[1] = &ffi_type_sint;
|
||||
cls_struct_fields[2] = &ffi_type_sint;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &h_dbl;
|
||||
args_dbl[1] = &j_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_12byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "7 4 9 1 5 3: 8 9 12" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 8 9 12" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_12byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl.a = 0;
|
||||
res_dbl.b = 0;
|
||||
res_dbl.c = 0;
|
||||
|
||||
res_dbl = ((cls_struct_12byte(*)(cls_struct_12byte, cls_struct_12byte))(code))(h_dbl, j_dbl);
|
||||
/* { dg-output "\n7 4 9 1 5 3: 8 9 12" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 8 9 12" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
95
.pc/msvc-changes/testsuite/libffi.call/cls_16byte.c
Normal file
95
.pc/msvc-changes/testsuite/libffi.call/cls_16byte.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_16byte {
|
||||
int a;
|
||||
double b;
|
||||
int c;
|
||||
} cls_struct_16byte;
|
||||
|
||||
cls_struct_16byte cls_struct_16byte_fn(struct cls_struct_16byte b1,
|
||||
struct cls_struct_16byte b2)
|
||||
{
|
||||
struct cls_struct_16byte result;
|
||||
|
||||
result.a = b1.a + b2.a;
|
||||
result.b = b1.b + b2.b;
|
||||
result.c = b1.c + b2.c;
|
||||
|
||||
printf("%d %g %d %d %g %d: %d %g %d\n", b1.a, b1.b, b1.c, b2.a, b2.b, b2.c,
|
||||
result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cls_struct_16byte_gn(ffi_cif* cif __UNUSED__, void* resp,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_16byte b1, b2;
|
||||
|
||||
b1 = *(struct cls_struct_16byte*)(args[0]);
|
||||
b2 = *(struct cls_struct_16byte*)(args[1]);
|
||||
|
||||
*(cls_struct_16byte*)resp = cls_struct_16byte_fn(b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_16byte h_dbl = { 7, 8.0, 9 };
|
||||
struct cls_struct_16byte j_dbl = { 1, 9.0, 3 };
|
||||
struct cls_struct_16byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_sint;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_sint;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &h_dbl;
|
||||
args_dbl[1] = &j_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_16byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "7 8 9 1 9 3: 8 17 12" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 8 17 12" } */
|
||||
|
||||
res_dbl.a = 0;
|
||||
res_dbl.b = 0.0;
|
||||
res_dbl.c = 0;
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_16byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_16byte(*)(cls_struct_16byte, cls_struct_16byte))(code))(h_dbl, j_dbl);
|
||||
/* { dg-output "\n7 8 9 1 9 3: 8 17 12" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 8 17 12" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
96
.pc/msvc-changes/testsuite/libffi.call/cls_18byte.c
Normal file
96
.pc/msvc-changes/testsuite/libffi.call/cls_18byte.c
Normal file
@@ -0,0 +1,96 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Double alignment check on darwin.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030915 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_18byte {
|
||||
double a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
double d;
|
||||
} cls_struct_18byte;
|
||||
|
||||
cls_struct_18byte cls_struct_18byte_fn(struct cls_struct_18byte a1,
|
||||
struct cls_struct_18byte a2)
|
||||
{
|
||||
struct cls_struct_18byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
|
||||
|
||||
printf("%g %d %d %g %g %d %d %g: %g %d %d %g\n", a1.a, a1.b, a1.c, a1.d,
|
||||
a2.a, a2.b, a2.c, a2.d,
|
||||
result.a, result.b, result.c, result.d);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_18byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_18byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_18byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_18byte*)(args[1]);
|
||||
|
||||
*(cls_struct_18byte*)resp = cls_struct_18byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_18byte g_dbl = { 1.0, 127, 126, 3.0 };
|
||||
struct cls_struct_18byte f_dbl = { 4.0, 125, 124, 5.0 };
|
||||
struct cls_struct_18byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_18byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 127 126 3 4 125 124 5: 5 252 250 8" } */
|
||||
printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 5 252 250 8" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_18byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_18byte(*)(cls_struct_18byte, cls_struct_18byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 127 126 3 4 125 124 5: 5 252 250 8" } */
|
||||
printf("res: %g %d %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 5 252 250 8" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
102
.pc/msvc-changes/testsuite/libffi.call/cls_19byte.c
Normal file
102
.pc/msvc-changes/testsuite/libffi.call/cls_19byte.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Double alignment check on darwin.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030915 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_19byte {
|
||||
double a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
double d;
|
||||
unsigned char e;
|
||||
} cls_struct_19byte;
|
||||
|
||||
cls_struct_19byte cls_struct_19byte_fn(struct cls_struct_19byte a1,
|
||||
struct cls_struct_19byte a2)
|
||||
{
|
||||
struct cls_struct_19byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
result.e = a1.e + a2.e;
|
||||
|
||||
|
||||
printf("%g %d %d %g %d %g %d %d %g %d: %g %d %d %g %d\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e,
|
||||
a2.a, a2.b, a2.c, a2.d, a2.e,
|
||||
result.a, result.b, result.c, result.d, result.e);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_19byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_19byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_19byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_19byte*)(args[1]);
|
||||
|
||||
*(cls_struct_19byte*)resp = cls_struct_19byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[6];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_19byte g_dbl = { 1.0, 127, 126, 3.0, 120 };
|
||||
struct cls_struct_19byte f_dbl = { 4.0, 125, 124, 5.0, 119 };
|
||||
struct cls_struct_19byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = &ffi_type_uchar;
|
||||
cls_struct_fields[5] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_19byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
|
||||
printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e);
|
||||
/* { dg-output "\nres: 5 252 250 8 239" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_19byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_19byte(*)(cls_struct_19byte, cls_struct_19byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 127 126 3 120 4 125 124 5 119: 5 252 250 8 239" } */
|
||||
printf("res: %g %d %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e);
|
||||
/* { dg-output "\nres: 5 252 250 8 239" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
89
.pc/msvc-changes/testsuite/libffi.call/cls_1_1byte.c
Normal file
89
.pc/msvc-changes/testsuite/libffi.call/cls_1_1byte.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Especially with small structures which may fit in one
|
||||
register. Depending on the ABI.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030902 */
|
||||
|
||||
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_1_1byte {
|
||||
unsigned char a;
|
||||
} cls_struct_1_1byte;
|
||||
|
||||
cls_struct_1_1byte cls_struct_1_1byte_fn(struct cls_struct_1_1byte a1,
|
||||
struct cls_struct_1_1byte a2)
|
||||
{
|
||||
struct cls_struct_1_1byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
|
||||
printf("%d %d: %d\n", a1.a, a2.a, result.a);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_1_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_1_1byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_1_1byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_1_1byte*)(args[1]);
|
||||
|
||||
*(cls_struct_1_1byte*)resp = cls_struct_1_1byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[2];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_1_1byte g_dbl = { 12 };
|
||||
struct cls_struct_1_1byte f_dbl = { 178 };
|
||||
struct cls_struct_1_1byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_1_1byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 178: 190" } */
|
||||
printf("res: %d\n", res_dbl.a);
|
||||
/* { dg-output "\nres: 190" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_1_1byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_1_1byte(*)(cls_struct_1_1byte, cls_struct_1_1byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 178: 190" } */
|
||||
printf("res: %d\n", res_dbl.a);
|
||||
/* { dg-output "\nres: 190" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_20byte.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_20byte.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_20byte {
|
||||
double a;
|
||||
double b;
|
||||
int c;
|
||||
} cls_struct_20byte;
|
||||
|
||||
cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
|
||||
struct cls_struct_20byte a2)
|
||||
{
|
||||
struct cls_struct_20byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%g %g %d %g %g %d: %g %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
|
||||
result.a, result.b, result.c);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_20byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_20byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_20byte*)(args[1]);
|
||||
|
||||
*(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_20byte g_dbl = { 1.0, 2.0, 3 };
|
||||
struct cls_struct_20byte f_dbl = { 4.0, 5.0, 7 };
|
||||
struct cls_struct_20byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_sint;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 2 3 4 5 7: 5 7 10" } */
|
||||
printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 5 7 10" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
|
||||
printf("res: %g %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 5 7 10" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
93
.pc/msvc-changes/testsuite/libffi.call/cls_20byte1.c
Normal file
93
.pc/msvc-changes/testsuite/libffi.call/cls_20byte1.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_20byte {
|
||||
int a;
|
||||
double b;
|
||||
double c;
|
||||
} cls_struct_20byte;
|
||||
|
||||
cls_struct_20byte cls_struct_20byte_fn(struct cls_struct_20byte a1,
|
||||
struct cls_struct_20byte a2)
|
||||
{
|
||||
struct cls_struct_20byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %g %g %d %g %g: %d %g %g\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c,
|
||||
result.a, result.b, result.c);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_20byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_20byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_20byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_20byte*)(args[1]);
|
||||
|
||||
*(cls_struct_20byte*)resp = cls_struct_20byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_20byte g_dbl = { 1, 2.0, 3.0 };
|
||||
struct cls_struct_20byte f_dbl = { 4, 5.0, 7.0 };
|
||||
struct cls_struct_20byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_sint;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_double;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 2 3 4 5 7: 5 7 10" } */
|
||||
printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 5 7 10" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_20byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */
|
||||
printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 5 7 10" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
113
.pc/msvc-changes/testsuite/libffi.call/cls_24byte.c
Normal file
113
.pc/msvc-changes/testsuite/libffi.call/cls_24byte.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_24byte {
|
||||
double a;
|
||||
double b;
|
||||
int c;
|
||||
float d;
|
||||
} cls_struct_24byte;
|
||||
|
||||
cls_struct_24byte cls_struct_24byte_fn(struct cls_struct_24byte b0,
|
||||
struct cls_struct_24byte b1,
|
||||
struct cls_struct_24byte b2,
|
||||
struct cls_struct_24byte b3)
|
||||
{
|
||||
struct cls_struct_24byte result;
|
||||
|
||||
result.a = b0.a + b1.a + b2.a + b3.a;
|
||||
result.b = b0.b + b1.b + b2.b + b3.b;
|
||||
result.c = b0.c + b1.c + b2.c + b3.c;
|
||||
result.d = b0.d + b1.d + b2.d + b3.d;
|
||||
|
||||
printf("%g %g %d %g %g %g %d %g %g %g %d %g %g %g %d %g: %g %g %d %g\n",
|
||||
b0.a, b0.b, b0.c, b0.d,
|
||||
b1.a, b1.b, b1.c, b1.d,
|
||||
b2.a, b2.b, b2.c, b2.d,
|
||||
b3.a, b3.b, b3.c, b2.d,
|
||||
result.a, result.b, result.c, result.d);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_24byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_24byte b0, b1, b2, b3;
|
||||
|
||||
b0 = *(struct cls_struct_24byte*)(args[0]);
|
||||
b1 = *(struct cls_struct_24byte*)(args[1]);
|
||||
b2 = *(struct cls_struct_24byte*)(args[2]);
|
||||
b3 = *(struct cls_struct_24byte*)(args[3]);
|
||||
|
||||
*(cls_struct_24byte*)resp = cls_struct_24byte_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_24byte e_dbl = { 9.0, 2.0, 6, 5.0 };
|
||||
struct cls_struct_24byte f_dbl = { 1.0, 2.0, 3, 7.0 };
|
||||
struct cls_struct_24byte g_dbl = { 4.0, 5.0, 7, 9.0 };
|
||||
struct cls_struct_24byte h_dbl = { 8.0, 6.0, 1, 4.0 };
|
||||
struct cls_struct_24byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_sint;
|
||||
cls_struct_fields[3] = &ffi_type_float;
|
||||
cls_struct_fields[4] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = &cls_struct_type;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_24byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
|
||||
printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 22 15 17 25" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_24byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_24byte(*)(cls_struct_24byte,
|
||||
cls_struct_24byte,
|
||||
cls_struct_24byte,
|
||||
cls_struct_24byte))
|
||||
(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n9 2 6 5 1 2 3 7 4 5 7 9 8 6 1 9: 22 15 17 25" } */
|
||||
printf("res: %g %g %d %g\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 22 15 17 25" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
90
.pc/msvc-changes/testsuite/libffi.call/cls_2byte.c
Normal file
90
.pc/msvc-changes/testsuite/libffi.call/cls_2byte.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Especially with small structures which may fit in one
|
||||
register. Depending on the ABI.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_2byte {
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
} cls_struct_2byte;
|
||||
|
||||
cls_struct_2byte cls_struct_2byte_fn(struct cls_struct_2byte a1,
|
||||
struct cls_struct_2byte a2)
|
||||
{
|
||||
struct cls_struct_2byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
|
||||
printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_2byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_2byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_2byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_2byte*)(args[1]);
|
||||
|
||||
*(cls_struct_2byte*)resp = cls_struct_2byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_2byte g_dbl = { 12, 127 };
|
||||
struct cls_struct_2byte f_dbl = { 1, 13 };
|
||||
struct cls_struct_2byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_2byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 127 1 13: 13 140" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 13 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_2byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_2byte(*)(cls_struct_2byte, cls_struct_2byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 127 1 13: 13 140" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 13 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
95
.pc/msvc-changes/testsuite/libffi.call/cls_3_1byte.c
Normal file
95
.pc/msvc-changes/testsuite/libffi.call/cls_3_1byte.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Especially with small structures which may fit in one
|
||||
register. Depending on the ABI.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030902 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_3_1byte {
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
} cls_struct_3_1byte;
|
||||
|
||||
cls_struct_3_1byte cls_struct_3_1byte_fn(struct cls_struct_3_1byte a1,
|
||||
struct cls_struct_3_1byte a2)
|
||||
{
|
||||
struct cls_struct_3_1byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
|
||||
a2.a, a2.b, a2.c,
|
||||
result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_3_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_3_1byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_3_1byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_3_1byte*)(args[1]);
|
||||
|
||||
*(cls_struct_3_1byte*)resp = cls_struct_3_1byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_3_1byte g_dbl = { 12, 13, 14 };
|
||||
struct cls_struct_3_1byte f_dbl = { 178, 179, 180 };
|
||||
struct cls_struct_3_1byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_3_1byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 13 14 178 179 180: 190 192 194" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 190 192 194" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3_1byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_3_1byte(*)(cls_struct_3_1byte, cls_struct_3_1byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 13 14 178 179 180: 190 192 194" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 190 192 194" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
90
.pc/msvc-changes/testsuite/libffi.call/cls_3byte1.c
Normal file
90
.pc/msvc-changes/testsuite/libffi.call/cls_3byte1.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Especially with small structures which may fit in one
|
||||
register. Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_3byte {
|
||||
unsigned short a;
|
||||
unsigned char b;
|
||||
} cls_struct_3byte;
|
||||
|
||||
cls_struct_3byte cls_struct_3byte_fn(struct cls_struct_3byte a1,
|
||||
struct cls_struct_3byte a2)
|
||||
{
|
||||
struct cls_struct_3byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
|
||||
printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_3byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_3byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_3byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_3byte*)(args[1]);
|
||||
|
||||
*(cls_struct_3byte*)resp = cls_struct_3byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_3byte g_dbl = { 12, 119 };
|
||||
struct cls_struct_3byte f_dbl = { 1, 15 };
|
||||
struct cls_struct_3byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_ushort;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_3byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 119 1 15: 13 134" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 13 134" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_3byte(*)(cls_struct_3byte, cls_struct_3byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 119 1 15: 13 134" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 13 134" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
90
.pc/msvc-changes/testsuite/libffi.call/cls_3byte2.c
Normal file
90
.pc/msvc-changes/testsuite/libffi.call/cls_3byte2.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Especially with small structures which may fit in one
|
||||
register. Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_3byte_1 {
|
||||
unsigned char a;
|
||||
unsigned short b;
|
||||
} cls_struct_3byte_1;
|
||||
|
||||
cls_struct_3byte_1 cls_struct_3byte_fn1(struct cls_struct_3byte_1 a1,
|
||||
struct cls_struct_3byte_1 a2)
|
||||
{
|
||||
struct cls_struct_3byte_1 result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
|
||||
printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_3byte_gn1(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_3byte_1 a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_3byte_1*)(args[0]);
|
||||
a2 = *(struct cls_struct_3byte_1*)(args[1]);
|
||||
|
||||
*(cls_struct_3byte_1*)resp = cls_struct_3byte_fn1(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_3byte_1 g_dbl = { 15, 125 };
|
||||
struct cls_struct_3byte_1 f_dbl = { 9, 19 };
|
||||
struct cls_struct_3byte_1 res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_ushort;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_3byte_fn1), &res_dbl, args_dbl);
|
||||
/* { dg-output "15 125 9 19: 24 144" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 24 144" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3byte_gn1, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_3byte_1(*)(cls_struct_3byte_1, cls_struct_3byte_1))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n15 125 9 19: 24 144" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 24 144" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
98
.pc/msvc-changes/testsuite/libffi.call/cls_4_1byte.c
Normal file
98
.pc/msvc-changes/testsuite/libffi.call/cls_4_1byte.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Especially with small structures which may fit in one
|
||||
register. Depending on the ABI.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030902 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_4_1byte {
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
unsigned char d;
|
||||
} cls_struct_4_1byte;
|
||||
|
||||
cls_struct_4_1byte cls_struct_4_1byte_fn(struct cls_struct_4_1byte a1,
|
||||
struct cls_struct_4_1byte a2)
|
||||
{
|
||||
struct cls_struct_4_1byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
|
||||
a2.a, a2.b, a2.c, a2.d,
|
||||
result.a, result.b, result.c, result.d);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_4_1byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_4_1byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_4_1byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_4_1byte*)(args[1]);
|
||||
|
||||
*(cls_struct_4_1byte*)resp = cls_struct_4_1byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_4_1byte g_dbl = { 12, 13, 14, 15 };
|
||||
struct cls_struct_4_1byte f_dbl = { 178, 179, 180, 181 };
|
||||
struct cls_struct_4_1byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_uchar;
|
||||
cls_struct_fields[4] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_4_1byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 13 14 15 178 179 180 181: 190 192 194 196" } */
|
||||
printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 190 192 194 196" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_4_1byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_4_1byte(*)(cls_struct_4_1byte, cls_struct_4_1byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 13 14 15 178 179 180 181: 190 192 194 196" } */
|
||||
printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 190 192 194 196" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
90
.pc/msvc-changes/testsuite/libffi.call/cls_4byte.c
Normal file
90
.pc/msvc-changes/testsuite/libffi.call/cls_4byte.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_4byte {
|
||||
unsigned short a;
|
||||
unsigned short b;
|
||||
} cls_struct_4byte;
|
||||
|
||||
cls_struct_4byte cls_struct_4byte_fn(struct cls_struct_4byte a1,
|
||||
struct cls_struct_4byte a2)
|
||||
{
|
||||
struct cls_struct_4byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
|
||||
printf("%d %d %d %d: %d %d\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_4byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_4byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_4byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_4byte*)(args[1]);
|
||||
|
||||
*(cls_struct_4byte*)resp = cls_struct_4byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_4byte g_dbl = { 127, 120 };
|
||||
struct cls_struct_4byte f_dbl = { 12, 128 };
|
||||
struct cls_struct_4byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_ushort;
|
||||
cls_struct_fields[1] = &ffi_type_ushort;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_4byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 12 128: 139 248" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 139 248" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_4byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_4byte(*)(cls_struct_4byte, cls_struct_4byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 12 128: 139 248" } */
|
||||
printf("res: %d %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 139 248" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
109
.pc/msvc-changes/testsuite/libffi.call/cls_5_1_byte.c
Normal file
109
.pc/msvc-changes/testsuite/libffi.call/cls_5_1_byte.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20050708 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_5byte {
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
unsigned char d;
|
||||
unsigned char e;
|
||||
} cls_struct_5byte;
|
||||
|
||||
cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
|
||||
struct cls_struct_5byte a2)
|
||||
{
|
||||
struct cls_struct_5byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
result.e = a1.e + a2.e;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e,
|
||||
a2.a, a2.b, a2.c, a2.d, a2.e,
|
||||
result.a, result.b, result.c, result.d, result.e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_5byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_5byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_5byte*)(args[1]);
|
||||
|
||||
*(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[6];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_5byte g_dbl = { 127, 120, 1, 3, 4 };
|
||||
struct cls_struct_5byte f_dbl = { 12, 128, 9, 3, 4 };
|
||||
struct cls_struct_5byte res_dbl = { 0, 0, 0, 0, 0 };
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_uchar;
|
||||
cls_struct_fields[4] = &ffi_type_uchar;
|
||||
cls_struct_fields[5] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
|
||||
printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e);
|
||||
/* { dg-output "\nres: 139 248 10 6 8" } */
|
||||
|
||||
res_dbl.a = 0;
|
||||
res_dbl.b = 0;
|
||||
res_dbl.c = 0;
|
||||
res_dbl.d = 0;
|
||||
res_dbl.e = 0;
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 1 3 4 12 128 9 3 4: 139 248 10 6 8" } */
|
||||
printf("res: %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e);
|
||||
/* { dg-output "\nres: 139 248 10 6 8" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
98
.pc/msvc-changes/testsuite/libffi.call/cls_5byte.c
Normal file
98
.pc/msvc-changes/testsuite/libffi.call/cls_5byte.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_5byte {
|
||||
unsigned short a;
|
||||
unsigned short b;
|
||||
unsigned char c;
|
||||
} cls_struct_5byte;
|
||||
|
||||
cls_struct_5byte cls_struct_5byte_fn(struct cls_struct_5byte a1,
|
||||
struct cls_struct_5byte a2)
|
||||
{
|
||||
struct cls_struct_5byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c,
|
||||
a2.a, a2.b, a2.c,
|
||||
result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_5byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_5byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_5byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_5byte*)(args[1]);
|
||||
|
||||
*(cls_struct_5byte*)resp = cls_struct_5byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_5byte g_dbl = { 127, 120, 1 };
|
||||
struct cls_struct_5byte f_dbl = { 12, 128, 9 };
|
||||
struct cls_struct_5byte res_dbl = { 0, 0, 0 };
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_ushort;
|
||||
cls_struct_fields[1] = &ffi_type_ushort;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_5byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 1 12 128 9: 139 248 10" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 139 248 10" } */
|
||||
|
||||
res_dbl.a = 0;
|
||||
res_dbl.b = 0;
|
||||
res_dbl.c = 0;
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_5byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_5byte(*)(cls_struct_5byte, cls_struct_5byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 1 12 128 9: 139 248 10" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 139 248 10" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
124
.pc/msvc-changes/testsuite/libffi.call/cls_64byte.c
Normal file
124
.pc/msvc-changes/testsuite/libffi.call/cls_64byte.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check bigger struct which overlaps
|
||||
the gp and fp register count on Darwin/AIX/ppc64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_64byte {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
double g;
|
||||
double h;
|
||||
} cls_struct_64byte;
|
||||
|
||||
cls_struct_64byte cls_struct_64byte_fn(struct cls_struct_64byte b0,
|
||||
struct cls_struct_64byte b1,
|
||||
struct cls_struct_64byte b2,
|
||||
struct cls_struct_64byte b3)
|
||||
{
|
||||
struct cls_struct_64byte result;
|
||||
|
||||
result.a = b0.a + b1.a + b2.a + b3.a;
|
||||
result.b = b0.b + b1.b + b2.b + b3.b;
|
||||
result.c = b0.c + b1.c + b2.c + b3.c;
|
||||
result.d = b0.d + b1.d + b2.d + b3.d;
|
||||
result.e = b0.e + b1.e + b2.e + b3.e;
|
||||
result.f = b0.f + b1.f + b2.f + b3.f;
|
||||
result.g = b0.g + b1.g + b2.g + b3.g;
|
||||
result.h = b0.h + b1.h + b2.h + b3.h;
|
||||
|
||||
printf("%g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
|
||||
result.d, result.e, result.f, result.g, result.h);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_64byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_64byte b0, b1, b2, b3;
|
||||
|
||||
b0 = *(struct cls_struct_64byte*)(args[0]);
|
||||
b1 = *(struct cls_struct_64byte*)(args[1]);
|
||||
b2 = *(struct cls_struct_64byte*)(args[2]);
|
||||
b3 = *(struct cls_struct_64byte*)(args[3]);
|
||||
|
||||
*(cls_struct_64byte*)resp = cls_struct_64byte_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[9];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_64byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0 };
|
||||
struct cls_struct_64byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0 };
|
||||
struct cls_struct_64byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0 };
|
||||
struct cls_struct_64byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0 };
|
||||
struct cls_struct_64byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_double;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = &ffi_type_double;
|
||||
cls_struct_fields[5] = &ffi_type_double;
|
||||
cls_struct_fields[6] = &ffi_type_double;
|
||||
cls_struct_fields[7] = &ffi_type_double;
|
||||
cls_struct_fields[8] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = &cls_struct_type;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_64byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "22 15 17 25 6 13 19 18" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_64byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_64byte(*)(cls_struct_64byte,
|
||||
cls_struct_64byte,
|
||||
cls_struct_64byte,
|
||||
cls_struct_64byte))
|
||||
(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n22 15 17 25 6 13 19 18" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
113
.pc/msvc-changes/testsuite/libffi.call/cls_6_1_byte.c
Normal file
113
.pc/msvc-changes/testsuite/libffi.call/cls_6_1_byte.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20050708 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_6byte {
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
unsigned char d;
|
||||
unsigned char e;
|
||||
unsigned char f;
|
||||
} cls_struct_6byte;
|
||||
|
||||
cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
|
||||
struct cls_struct_6byte a2)
|
||||
{
|
||||
struct cls_struct_6byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
result.e = a1.e + a2.e;
|
||||
result.f = a1.f + a2.f;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e, a1.f,
|
||||
a2.a, a2.b, a2.c, a2.d, a2.e, a2.f,
|
||||
result.a, result.b, result.c, result.d, result.e, result.f);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_6byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_6byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_6byte*)(args[1]);
|
||||
|
||||
*(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[7];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_6byte g_dbl = { 127, 120, 1, 3, 4, 5 };
|
||||
struct cls_struct_6byte f_dbl = { 12, 128, 9, 3, 4, 5 };
|
||||
struct cls_struct_6byte res_dbl = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_uchar;
|
||||
cls_struct_fields[4] = &ffi_type_uchar;
|
||||
cls_struct_fields[5] = &ffi_type_uchar;
|
||||
cls_struct_fields[6] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
|
||||
printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f);
|
||||
/* { dg-output "\nres: 139 248 10 6 8 10" } */
|
||||
|
||||
res_dbl.a = 0;
|
||||
res_dbl.b = 0;
|
||||
res_dbl.c = 0;
|
||||
res_dbl.d = 0;
|
||||
res_dbl.e = 0;
|
||||
res_dbl.f = 0;
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 1 3 4 5 12 128 9 3 4 5: 139 248 10 6 8 10" } */
|
||||
printf("res: %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f);
|
||||
/* { dg-output "\nres: 139 248 10 6 8 10" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
99
.pc/msvc-changes/testsuite/libffi.call/cls_6byte.c
Normal file
99
.pc/msvc-changes/testsuite/libffi.call/cls_6byte.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_6byte {
|
||||
unsigned short a;
|
||||
unsigned short b;
|
||||
unsigned char c;
|
||||
unsigned char d;
|
||||
} cls_struct_6byte;
|
||||
|
||||
cls_struct_6byte cls_struct_6byte_fn(struct cls_struct_6byte a1,
|
||||
struct cls_struct_6byte a2)
|
||||
{
|
||||
struct cls_struct_6byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
|
||||
a2.a, a2.b, a2.c, a2.d,
|
||||
result.a, result.b, result.c, result.d);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_6byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_6byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_6byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_6byte*)(args[1]);
|
||||
|
||||
*(cls_struct_6byte*)resp = cls_struct_6byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_6byte g_dbl = { 127, 120, 1, 128 };
|
||||
struct cls_struct_6byte f_dbl = { 12, 128, 9, 127 };
|
||||
struct cls_struct_6byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_ushort;
|
||||
cls_struct_fields[1] = &ffi_type_ushort;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_uchar;
|
||||
cls_struct_fields[4] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_6byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 1 128 12 128 9 127: 139 248 10 255" } */
|
||||
printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 139 248 10 255" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_6byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_6byte(*)(cls_struct_6byte, cls_struct_6byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 1 128 12 128 9 127: 139 248 10 255" } */
|
||||
printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 139 248 10 255" } */
|
||||
|
||||
|
||||
exit(0);
|
||||
}
|
||||
117
.pc/msvc-changes/testsuite/libffi.call/cls_7_1_byte.c
Normal file
117
.pc/msvc-changes/testsuite/libffi.call/cls_7_1_byte.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20050708 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_7byte {
|
||||
unsigned char a;
|
||||
unsigned char b;
|
||||
unsigned char c;
|
||||
unsigned char d;
|
||||
unsigned char e;
|
||||
unsigned char f;
|
||||
unsigned char g;
|
||||
} cls_struct_7byte;
|
||||
|
||||
cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
|
||||
struct cls_struct_7byte a2)
|
||||
{
|
||||
struct cls_struct_7byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
result.e = a1.e + a2.e;
|
||||
result.f = a1.f + a2.f;
|
||||
result.g = a1.g + a2.g;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d %d %d %d %d %d %d\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
|
||||
a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
|
||||
result.a, result.b, result.c, result.d, result.e, result.f, result.g);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_7byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_7byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_7byte*)(args[1]);
|
||||
|
||||
*(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[8];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_7byte g_dbl = { 127, 120, 1, 3, 4, 5, 6 };
|
||||
struct cls_struct_7byte f_dbl = { 12, 128, 9, 3, 4, 5, 6 };
|
||||
struct cls_struct_7byte res_dbl = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_uchar;
|
||||
cls_struct_fields[4] = &ffi_type_uchar;
|
||||
cls_struct_fields[5] = &ffi_type_uchar;
|
||||
cls_struct_fields[6] = &ffi_type_uchar;
|
||||
cls_struct_fields[7] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
|
||||
printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
|
||||
/* { dg-output "\nres: 139 248 10 6 8 10 12" } */
|
||||
|
||||
res_dbl.a = 0;
|
||||
res_dbl.b = 0;
|
||||
res_dbl.c = 0;
|
||||
res_dbl.d = 0;
|
||||
res_dbl.e = 0;
|
||||
res_dbl.f = 0;
|
||||
res_dbl.g = 0;
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 1 3 4 5 6 12 128 9 3 4 5 6: 139 248 10 6 8 10 12" } */
|
||||
printf("res: %d %d %d %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
|
||||
/* { dg-output "\nres: 139 248 10 6 8 10 12" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
97
.pc/msvc-changes/testsuite/libffi.call/cls_7byte.c
Normal file
97
.pc/msvc-changes/testsuite/libffi.call/cls_7byte.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_7byte {
|
||||
unsigned short a;
|
||||
unsigned short b;
|
||||
unsigned char c;
|
||||
unsigned short d;
|
||||
} cls_struct_7byte;
|
||||
|
||||
cls_struct_7byte cls_struct_7byte_fn(struct cls_struct_7byte a1,
|
||||
struct cls_struct_7byte a2)
|
||||
{
|
||||
struct cls_struct_7byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
result.d = a1.d + a2.d;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d: %d %d %d %d\n", a1.a, a1.b, a1.c, a1.d,
|
||||
a2.a, a2.b, a2.c, a2.d,
|
||||
result.a, result.b, result.c, result.d);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_7byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_7byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_7byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_7byte*)(args[1]);
|
||||
|
||||
*(cls_struct_7byte*)resp = cls_struct_7byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_7byte g_dbl = { 127, 120, 1, 254 };
|
||||
struct cls_struct_7byte f_dbl = { 12, 128, 9, 255 };
|
||||
struct cls_struct_7byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_ushort;
|
||||
cls_struct_fields[1] = &ffi_type_ushort;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = &ffi_type_ushort;
|
||||
cls_struct_fields[4] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "127 120 1 254 12 128 9 255: 139 248 10 509" } */
|
||||
printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 139 248 10 509" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_7byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n127 120 1 254 12 128 9 255: 139 248 10 509" } */
|
||||
printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d);
|
||||
/* { dg-output "\nres: 139 248 10 509" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
88
.pc/msvc-changes/testsuite/libffi.call/cls_8byte.c
Normal file
88
.pc/msvc-changes/testsuite/libffi.call/cls_8byte.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Check overlapping.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_8byte {
|
||||
int a;
|
||||
float b;
|
||||
} cls_struct_8byte;
|
||||
|
||||
cls_struct_8byte cls_struct_8byte_fn(struct cls_struct_8byte a1,
|
||||
struct cls_struct_8byte a2)
|
||||
{
|
||||
struct cls_struct_8byte result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
|
||||
printf("%d %g %d %g: %d %g\n", a1.a, a1.b, a2.a, a2.b, result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_8byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_8byte a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_8byte*)(args[0]);
|
||||
a2 = *(struct cls_struct_8byte*)(args[1]);
|
||||
|
||||
*(cls_struct_8byte*)resp = cls_struct_8byte_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_8byte g_dbl = { 1, 2.0 };
|
||||
struct cls_struct_8byte f_dbl = { 4, 5.0 };
|
||||
struct cls_struct_8byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_sint;
|
||||
cls_struct_fields[1] = &ffi_type_float;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_8byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 2 4 5: 5 7" } */
|
||||
printf("res: %d %g\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 5 7" } */
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_8byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_8byte(*)(cls_struct_8byte, cls_struct_8byte))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 2 4 5: 5 7" } */
|
||||
printf("res: %d %g\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 5 7" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
90
.pc/msvc-changes/testsuite/libffi.call/cls_9byte1.c
Normal file
90
.pc/msvc-changes/testsuite/libffi.call/cls_9byte1.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Darwin/AIX do double-word
|
||||
alignment of the struct if the first element is a double.
|
||||
Check that it does not here.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030914 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_9byte {
|
||||
int a;
|
||||
double b;
|
||||
} cls_struct_9byte;
|
||||
|
||||
cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
|
||||
struct cls_struct_9byte b2)
|
||||
{
|
||||
struct cls_struct_9byte result;
|
||||
|
||||
result.a = b1.a + b2.a;
|
||||
result.b = b1.b + b2.b;
|
||||
|
||||
printf("%d %g %d %g: %d %g\n", b1.a, b1.b, b2.a, b2.b,
|
||||
result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_9byte b1, b2;
|
||||
|
||||
b1 = *(struct cls_struct_9byte*)(args[0]);
|
||||
b2 = *(struct cls_struct_9byte*)(args[1]);
|
||||
|
||||
*(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_9byte h_dbl = { 7, 8.0};
|
||||
struct cls_struct_9byte j_dbl = { 1, 9.0};
|
||||
struct cls_struct_9byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_sint;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &h_dbl;
|
||||
args_dbl[1] = &j_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "7 8 1 9: 8 17" } */
|
||||
printf("res: %d %g\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 8 17" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl);
|
||||
/* { dg-output "\n7 8 1 9: 8 17" } */
|
||||
printf("res: %d %g\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 8 17" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_9byte2.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_9byte2.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Depending on the ABI. Darwin/AIX do double-word
|
||||
alignment of the struct if the first element is a double.
|
||||
Check that it does here.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030914 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_9byte {
|
||||
double a;
|
||||
int b;
|
||||
} cls_struct_9byte;
|
||||
|
||||
cls_struct_9byte cls_struct_9byte_fn(struct cls_struct_9byte b1,
|
||||
struct cls_struct_9byte b2)
|
||||
{
|
||||
struct cls_struct_9byte result;
|
||||
|
||||
result.a = b1.a + b2.a;
|
||||
result.b = b1.b + b2.b;
|
||||
|
||||
printf("%g %d %g %d: %g %d\n", b1.a, b1.b, b2.a, b2.b,
|
||||
result.a, result.b);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void cls_struct_9byte_gn(ffi_cif* cif __UNUSED__, void* resp,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_9byte b1, b2;
|
||||
|
||||
b1 = *(struct cls_struct_9byte*)(args[0]);
|
||||
b2 = *(struct cls_struct_9byte*)(args[1]);
|
||||
|
||||
*(cls_struct_9byte*)resp = cls_struct_9byte_fn(b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_9byte h_dbl = { 7.0, 8};
|
||||
struct cls_struct_9byte j_dbl = { 1.0, 9};
|
||||
struct cls_struct_9byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_sint;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &h_dbl;
|
||||
args_dbl[1] = &j_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_9byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "7 8 1 9: 8 17" } */
|
||||
printf("res: %g %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 8 17" } */
|
||||
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_9byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_9byte(*)(cls_struct_9byte, cls_struct_9byte))(code))(h_dbl, j_dbl);
|
||||
/* { dg-output "\n7 8 1 9: 8 17" } */
|
||||
printf("res: %g %d\n", res_dbl.a, res_dbl.b);
|
||||
/* { dg-output "\nres: 8 17" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
93
.pc/msvc-changes/testsuite/libffi.call/cls_align_double.c
Normal file
93
.pc/msvc-changes/testsuite/libffi.call/cls_align_double.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of double.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
double b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_float.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_float.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of float.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
float b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_float;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of long double.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
long double b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %g %d %d %g %d: %d %g %d\n", a1.a, (double)a1.b, a1.c, a2.a, (double)a2.b, a2.c, result.a, (double)result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_longdouble;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %g %d\n", res_dbl.a, (double)res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of long double.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
|
||||
/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
long double a;
|
||||
long double b;
|
||||
long double c;
|
||||
long double d;
|
||||
long double e;
|
||||
long double f;
|
||||
long double g;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(
|
||||
cls_struct_align a1,
|
||||
cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align r;
|
||||
|
||||
r.a = a1.a + a2.a;
|
||||
r.b = a1.b + a2.b;
|
||||
r.c = a1.c + a2.c;
|
||||
r.d = a1.d + a2.d;
|
||||
r.e = a1.e + a2.e;
|
||||
r.f = a1.f + a2.f;
|
||||
r.g = a1.g + a2.g;
|
||||
|
||||
printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
|
||||
"%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
|
||||
a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
|
||||
r.a, r.b, r.c, r.d, r.e, r.f, r.g);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
cls_struct_align cls_struct_align_fn2(
|
||||
cls_struct_align a1)
|
||||
{
|
||||
struct cls_struct_align r;
|
||||
|
||||
r.a = a1.a + 1;
|
||||
r.b = a1.b + 1;
|
||||
r.c = a1.c + 1;
|
||||
r.d = a1.d + 1;
|
||||
r.e = a1.e + 1;
|
||||
r.f = a1.f + 1;
|
||||
r.g = a1.g + 1;
|
||||
|
||||
printf("%Lg %Lg %Lg %Lg %Lg %Lg %Lg: "
|
||||
"%Lg %Lg %Lg %Lg %Lg %Lg %Lg\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
|
||||
r.a, r.b, r.c, r.d, r.e, r.f, r.g);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[8];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
|
||||
struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_longdouble;
|
||||
cls_struct_fields[1] = &ffi_type_longdouble;
|
||||
cls_struct_fields[2] = &ffi_type_longdouble;
|
||||
cls_struct_fields[3] = &ffi_type_longdouble;
|
||||
cls_struct_fields[4] = &ffi_type_longdouble;
|
||||
cls_struct_fields[5] = &ffi_type_longdouble;
|
||||
cls_struct_fields[6] = &ffi_type_longdouble;
|
||||
cls_struct_fields[7] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
|
||||
printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
|
||||
/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
|
||||
printf("res: %Lg %Lg %Lg %Lg %Lg %Lg %Lg\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
|
||||
/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of long double.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/18/2007
|
||||
*/
|
||||
|
||||
/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
|
||||
/* { dg-do run { xfail strongarm*-*-* } } */
|
||||
/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
|
||||
/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
long double a;
|
||||
long double b;
|
||||
long double c;
|
||||
long double d;
|
||||
long double e;
|
||||
double f;
|
||||
long double g;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(
|
||||
cls_struct_align a1,
|
||||
cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align r;
|
||||
|
||||
r.a = a1.a + a2.a;
|
||||
r.b = a1.b + a2.b;
|
||||
r.c = a1.c + a2.c;
|
||||
r.d = a1.d + a2.d;
|
||||
r.e = a1.e + a2.e;
|
||||
r.f = a1.f + a2.f;
|
||||
r.g = a1.g + a2.g;
|
||||
|
||||
printf("%Lg %Lg %Lg %Lg %Lg %g %Lg %Lg %Lg %Lg %Lg %Lg %g %Lg: "
|
||||
"%Lg %Lg %Lg %Lg %Lg %g %Lg\n",
|
||||
a1.a, a1.b, a1.c, a1.d, a1.e, a1.f, a1.g,
|
||||
a2.a, a2.b, a2.c, a2.d, a2.e, a2.f, a2.g,
|
||||
r.a, r.b, r.c, r.d, r.e, r.f, r.g);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[8];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 1, 2, 3, 4, 5, 6, 7 };
|
||||
struct cls_struct_align f_dbl = { 8, 9, 10, 11, 12, 13, 14 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_longdouble;
|
||||
cls_struct_fields[1] = &ffi_type_longdouble;
|
||||
cls_struct_fields[2] = &ffi_type_longdouble;
|
||||
cls_struct_fields[3] = &ffi_type_longdouble;
|
||||
cls_struct_fields[4] = &ffi_type_longdouble;
|
||||
cls_struct_fields[5] = &ffi_type_double;
|
||||
cls_struct_fields[6] = &ffi_type_longdouble;
|
||||
cls_struct_fields[7] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
|
||||
printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
|
||||
/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 12 13 14: 9 11 13 15 17 19 21" } */
|
||||
printf("res: %Lg %Lg %Lg %Lg %Lg %g %Lg\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g);
|
||||
/* { dg-output "\nres: 9 11 13 15 17 19 21" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
95
.pc/msvc-changes/testsuite/libffi.call/cls_align_pointer.c
Normal file
95
.pc/msvc-changes/testsuite/libffi.call/cls_align_pointer.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of pointer.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
void *b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = (void *)((uintptr_t)a1.b + (uintptr_t)a2.b);
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %" PRIuPTR " %d %d %" PRIuPTR " %d: %d %" PRIuPTR " %d\n",
|
||||
a1.a, (uintptr_t)a1.b, a1.c,
|
||||
a2.a, (uintptr_t)a2.b, a2.c,
|
||||
result.a, (uintptr_t)result.b,
|
||||
result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, (void *)4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, (void *)9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_pointer;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %" PRIuPTR " %d\n", res_dbl.a, (uintptr_t)res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_sint16.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_sint16.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of sint16.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
signed short b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_sshort;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_sint32.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_sint32.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of sint32.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
signed int b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_sint;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
92
.pc/msvc-changes/testsuite/libffi.call/cls_align_sint64.c
Normal file
92
.pc/msvc-changes/testsuite/libffi.call/cls_align_sint64.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of sint64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
signed long long b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_sint64;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_uint16.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_uint16.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of uint16.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
unsigned short b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_ushort;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_uint32.c
Normal file
91
.pc/msvc-changes/testsuite/libffi.call/cls_align_uint32.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of uint32.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
unsigned int b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %d %d %d %d %d: %d %d %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uint;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
93
.pc/msvc-changes/testsuite/libffi.call/cls_align_uint64.c
Normal file
93
.pc/msvc-changes/testsuite/libffi.call/cls_align_uint64.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure alignment of uint64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <hos@tamanegi.org> 20031203 */
|
||||
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_align {
|
||||
unsigned char a;
|
||||
unsigned long long b;
|
||||
unsigned char c;
|
||||
} cls_struct_align;
|
||||
|
||||
cls_struct_align cls_struct_align_fn(struct cls_struct_align a1,
|
||||
struct cls_struct_align a2)
|
||||
{
|
||||
struct cls_struct_align result;
|
||||
|
||||
result.a = a1.a + a2.a;
|
||||
result.b = a1.b + a2.b;
|
||||
result.c = a1.c + a2.c;
|
||||
|
||||
printf("%d %" PRIdLL " %d %d %" PRIdLL " %d: %d %" PRIdLL " %d\n", a1.a, a1.b, a1.c, a2.a, a2.b, a2.c, result.a, result.b, result.c);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
|
||||
struct cls_struct_align a1, a2;
|
||||
|
||||
a1 = *(struct cls_struct_align*)(args[0]);
|
||||
a2 = *(struct cls_struct_align*)(args[1]);
|
||||
|
||||
*(cls_struct_align*)resp = cls_struct_align_fn(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[4];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct cls_struct_align g_dbl = { 12, 4951, 127 };
|
||||
struct cls_struct_align f_dbl = { 1, 9320, 13 };
|
||||
struct cls_struct_align res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uint64;
|
||||
cls_struct_fields[2] = &ffi_type_uchar;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &g_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_dbl, f_dbl);
|
||||
/* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */
|
||||
printf("res: %d %" PRIdLL " %d\n", res_dbl.a, res_dbl.b, res_dbl.c);
|
||||
/* { dg-output "\nres: 13 14271 140" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
66
.pc/msvc-changes/testsuite/libffi.call/cls_dbls_struct.c
Normal file
66
.pc/msvc-changes/testsuite/libffi.call/cls_dbls_struct.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check double arguments in structs.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/23/2007 */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct Dbls {
|
||||
double x;
|
||||
double y;
|
||||
} Dbls;
|
||||
|
||||
void
|
||||
closure_test_fn(Dbls p)
|
||||
{
|
||||
printf("%.1f %.1f\n", p.x, p.y);
|
||||
}
|
||||
|
||||
void
|
||||
closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
closure_test_fn(*(Dbls*)args[0]);
|
||||
}
|
||||
|
||||
int main(int argc __UNUSED__, char** argv __UNUSED__)
|
||||
{
|
||||
ffi_cif cif;
|
||||
|
||||
void *code;
|
||||
ffi_closure* pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
ffi_type* cl_arg_types[1];
|
||||
|
||||
ffi_type ts1_type;
|
||||
ffi_type* ts1_type_elements[4];
|
||||
|
||||
ts1_type.size = 0;
|
||||
ts1_type.alignment = 0;
|
||||
ts1_type.type = FFI_TYPE_STRUCT;
|
||||
ts1_type.elements = ts1_type_elements;
|
||||
|
||||
ts1_type_elements[0] = &ffi_type_double;
|
||||
ts1_type_elements[1] = &ffi_type_double;
|
||||
ts1_type_elements[2] = NULL;
|
||||
|
||||
cl_arg_types[0] = &ts1_type;
|
||||
|
||||
Dbls arg = { 1.0, 2.0 };
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_void, cl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK);
|
||||
|
||||
((void*(*)(Dbls))(code))(arg);
|
||||
/* { dg-output "1.0 2.0\n" } */
|
||||
|
||||
closure_test_fn(arg);
|
||||
/* { dg-output "1.0 2.0\n" } */
|
||||
|
||||
return 0;
|
||||
}
|
||||
140
.pc/msvc-changes/testsuite/libffi.call/cls_pointer_stack.c
Normal file
140
.pc/msvc-changes/testsuite/libffi.call/cls_pointer_stack.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check pointer arguments across multiple hideous stack frames.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/7/2007 */
|
||||
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
static long dummyVar;
|
||||
|
||||
long dummy_func(
|
||||
long double a1, char b1,
|
||||
long double a2, char b2,
|
||||
long double a3, char b3,
|
||||
long double a4, char b4)
|
||||
{
|
||||
return a1 + b1 + a2 + b2 + a3 + b3 + a4 + b4;
|
||||
}
|
||||
|
||||
void* cls_pointer_fn2(void* a1, void* a2)
|
||||
{
|
||||
long double trample1 = (intptr_t)a1 + (intptr_t)a2;
|
||||
char trample2 = ((char*)&a1)[0] + ((char*)&a2)[0];
|
||||
long double trample3 = (intptr_t)trample1 + (intptr_t)a1;
|
||||
char trample4 = trample2 + ((char*)&a1)[1];
|
||||
long double trample5 = (intptr_t)trample3 + (intptr_t)a2;
|
||||
char trample6 = trample4 + ((char*)&a2)[1];
|
||||
long double trample7 = (intptr_t)trample5 + (intptr_t)trample1;
|
||||
char trample8 = trample6 + trample2;
|
||||
|
||||
dummyVar = dummy_func(trample1, trample2, trample3, trample4,
|
||||
trample5, trample6, trample7, trample8);
|
||||
|
||||
void* result = (void*)((intptr_t)a1 + (intptr_t)a2);
|
||||
|
||||
printf("0x%08x 0x%08x: 0x%08x\n",
|
||||
(unsigned int)(uintptr_t) a1,
|
||||
(unsigned int)(uintptr_t) a2,
|
||||
(unsigned int)(uintptr_t) result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void* cls_pointer_fn1(void* a1, void* a2)
|
||||
{
|
||||
long double trample1 = (intptr_t)a1 + (intptr_t)a2;
|
||||
char trample2 = ((char*)&a1)[0] + ((char*)&a2)[0];
|
||||
long double trample3 = (intptr_t)trample1 + (intptr_t)a1;
|
||||
char trample4 = trample2 + ((char*)&a1)[1];
|
||||
long double trample5 = (intptr_t)trample3 + (intptr_t)a2;
|
||||
char trample6 = trample4 + ((char*)&a2)[1];
|
||||
long double trample7 = (intptr_t)trample5 + (intptr_t)trample1;
|
||||
char trample8 = trample6 + trample2;
|
||||
|
||||
dummyVar = dummy_func(trample1, trample2, trample3, trample4,
|
||||
trample5, trample6, trample7, trample8);
|
||||
|
||||
void* result = (void*)((intptr_t)a1 + (intptr_t)a2);
|
||||
|
||||
printf("0x%08x 0x%08x: 0x%08x\n",
|
||||
(unsigned int)(intptr_t) a1,
|
||||
(unsigned int)(intptr_t) a2,
|
||||
(unsigned int)(intptr_t) result);
|
||||
|
||||
result = cls_pointer_fn2(result, a1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_pointer_gn(ffi_cif* cif __UNUSED__, void* resp,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
void* a1 = *(void**)(args[0]);
|
||||
void* a2 = *(void**)(args[1]);
|
||||
|
||||
long double trample1 = (intptr_t)a1 + (intptr_t)a2;
|
||||
char trample2 = ((char*)&a1)[0] + ((char*)&a2)[0];
|
||||
long double trample3 = (intptr_t)trample1 + (intptr_t)a1;
|
||||
char trample4 = trample2 + ((char*)&a1)[1];
|
||||
long double trample5 = (intptr_t)trample3 + (intptr_t)a2;
|
||||
char trample6 = trample4 + ((char*)&a2)[1];
|
||||
long double trample7 = (intptr_t)trample5 + (intptr_t)trample1;
|
||||
char trample8 = trample6 + trample2;
|
||||
|
||||
dummyVar = dummy_func(trample1, trample2, trample3, trample4,
|
||||
trample5, trample6, trample7, trample8);
|
||||
|
||||
*(void**)resp = cls_pointer_fn1(a1, a2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure* pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args[3];
|
||||
// ffi_type cls_pointer_type;
|
||||
ffi_type* arg_types[3];
|
||||
|
||||
/* cls_pointer_type.size = sizeof(void*);
|
||||
cls_pointer_type.alignment = 0;
|
||||
cls_pointer_type.type = FFI_TYPE_POINTER;
|
||||
cls_pointer_type.elements = NULL;*/
|
||||
|
||||
void* arg1 = (void*)0x01234567;
|
||||
void* arg2 = (void*)0x89abcdef;
|
||||
ffi_arg res = 0;
|
||||
|
||||
arg_types[0] = &ffi_type_pointer;
|
||||
arg_types[1] = &ffi_type_pointer;
|
||||
arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_pointer,
|
||||
arg_types) == FFI_OK);
|
||||
|
||||
args[0] = &arg1;
|
||||
args[1] = &arg2;
|
||||
args[2] = NULL;
|
||||
|
||||
printf("\n");
|
||||
ffi_call(&cif, FFI_FN(cls_pointer_fn1), &res, args);
|
||||
|
||||
printf("res: 0x%08x\n", (unsigned int) res);
|
||||
// { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
|
||||
// { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
|
||||
// { dg-output "\nres: 0x8bf258bd" }
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_pointer_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res = (ffi_arg)(uintptr_t)((void*(*)(void*, void*))(code))(arg1, arg2);
|
||||
|
||||
printf("res: 0x%08x\n", (unsigned int) res);
|
||||
// { dg-output "\n0x01234567 0x89abcdef: 0x8acf1356" }
|
||||
// { dg-output "\n0x8acf1356 0x01234567: 0x8bf258bd" }
|
||||
// { dg-output "\nres: 0x8bf258bd" }
|
||||
|
||||
exit(0);
|
||||
}
|
||||
26
.pc/msvc-changes/testsuite/libffi.call/err_bad_typedef.c
Normal file
26
.pc/msvc-changes/testsuite/libffi.call/err_bad_typedef.c
Normal file
@@ -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];
|
||||
|
||||
arg_types[0] = NULL;
|
||||
|
||||
ffi_type badType = ffi_type_void;
|
||||
|
||||
badType.size = 0;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &badType,
|
||||
arg_types) == FFI_BAD_TYPEDEF);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
50
.pc/msvc-changes/testsuite/libffi.call/fastthis1_win32.c
Normal file
50
.pc/msvc-changes/testsuite/libffi.call/fastthis1_win32.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check fastcall fct call on X86_WIN32 systems.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: From the original ffitest.c */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
static size_t __attribute__((fastcall)) my_fastcall_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, FFI_FASTCALL, 2,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
s = "a";
|
||||
v2 = 0.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 1);
|
||||
|
||||
s = "1234567";
|
||||
v2 = -1.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 6);
|
||||
|
||||
s = "1234567890123456789012345";
|
||||
v2 = 1.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 26);
|
||||
|
||||
printf("fastcall fct1 tests passed\n");
|
||||
exit(0);
|
||||
}
|
||||
50
.pc/msvc-changes/testsuite/libffi.call/fastthis2_win32.c
Normal file
50
.pc/msvc-changes/testsuite/libffi.call/fastthis2_win32.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check fastcall fct call on X86_WIN32 systems.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: From the original ffitest.c */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
static size_t __attribute__((fastcall)) my_fastcall_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, FFI_FASTCALL, 2,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
s = "a";
|
||||
v2 = 0.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 1);
|
||||
|
||||
s = "1234567";
|
||||
v2 = -1.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 6);
|
||||
|
||||
s = "1234567890123456789012345";
|
||||
v2 = 1.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 26);
|
||||
|
||||
printf("fastcall fct2 tests passed\n");
|
||||
exit(0);
|
||||
}
|
||||
56
.pc/msvc-changes/testsuite/libffi.call/fastthis3_win32.c
Normal file
56
.pc/msvc-changes/testsuite/libffi.call/fastthis3_win32.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check fastcall f call on X86_WIN32 systems.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: From the original ffitest.c */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
static size_t __attribute__((fastcall)) my_fastcall_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, FFI_FASTCALL, 3,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
s = "a";
|
||||
v1 = 1;
|
||||
v2 = 0.0;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 2);
|
||||
|
||||
s = "1234567";
|
||||
v2 = -1.0;
|
||||
v1 = -2;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 4);
|
||||
|
||||
s = "1234567890123456789012345";
|
||||
v2 = 1.0;
|
||||
v1 = 2;
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_f), &rint, values);
|
||||
CHECK(rint == 28);
|
||||
|
||||
printf("fastcall fct3 tests passed\n");
|
||||
exit(0);
|
||||
}
|
||||
153
.pc/msvc-changes/testsuite/libffi.call/ffitest.h
Normal file
153
.pc/msvc-changes/testsuite/libffi.call/ffitest.h
Normal file
@@ -0,0 +1,153 @@
|
||||
#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) !(x) ? abort() : 0
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
||||
#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 == (void *) MAP_FAILED)
|
||||
{
|
||||
perror ("virtual memory exhausted");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
#endif
|
||||
342
.pc/msvc-changes/testsuite/libffi.call/huge_struct.c
Normal file
342
.pc/msvc-changes/testsuite/libffi.call/huge_struct.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check large structure returns.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/18/2007
|
||||
*/
|
||||
|
||||
/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* } } */
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
/* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */
|
||||
/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct BigStruct{
|
||||
uint8_t a;
|
||||
int8_t b;
|
||||
uint16_t c;
|
||||
int16_t d;
|
||||
uint32_t e;
|
||||
int32_t f;
|
||||
uint64_t g;
|
||||
int64_t h;
|
||||
float i;
|
||||
double j;
|
||||
long double k;
|
||||
char* l;
|
||||
uint8_t m;
|
||||
int8_t n;
|
||||
uint16_t o;
|
||||
int16_t p;
|
||||
uint32_t q;
|
||||
int32_t r;
|
||||
uint64_t s;
|
||||
int64_t t;
|
||||
float u;
|
||||
double v;
|
||||
long double w;
|
||||
char* x;
|
||||
uint8_t y;
|
||||
int8_t z;
|
||||
uint16_t aa;
|
||||
int16_t bb;
|
||||
uint32_t cc;
|
||||
int32_t dd;
|
||||
uint64_t ee;
|
||||
int64_t ff;
|
||||
float gg;
|
||||
double hh;
|
||||
long double ii;
|
||||
char* jj;
|
||||
uint8_t kk;
|
||||
int8_t ll;
|
||||
uint16_t mm;
|
||||
int16_t nn;
|
||||
uint32_t oo;
|
||||
int32_t pp;
|
||||
uint64_t qq;
|
||||
int64_t rr;
|
||||
float ss;
|
||||
double tt;
|
||||
long double uu;
|
||||
char* vv;
|
||||
uint8_t ww;
|
||||
int8_t xx;
|
||||
} BigStruct;
|
||||
|
||||
BigStruct
|
||||
test_large_fn(
|
||||
uint8_t ui8_1,
|
||||
int8_t si8_1,
|
||||
uint16_t ui16_1,
|
||||
int16_t si16_1,
|
||||
uint32_t ui32_1,
|
||||
int32_t si32_1,
|
||||
uint64_t ui64_1,
|
||||
int64_t si64_1,
|
||||
float f_1,
|
||||
double d_1,
|
||||
long double ld_1,
|
||||
char* p_1,
|
||||
uint8_t ui8_2,
|
||||
int8_t si8_2,
|
||||
uint16_t ui16_2,
|
||||
int16_t si16_2,
|
||||
uint32_t ui32_2,
|
||||
int32_t si32_2,
|
||||
uint64_t ui64_2,
|
||||
int64_t si64_2,
|
||||
float f_2,
|
||||
double d_2,
|
||||
long double ld_2,
|
||||
char* p_2,
|
||||
uint8_t ui8_3,
|
||||
int8_t si8_3,
|
||||
uint16_t ui16_3,
|
||||
int16_t si16_3,
|
||||
uint32_t ui32_3,
|
||||
int32_t si32_3,
|
||||
uint64_t ui64_3,
|
||||
int64_t si64_3,
|
||||
float f_3,
|
||||
double d_3,
|
||||
long double ld_3,
|
||||
char* p_3,
|
||||
uint8_t ui8_4,
|
||||
int8_t si8_4,
|
||||
uint16_t ui16_4,
|
||||
int16_t si16_4,
|
||||
uint32_t ui32_4,
|
||||
int32_t si32_4,
|
||||
uint64_t ui64_4,
|
||||
int64_t si64_4,
|
||||
float f_4,
|
||||
double d_4,
|
||||
long double ld_4,
|
||||
char* p_4,
|
||||
uint8_t ui8_5,
|
||||
int8_t si8_5)
|
||||
{
|
||||
BigStruct retVal = {
|
||||
ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1, ui32_1 + 1, si32_1 + 1,
|
||||
ui64_1 + 1, si64_1 + 1, f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((intptr_t)p_1 + 1),
|
||||
ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2, ui32_2 + 2, si32_2 + 2,
|
||||
ui64_2 + 2, si64_2 + 2, f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((intptr_t)p_2 + 2),
|
||||
ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3, ui32_3 + 3, si32_3 + 3,
|
||||
ui64_3 + 3, si64_3 + 3, f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((intptr_t)p_3 + 3),
|
||||
ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4, ui32_4 + 4, si32_4 + 4,
|
||||
ui64_4 + 4, si64_4 + 4, f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((intptr_t)p_4 + 4),
|
||||
ui8_5 + 5, si8_5 + 5};
|
||||
|
||||
printf("%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 ": "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
|
||||
ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, (unsigned long)p_1,
|
||||
ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, (unsigned long)p_2,
|
||||
ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, (unsigned long)p_3,
|
||||
ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, (unsigned long)p_4, ui8_5, si8_5,
|
||||
retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
|
||||
retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
|
||||
retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
|
||||
retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
|
||||
retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
|
||||
retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
|
||||
retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
|
||||
retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_large_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
uint8_t ui8_1 = *(uint8_t*)args[0];
|
||||
int8_t si8_1 = *(int8_t*)args[1];
|
||||
uint16_t ui16_1 = *(uint16_t*)args[2];
|
||||
int16_t si16_1 = *(int16_t*)args[3];
|
||||
uint32_t ui32_1 = *(uint32_t*)args[4];
|
||||
int32_t si32_1 = *(int32_t*)args[5];
|
||||
uint64_t ui64_1 = *(uint64_t*)args[6];
|
||||
int64_t si64_1 = *(int64_t*)args[7];
|
||||
float f_1 = *(float*)args[8];
|
||||
double d_1 = *(double*)args[9];
|
||||
long double ld_1 = *(long double*)args[10];
|
||||
char* p_1 = *(char**)args[11];
|
||||
uint8_t ui8_2 = *(uint8_t*)args[12];
|
||||
int8_t si8_2 = *(int8_t*)args[13];
|
||||
uint16_t ui16_2 = *(uint16_t*)args[14];
|
||||
int16_t si16_2 = *(int16_t*)args[15];
|
||||
uint32_t ui32_2 = *(uint32_t*)args[16];
|
||||
int32_t si32_2 = *(int32_t*)args[17];
|
||||
uint64_t ui64_2 = *(uint64_t*)args[18];
|
||||
int64_t si64_2 = *(int64_t*)args[19];
|
||||
float f_2 = *(float*)args[20];
|
||||
double d_2 = *(double*)args[21];
|
||||
long double ld_2 = *(long double*)args[22];
|
||||
char* p_2 = *(char**)args[23];
|
||||
uint8_t ui8_3 = *(uint8_t*)args[24];
|
||||
int8_t si8_3 = *(int8_t*)args[25];
|
||||
uint16_t ui16_3 = *(uint16_t*)args[26];
|
||||
int16_t si16_3 = *(int16_t*)args[27];
|
||||
uint32_t ui32_3 = *(uint32_t*)args[28];
|
||||
int32_t si32_3 = *(int32_t*)args[29];
|
||||
uint64_t ui64_3 = *(uint64_t*)args[30];
|
||||
int64_t si64_3 = *(int64_t*)args[31];
|
||||
float f_3 = *(float*)args[32];
|
||||
double d_3 = *(double*)args[33];
|
||||
long double ld_3 = *(long double*)args[34];
|
||||
char* p_3 = *(char**)args[35];
|
||||
uint8_t ui8_4 = *(uint8_t*)args[36];
|
||||
int8_t si8_4 = *(int8_t*)args[37];
|
||||
uint16_t ui16_4 = *(uint16_t*)args[38];
|
||||
int16_t si16_4 = *(int16_t*)args[39];
|
||||
uint32_t ui32_4 = *(uint32_t*)args[40];
|
||||
int32_t si32_4 = *(int32_t*)args[41];
|
||||
uint64_t ui64_4 = *(uint64_t*)args[42];
|
||||
int64_t si64_4 = *(int64_t*)args[43];
|
||||
float f_4 = *(float*)args[44];
|
||||
double d_4 = *(double*)args[45];
|
||||
long double ld_4 = *(long double*)args[46];
|
||||
char* p_4 = *(char**)args[47];
|
||||
uint8_t ui8_5 = *(uint8_t*)args[48];
|
||||
int8_t si8_5 = *(int8_t*)args[49];
|
||||
|
||||
*(BigStruct*)resp = test_large_fn(
|
||||
ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
|
||||
ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
|
||||
ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
|
||||
ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4,
|
||||
ui8_5, si8_5);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc __UNUSED__, const char** argv __UNUSED__)
|
||||
{
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
|
||||
ffi_cif cif;
|
||||
ffi_type* argTypes[51];
|
||||
void* argValues[51];
|
||||
|
||||
ffi_type ret_struct_type;
|
||||
ffi_type* st_fields[51];
|
||||
BigStruct retVal;
|
||||
|
||||
memset (&retVal, 0, sizeof(retVal));
|
||||
|
||||
ret_struct_type.size = 0;
|
||||
ret_struct_type.alignment = 0;
|
||||
ret_struct_type.type = FFI_TYPE_STRUCT;
|
||||
ret_struct_type.elements = st_fields;
|
||||
|
||||
st_fields[0] = st_fields[12] = st_fields[24] = st_fields[36] = st_fields[48] = &ffi_type_uint8;
|
||||
st_fields[1] = st_fields[13] = st_fields[25] = st_fields[37] = st_fields[49] = &ffi_type_sint8;
|
||||
st_fields[2] = st_fields[14] = st_fields[26] = st_fields[38] = &ffi_type_uint16;
|
||||
st_fields[3] = st_fields[15] = st_fields[27] = st_fields[39] = &ffi_type_sint16;
|
||||
st_fields[4] = st_fields[16] = st_fields[28] = st_fields[40] = &ffi_type_uint32;
|
||||
st_fields[5] = st_fields[17] = st_fields[29] = st_fields[41] = &ffi_type_sint32;
|
||||
st_fields[6] = st_fields[18] = st_fields[30] = st_fields[42] = &ffi_type_uint64;
|
||||
st_fields[7] = st_fields[19] = st_fields[31] = st_fields[43] = &ffi_type_sint64;
|
||||
st_fields[8] = st_fields[20] = st_fields[32] = st_fields[44] = &ffi_type_float;
|
||||
st_fields[9] = st_fields[21] = st_fields[33] = st_fields[45] = &ffi_type_double;
|
||||
st_fields[10] = st_fields[22] = st_fields[34] = st_fields[46] = &ffi_type_longdouble;
|
||||
st_fields[11] = st_fields[23] = st_fields[35] = st_fields[47] = &ffi_type_pointer;
|
||||
|
||||
st_fields[50] = NULL;
|
||||
|
||||
uint8_t ui8 = 1;
|
||||
int8_t si8 = 2;
|
||||
uint16_t ui16 = 3;
|
||||
int16_t si16 = 4;
|
||||
uint32_t ui32 = 5;
|
||||
int32_t si32 = 6;
|
||||
uint64_t ui64 = 7;
|
||||
int64_t si64 = 8;
|
||||
float f = 9;
|
||||
double d = 10;
|
||||
long double ld = 11;
|
||||
char* p = (char*)0x12345678;
|
||||
|
||||
argTypes[0] = argTypes[12] = argTypes[24] = argTypes[36] = argTypes[48] = &ffi_type_uint8;
|
||||
argValues[0] = argValues[12] = argValues[24] = argValues[36] = argValues[48] = &ui8;
|
||||
argTypes[1] = argTypes[13] = argTypes[25] = argTypes[37] = argTypes[49] = &ffi_type_sint8;
|
||||
argValues[1] = argValues[13] = argValues[25] = argValues[37] = argValues[49] = &si8;
|
||||
argTypes[2] = argTypes[14] = argTypes[26] = argTypes[38] = &ffi_type_uint16;
|
||||
argValues[2] = argValues[14] = argValues[26] = argValues[38] = &ui16;
|
||||
argTypes[3] = argTypes[15] = argTypes[27] = argTypes[39] = &ffi_type_sint16;
|
||||
argValues[3] = argValues[15] = argValues[27] = argValues[39] = &si16;
|
||||
argTypes[4] = argTypes[16] = argTypes[28] = argTypes[40] = &ffi_type_uint32;
|
||||
argValues[4] = argValues[16] = argValues[28] = argValues[40] = &ui32;
|
||||
argTypes[5] = argTypes[17] = argTypes[29] = argTypes[41] = &ffi_type_sint32;
|
||||
argValues[5] = argValues[17] = argValues[29] = argValues[41] = &si32;
|
||||
argTypes[6] = argTypes[18] = argTypes[30] = argTypes[42] = &ffi_type_uint64;
|
||||
argValues[6] = argValues[18] = argValues[30] = argValues[42] = &ui64;
|
||||
argTypes[7] = argTypes[19] = argTypes[31] = argTypes[43] = &ffi_type_sint64;
|
||||
argValues[7] = argValues[19] = argValues[31] = argValues[43] = &si64;
|
||||
argTypes[8] = argTypes[20] = argTypes[32] = argTypes[44] = &ffi_type_float;
|
||||
argValues[8] = argValues[20] = argValues[32] = argValues[44] = &f;
|
||||
argTypes[9] = argTypes[21] = argTypes[33] = argTypes[45] = &ffi_type_double;
|
||||
argValues[9] = argValues[21] = argValues[33] = argValues[45] = &d;
|
||||
argTypes[10] = argTypes[22] = argTypes[34] = argTypes[46] = &ffi_type_longdouble;
|
||||
argValues[10] = argValues[22] = argValues[34] = argValues[46] = &ld;
|
||||
argTypes[11] = argTypes[23] = argTypes[35] = argTypes[47] = &ffi_type_pointer;
|
||||
argValues[11] = argValues[23] = argValues[35] = argValues[47] = &p;
|
||||
|
||||
argTypes[50] = NULL;
|
||||
argValues[50] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 50, &ret_struct_type, argTypes) == FFI_OK);
|
||||
|
||||
ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues);
|
||||
// { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
|
||||
printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
|
||||
retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
|
||||
retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
|
||||
retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
|
||||
retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
|
||||
retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
|
||||
retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
|
||||
retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
|
||||
retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
|
||||
// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_large_fn, NULL, code) == FFI_OK);
|
||||
|
||||
retVal = ((BigStruct(*)(
|
||||
uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
|
||||
uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
|
||||
uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
|
||||
uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
|
||||
uint8_t, int8_t))(code))(
|
||||
ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
|
||||
ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
|
||||
ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
|
||||
ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
|
||||
ui8, si8);
|
||||
// { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
|
||||
printf("res: %" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx "
|
||||
"%" PRIu8 " %" PRId8 " %hu %hd %u %d %" PRIu64 " %" PRId64 " %.0f %.0f %.0Lf %#lx %" PRIu8 " %" PRId8 "\n",
|
||||
retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
|
||||
retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, (unsigned long)retVal.l,
|
||||
retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
|
||||
retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, (unsigned long)retVal.x,
|
||||
retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
|
||||
retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, (unsigned long)retVal.jj,
|
||||
retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
|
||||
retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, (unsigned long)retVal.vv, retVal.ww, retVal.xx);
|
||||
// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
|
||||
|
||||
return 0;
|
||||
}
|
||||
152
.pc/msvc-changes/testsuite/libffi.call/nested_struct.c
Normal file
152
.pc/msvc-changes/testsuite/libffi.call/nested_struct.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_16byte1 {
|
||||
double a;
|
||||
float b;
|
||||
int c;
|
||||
} cls_struct_16byte1;
|
||||
|
||||
typedef struct cls_struct_16byte2 {
|
||||
int ii;
|
||||
double dd;
|
||||
float ff;
|
||||
} cls_struct_16byte2;
|
||||
|
||||
typedef struct cls_struct_combined {
|
||||
cls_struct_16byte1 d;
|
||||
cls_struct_16byte2 e;
|
||||
} cls_struct_combined;
|
||||
|
||||
cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
|
||||
struct cls_struct_16byte2 b1,
|
||||
struct cls_struct_combined b2)
|
||||
{
|
||||
struct cls_struct_combined result;
|
||||
|
||||
result.d.a = b0.a + b1.dd + b2.d.a;
|
||||
result.d.b = b0.b + b1.ff + b2.d.b;
|
||||
result.d.c = b0.c + b1.ii + b2.d.c;
|
||||
result.e.ii = b0.c + b1.ii + b2.e.ii;
|
||||
result.e.dd = b0.a + b1.dd + b2.e.dd;
|
||||
result.e.ff = b0.b + b1.ff + b2.e.ff;
|
||||
|
||||
printf("%g %g %d %d %g %g %g %g %d %d %g %g: %g %g %d %d %g %g\n",
|
||||
b0.a, b0.b, b0.c,
|
||||
b1.ii, b1.dd, b1.ff,
|
||||
b2.d.a, b2.d.b, b2.d.c,
|
||||
b2.e.ii, b2.e.dd, b2.e.ff,
|
||||
result.d.a, result.d.b, result.d.c,
|
||||
result.e.ii, result.e.dd, result.e.ff);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_16byte1 b0;
|
||||
struct cls_struct_16byte2 b1;
|
||||
struct cls_struct_combined b2;
|
||||
|
||||
b0 = *(struct cls_struct_16byte1*)(args[0]);
|
||||
b1 = *(struct cls_struct_16byte2*)(args[1]);
|
||||
b2 = *(struct cls_struct_combined*)(args[2]);
|
||||
|
||||
|
||||
*(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type* cls_struct_fields1[5];
|
||||
ffi_type* cls_struct_fields2[5];
|
||||
ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
cls_struct_type2.size = 0;
|
||||
cls_struct_type2.alignment = 0;
|
||||
cls_struct_type2.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type2.elements = cls_struct_fields2;
|
||||
|
||||
struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6};
|
||||
struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0};
|
||||
struct cls_struct_combined g_dbl = {{4.0, 5.0, 6},
|
||||
{3, 1.0, 8.0}};
|
||||
struct cls_struct_combined res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_float;
|
||||
cls_struct_fields[2] = &ffi_type_sint;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &ffi_type_sint;
|
||||
cls_struct_fields1[1] = &ffi_type_double;
|
||||
cls_struct_fields1[2] = &ffi_type_float;
|
||||
cls_struct_fields1[3] = NULL;
|
||||
|
||||
cls_struct_fields2[0] = &cls_struct_type;
|
||||
cls_struct_fields2[1] = &cls_struct_type1;
|
||||
cls_struct_fields2[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = &cls_struct_type2;
|
||||
dbl_arg_types[3] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type2,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
|
||||
CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
|
||||
CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
|
||||
CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
|
||||
CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
|
||||
CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
|
||||
CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
|
||||
cls_struct_16byte2,
|
||||
cls_struct_combined))
|
||||
(code))(e_dbl, f_dbl, g_dbl);
|
||||
/* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8: 15 10 13 10 12 13" } */
|
||||
CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
|
||||
CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
|
||||
CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
|
||||
CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
|
||||
CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
|
||||
CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
|
||||
exit(0);
|
||||
}
|
||||
161
.pc/msvc-changes/testsuite/libffi.call/nested_struct1.c
Normal file
161
.pc/msvc-changes/testsuite/libffi.call/nested_struct1.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030828 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_16byte1 {
|
||||
double a;
|
||||
float b;
|
||||
int c;
|
||||
} cls_struct_16byte1;
|
||||
|
||||
typedef struct cls_struct_16byte2 {
|
||||
int ii;
|
||||
double dd;
|
||||
float ff;
|
||||
} cls_struct_16byte2;
|
||||
|
||||
typedef struct cls_struct_combined {
|
||||
cls_struct_16byte1 d;
|
||||
cls_struct_16byte2 e;
|
||||
} cls_struct_combined;
|
||||
|
||||
cls_struct_combined cls_struct_combined_fn(struct cls_struct_16byte1 b0,
|
||||
struct cls_struct_16byte2 b1,
|
||||
struct cls_struct_combined b2,
|
||||
struct cls_struct_16byte1 b3)
|
||||
{
|
||||
struct cls_struct_combined result;
|
||||
|
||||
result.d.a = b0.a + b1.dd + b2.d.a;
|
||||
result.d.b = b0.b + b1.ff + b2.d.b;
|
||||
result.d.c = b0.c + b1.ii + b2.d.c;
|
||||
result.e.ii = b0.c + b1.ii + b2.e.ii;
|
||||
result.e.dd = b0.a + b1.dd + b2.e.dd;
|
||||
result.e.ff = b0.b + b1.ff + b2.e.ff;
|
||||
|
||||
printf("%g %g %d %d %g %g %g %g %d %d %g %g %g %g %d: %g %g %d %d %g %g\n",
|
||||
b0.a, b0.b, b0.c,
|
||||
b1.ii, b1.dd, b1.ff,
|
||||
b2.d.a, b2.d.b, b2.d.c,
|
||||
b2.e.ii, b2.e.dd, b2.e.ff,
|
||||
b3.a, b3.b, b3.c,
|
||||
result.d.a, result.d.b, result.d.c,
|
||||
result.e.ii, result.e.dd, result.e.ff);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_16byte1 b0;
|
||||
struct cls_struct_16byte2 b1;
|
||||
struct cls_struct_combined b2;
|
||||
struct cls_struct_16byte1 b3;
|
||||
|
||||
b0 = *(struct cls_struct_16byte1*)(args[0]);
|
||||
b1 = *(struct cls_struct_16byte2*)(args[1]);
|
||||
b2 = *(struct cls_struct_combined*)(args[2]);
|
||||
b3 = *(struct cls_struct_16byte1*)(args[3]);
|
||||
|
||||
|
||||
*(cls_struct_combined*)resp = cls_struct_combined_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[5];
|
||||
ffi_type* cls_struct_fields1[5];
|
||||
ffi_type* cls_struct_fields2[5];
|
||||
ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
cls_struct_type2.size = 0;
|
||||
cls_struct_type2.alignment = 0;
|
||||
cls_struct_type2.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type2.elements = cls_struct_fields2;
|
||||
|
||||
struct cls_struct_16byte1 e_dbl = { 9.0, 2.0, 6};
|
||||
struct cls_struct_16byte2 f_dbl = { 1, 2.0, 3.0};
|
||||
struct cls_struct_combined g_dbl = {{4.0, 5.0, 6},
|
||||
{3, 1.0, 8.0}};
|
||||
struct cls_struct_16byte1 h_dbl = { 3.0, 2.0, 4};
|
||||
struct cls_struct_combined res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_float;
|
||||
cls_struct_fields[2] = &ffi_type_sint;
|
||||
cls_struct_fields[3] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &ffi_type_sint;
|
||||
cls_struct_fields1[1] = &ffi_type_double;
|
||||
cls_struct_fields1[2] = &ffi_type_float;
|
||||
cls_struct_fields1[3] = NULL;
|
||||
|
||||
cls_struct_fields2[0] = &cls_struct_type;
|
||||
cls_struct_fields2[1] = &cls_struct_type1;
|
||||
cls_struct_fields2[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = &cls_struct_type2;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type2,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_combined_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
|
||||
CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
|
||||
CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
|
||||
CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
|
||||
CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
|
||||
CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
|
||||
CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((cls_struct_combined(*)(cls_struct_16byte1,
|
||||
cls_struct_16byte2,
|
||||
cls_struct_combined,
|
||||
cls_struct_16byte1))
|
||||
(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n9 2 6 1 2 3 4 5 6 3 1 8 3 2 4: 15 10 13 10 12 13" } */
|
||||
CHECK( res_dbl.d.a == (e_dbl.a + f_dbl.dd + g_dbl.d.a));
|
||||
CHECK( res_dbl.d.b == (e_dbl.b + f_dbl.ff + g_dbl.d.b));
|
||||
CHECK( res_dbl.d.c == (e_dbl.c + f_dbl.ii + g_dbl.d.c));
|
||||
CHECK( res_dbl.e.ii == (e_dbl.c + f_dbl.ii + g_dbl.e.ii));
|
||||
CHECK( res_dbl.e.dd == (e_dbl.a + f_dbl.dd + g_dbl.e.dd));
|
||||
CHECK( res_dbl.e.ff == (e_dbl.b + f_dbl.ff + g_dbl.e.ff));
|
||||
// CHECK( 1 == 0);
|
||||
exit(0);
|
||||
}
|
||||
133
.pc/msvc-changes/testsuite/libffi.call/nested_struct10.c
Normal file
133
.pc/msvc-changes/testsuite/libffi.call/nested_struct10.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
unsigned long long a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
unsigned char y;
|
||||
struct A x;
|
||||
unsigned int z;
|
||||
} B;
|
||||
|
||||
typedef struct C {
|
||||
unsigned long long d;
|
||||
unsigned char e;
|
||||
} C;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3, struct C b4)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a + b3.z + b4.d;
|
||||
result.x.b = b2.b + b3.x.b + b3.y + b4.e;
|
||||
result.y = b2.b + b3.x.b + b4.e;
|
||||
|
||||
printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
|
||||
(int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
struct C b2;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
b2 = *(struct C*)(args[2]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[4];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[4];
|
||||
ffi_type* cls_struct_fields2[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
|
||||
ffi_type* dbl_arg_types[4];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
cls_struct_type2.size = 0;
|
||||
cls_struct_type2.alignment = 0;
|
||||
cls_struct_type2.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type2.elements = cls_struct_fields2;
|
||||
|
||||
struct A e_dbl = { 1LL, 7};
|
||||
struct B f_dbl = { 99, {12LL , 127}, 255};
|
||||
struct C g_dbl = { 2LL, 9};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uint64;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &ffi_type_uchar;
|
||||
cls_struct_fields1[1] = &cls_struct_type;
|
||||
cls_struct_fields1[2] = &ffi_type_uint;
|
||||
cls_struct_fields1[3] = NULL;
|
||||
|
||||
cls_struct_fields2[0] = &ffi_type_uint64;
|
||||
cls_struct_fields2[1] = &ffi_type_uchar;
|
||||
cls_struct_fields2[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = &cls_struct_type2;
|
||||
dbl_arg_types[3] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99 255 2 9: 270 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99 255 2 9: 270 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + f_dbl.z + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
110
.pc/msvc-changes/testsuite/libffi.call/nested_struct2.c
Normal file
110
.pc/msvc-changes/testsuite/libffi.call/nested_struct2.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030911 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
unsigned long a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
B B_fn(struct A b0, struct B b1)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b0.a + b1.x.a;
|
||||
result.x.b = b0.b + b1.x.b + b1.y;
|
||||
result.y = b0.b + b1.x.b;
|
||||
|
||||
printf("%lu %d %lu %d %d: %lu %d %d\n", b0.a, b0.b, b1.x.a, b1.x.b, b1.y,
|
||||
result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
struct A e_dbl = { 1, 7};
|
||||
struct B f_dbl = {{12 , 127}, 99};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_ulong;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
111
.pc/msvc-changes/testsuite/libffi.call/nested_struct3.c
Normal file
111
.pc/msvc-changes/testsuite/libffi.call/nested_struct3.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20030911 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
unsigned long long a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
B B_fn(struct A b0, struct B b1)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b0.a + b1.x.a;
|
||||
result.x.b = b0.b + b1.x.b + b1.y;
|
||||
result.y = b0.b + b1.x.b;
|
||||
|
||||
printf("%d %d %d %d %d: %d %d %d\n", (int)b0.a, b0.b,
|
||||
(int)b1.x.a, b1.x.b, b1.y,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
struct A e_dbl = { 1LL, 7};
|
||||
struct B f_dbl = {{12LL , 127}, 99};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uint64;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
exit(0);
|
||||
}
|
||||
111
.pc/msvc-changes/testsuite/libffi.call/nested_struct4.c
Normal file
111
.pc/msvc-changes/testsuite/libffi.call/nested_struct4.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: PR 25630.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
double a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a;
|
||||
result.x.b = b2.b + b3.x.b + b3.y;
|
||||
result.y = b2.b + b3.x.b;
|
||||
|
||||
printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
|
||||
(int)b3.x.a, b3.x.b, b3.y,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
struct A e_dbl = { 1.0, 7};
|
||||
struct B f_dbl = {{12.0 , 127}, 99};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
112
.pc/msvc-changes/testsuite/libffi.call/nested_struct5.c
Normal file
112
.pc/msvc-changes/testsuite/libffi.call/nested_struct5.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
long double a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a;
|
||||
result.x.b = b2.b + b3.x.b + b3.y;
|
||||
result.y = b2.b + b3.x.b;
|
||||
|
||||
printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
|
||||
(int)b3.x.a, b3.x.b, b3.y,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
struct A e_dbl = { 1.0, 7};
|
||||
struct B f_dbl = {{12.0 , 127}, 99};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_longdouble;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
131
.pc/msvc-changes/testsuite/libffi.call/nested_struct6.c
Normal file
131
.pc/msvc-changes/testsuite/libffi.call/nested_struct6.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: PR 25630.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
double a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
typedef struct C {
|
||||
long d;
|
||||
unsigned char e;
|
||||
} C;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3, struct C b4)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a + b4.d;
|
||||
result.x.b = b2.b + b3.x.b + b3.y + b4.e;
|
||||
result.y = b2.b + b3.x.b + b4.e;
|
||||
|
||||
printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
|
||||
(int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
struct C b2;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
b2 = *(struct C*)(args[2]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[4];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type* cls_struct_fields2[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
|
||||
ffi_type* dbl_arg_types[4];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
cls_struct_type2.size = 0;
|
||||
cls_struct_type2.alignment = 0;
|
||||
cls_struct_type2.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type2.elements = cls_struct_fields2;
|
||||
|
||||
struct A e_dbl = { 1.0, 7};
|
||||
struct B f_dbl = {{12.0 , 127}, 99};
|
||||
struct C g_dbl = { 2, 9};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
cls_struct_fields2[0] = &ffi_type_slong;
|
||||
cls_struct_fields2[1] = &ffi_type_uchar;
|
||||
cls_struct_fields2[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = &cls_struct_type2;
|
||||
dbl_arg_types[3] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
111
.pc/msvc-changes/testsuite/libffi.call/nested_struct7.c
Normal file
111
.pc/msvc-changes/testsuite/libffi.call/nested_struct7.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
unsigned long long a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a;
|
||||
result.x.b = b2.b + b3.x.b + b3.y;
|
||||
result.y = b2.b + b3.x.b;
|
||||
|
||||
printf("%d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
|
||||
(int)b3.x.a, b3.x.b, b3.y,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[3];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1;
|
||||
ffi_type* dbl_arg_types[3];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
struct A e_dbl = { 1LL, 7};
|
||||
struct B f_dbl = {{12.0 , 127}, 99};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uint64;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B))(code))(e_dbl, f_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99: 13 233 134" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
131
.pc/msvc-changes/testsuite/libffi.call/nested_struct8.c
Normal file
131
.pc/msvc-changes/testsuite/libffi.call/nested_struct8.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
unsigned long long a;
|
||||
unsigned char b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
typedef struct C {
|
||||
unsigned long long d;
|
||||
unsigned char e;
|
||||
} C;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3, struct C b4)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a + b4.d;
|
||||
result.x.b = b2.b + b3.x.b + b3.y + b4.e;
|
||||
result.y = b2.b + b3.x.b + b4.e;
|
||||
|
||||
printf("%d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b,
|
||||
(int)b3.x.a, b3.x.b, b3.y, (int)b4.d, b4.e,
|
||||
(int)result.x.a, result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
struct C b2;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
b2 = *(struct C*)(args[2]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[4];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type* cls_struct_fields2[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
|
||||
ffi_type* dbl_arg_types[4];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
cls_struct_type2.size = 0;
|
||||
cls_struct_type2.alignment = 0;
|
||||
cls_struct_type2.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type2.elements = cls_struct_fields2;
|
||||
|
||||
struct A e_dbl = { 1LL, 7};
|
||||
struct B f_dbl = {{12LL , 127}, 99};
|
||||
struct C g_dbl = { 2LL, 9};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uint64;
|
||||
cls_struct_fields[1] = &ffi_type_uchar;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
cls_struct_fields2[0] = &ffi_type_uint64;
|
||||
cls_struct_fields2[1] = &ffi_type_uchar;
|
||||
cls_struct_fields2[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = &cls_struct_type2;
|
||||
dbl_arg_types[3] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
131
.pc/msvc-changes/testsuite/libffi.call/nested_struct9.c
Normal file
131
.pc/msvc-changes/testsuite/libffi.call/nested_struct9.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure passing with different structure size.
|
||||
Contains structs as parameter of the struct itself.
|
||||
Sample taken from Alan Modras patch to src/prep_cif.c.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: <andreast@gcc.gnu.org> 20051010 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct A {
|
||||
unsigned char a;
|
||||
unsigned long long b;
|
||||
} A;
|
||||
|
||||
typedef struct B {
|
||||
struct A x;
|
||||
unsigned char y;
|
||||
} B;
|
||||
|
||||
typedef struct C {
|
||||
unsigned long d;
|
||||
unsigned char e;
|
||||
} C;
|
||||
|
||||
static B B_fn(struct A b2, struct B b3, struct C b4)
|
||||
{
|
||||
struct B result;
|
||||
|
||||
result.x.a = b2.a + b3.x.a + b4.d;
|
||||
result.x.b = b2.b + b3.x.b + b3.y + b4.e;
|
||||
result.y = b2.b + b3.x.b + b4.e;
|
||||
|
||||
printf("%d %d %d %d %d %d %d: %d %d %d\n", b2.a, (int)b2.b,
|
||||
b3.x.a, (int)b3.x.b, b3.y, (int)b4.d, b4.e,
|
||||
result.x.a, (int)result.x.b, result.y);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
B_gn(ffi_cif* cif __UNUSED__, void* resp, void** args,
|
||||
void* userdata __UNUSED__)
|
||||
{
|
||||
struct A b0;
|
||||
struct B b1;
|
||||
struct C b2;
|
||||
|
||||
b0 = *(struct A*)(args[0]);
|
||||
b1 = *(struct B*)(args[1]);
|
||||
b2 = *(struct C*)(args[2]);
|
||||
|
||||
*(B*)resp = B_fn(b0, b1, b2);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[4];
|
||||
ffi_type* cls_struct_fields[3];
|
||||
ffi_type* cls_struct_fields1[3];
|
||||
ffi_type* cls_struct_fields2[3];
|
||||
ffi_type cls_struct_type, cls_struct_type1, cls_struct_type2;
|
||||
ffi_type* dbl_arg_types[4];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
cls_struct_type1.size = 0;
|
||||
cls_struct_type1.alignment = 0;
|
||||
cls_struct_type1.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type1.elements = cls_struct_fields1;
|
||||
|
||||
cls_struct_type2.size = 0;
|
||||
cls_struct_type2.alignment = 0;
|
||||
cls_struct_type2.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type2.elements = cls_struct_fields2;
|
||||
|
||||
struct A e_dbl = { 1, 7LL};
|
||||
struct B f_dbl = {{12.0 , 127}, 99};
|
||||
struct C g_dbl = { 2, 9};
|
||||
|
||||
struct B res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_uchar;
|
||||
cls_struct_fields[1] = &ffi_type_uint64;
|
||||
cls_struct_fields[2] = NULL;
|
||||
|
||||
cls_struct_fields1[0] = &cls_struct_type;
|
||||
cls_struct_fields1[1] = &ffi_type_uchar;
|
||||
cls_struct_fields1[2] = NULL;
|
||||
|
||||
cls_struct_fields2[0] = &ffi_type_ulong;
|
||||
cls_struct_fields2[1] = &ffi_type_uchar;
|
||||
cls_struct_fields2[2] = NULL;
|
||||
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type1;
|
||||
dbl_arg_types[2] = &cls_struct_type2;
|
||||
dbl_arg_types[3] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &cls_struct_type1,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(B_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "1 7 12 127 99 2 9: 15 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, B_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((B(*)(A, B, C))(code))(e_dbl, f_dbl, g_dbl);
|
||||
/* { dg-output "\n1 7 12 127 99 2 9: 15 242 143" } */
|
||||
CHECK( res_dbl.x.a == (e_dbl.a + f_dbl.x.a + g_dbl.d));
|
||||
CHECK( res_dbl.x.b == (e_dbl.b + f_dbl.x.b + f_dbl.y + g_dbl.e));
|
||||
CHECK( res_dbl.y == (e_dbl.b + f_dbl.x.b + g_dbl.e));
|
||||
|
||||
exit(0);
|
||||
}
|
||||
145
.pc/msvc-changes/testsuite/libffi.call/stret_large.c
Normal file
145
.pc/msvc-changes/testsuite/libffi.call/stret_large.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure returning with different structure size.
|
||||
Depending on the ABI. Check bigger struct which overlaps
|
||||
the gp and fp register count on Darwin/AIX/ppc64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/21/2007 */
|
||||
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
// 13 FPRs: 104 bytes
|
||||
// 14 FPRs: 112 bytes
|
||||
|
||||
typedef struct struct_108byte {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
double g;
|
||||
double h;
|
||||
double i;
|
||||
double j;
|
||||
double k;
|
||||
double l;
|
||||
double m;
|
||||
int n;
|
||||
} struct_108byte;
|
||||
|
||||
struct_108byte cls_struct_108byte_fn(
|
||||
struct_108byte b0,
|
||||
struct_108byte b1,
|
||||
struct_108byte b2,
|
||||
struct_108byte b3)
|
||||
{
|
||||
struct_108byte result;
|
||||
|
||||
result.a = b0.a + b1.a + b2.a + b3.a;
|
||||
result.b = b0.b + b1.b + b2.b + b3.b;
|
||||
result.c = b0.c + b1.c + b2.c + b3.c;
|
||||
result.d = b0.d + b1.d + b2.d + b3.d;
|
||||
result.e = b0.e + b1.e + b2.e + b3.e;
|
||||
result.f = b0.f + b1.f + b2.f + b3.f;
|
||||
result.g = b0.g + b1.g + b2.g + b3.g;
|
||||
result.h = b0.h + b1.h + b2.h + b3.h;
|
||||
result.i = b0.i + b1.i + b2.i + b3.i;
|
||||
result.j = b0.j + b1.j + b2.j + b3.j;
|
||||
result.k = b0.k + b1.k + b2.k + b3.k;
|
||||
result.l = b0.l + b1.l + b2.l + b3.l;
|
||||
result.m = b0.m + b1.m + b2.m + b3.m;
|
||||
result.n = b0.n + b1.n + b2.n + b3.n;
|
||||
|
||||
printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
|
||||
result.d, result.e, result.f, result.g, result.h, result.i,
|
||||
result.j, result.k, result.l, result.m, result.n);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_108byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct_108byte b0, b1, b2, b3;
|
||||
|
||||
b0 = *(struct_108byte*)(args[0]);
|
||||
b1 = *(struct_108byte*)(args[1]);
|
||||
b2 = *(struct_108byte*)(args[2]);
|
||||
b3 = *(struct_108byte*)(args[3]);
|
||||
|
||||
*(struct_108byte*)resp = cls_struct_108byte_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[15];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct_108byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 7 };
|
||||
struct_108byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 4 };
|
||||
struct_108byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 3 };
|
||||
struct_108byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 2 };
|
||||
struct_108byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_double;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = &ffi_type_double;
|
||||
cls_struct_fields[5] = &ffi_type_double;
|
||||
cls_struct_fields[6] = &ffi_type_double;
|
||||
cls_struct_fields[7] = &ffi_type_double;
|
||||
cls_struct_fields[8] = &ffi_type_double;
|
||||
cls_struct_fields[9] = &ffi_type_double;
|
||||
cls_struct_fields[10] = &ffi_type_double;
|
||||
cls_struct_fields[11] = &ffi_type_double;
|
||||
cls_struct_fields[12] = &ffi_type_double;
|
||||
cls_struct_fields[13] = &ffi_type_sint32;
|
||||
cls_struct_fields[14] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = &cls_struct_type;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_108byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
|
||||
res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_108byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((struct_108byte(*)(struct_108byte, struct_108byte,
|
||||
struct_108byte, struct_108byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
|
||||
res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 16" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
148
.pc/msvc-changes/testsuite/libffi.call/stret_large2.c
Normal file
148
.pc/msvc-changes/testsuite/libffi.call/stret_large2.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure returning with different structure size.
|
||||
Depending on the ABI. Check bigger struct which overlaps
|
||||
the gp and fp register count on Darwin/AIX/ppc64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/21/2007 */
|
||||
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
// 13 FPRs: 104 bytes
|
||||
// 14 FPRs: 112 bytes
|
||||
|
||||
typedef struct struct_116byte {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
double g;
|
||||
double h;
|
||||
double i;
|
||||
double j;
|
||||
double k;
|
||||
double l;
|
||||
double m;
|
||||
double n;
|
||||
int o;
|
||||
} struct_116byte;
|
||||
|
||||
struct_116byte cls_struct_116byte_fn(
|
||||
struct_116byte b0,
|
||||
struct_116byte b1,
|
||||
struct_116byte b2,
|
||||
struct_116byte b3)
|
||||
{
|
||||
struct_116byte result;
|
||||
|
||||
result.a = b0.a + b1.a + b2.a + b3.a;
|
||||
result.b = b0.b + b1.b + b2.b + b3.b;
|
||||
result.c = b0.c + b1.c + b2.c + b3.c;
|
||||
result.d = b0.d + b1.d + b2.d + b3.d;
|
||||
result.e = b0.e + b1.e + b2.e + b3.e;
|
||||
result.f = b0.f + b1.f + b2.f + b3.f;
|
||||
result.g = b0.g + b1.g + b2.g + b3.g;
|
||||
result.h = b0.h + b1.h + b2.h + b3.h;
|
||||
result.i = b0.i + b1.i + b2.i + b3.i;
|
||||
result.j = b0.j + b1.j + b2.j + b3.j;
|
||||
result.k = b0.k + b1.k + b2.k + b3.k;
|
||||
result.l = b0.l + b1.l + b2.l + b3.l;
|
||||
result.m = b0.m + b1.m + b2.m + b3.m;
|
||||
result.n = b0.n + b1.n + b2.n + b3.n;
|
||||
result.o = b0.o + b1.o + b2.o + b3.o;
|
||||
|
||||
printf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", result.a, result.b, result.c,
|
||||
result.d, result.e, result.f, result.g, result.h, result.i,
|
||||
result.j, result.k, result.l, result.m, result.n, result.o);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_116byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct_116byte b0, b1, b2, b3;
|
||||
|
||||
b0 = *(struct_116byte*)(args[0]);
|
||||
b1 = *(struct_116byte*)(args[1]);
|
||||
b2 = *(struct_116byte*)(args[2]);
|
||||
b3 = *(struct_116byte*)(args[3]);
|
||||
|
||||
*(struct_116byte*)resp = cls_struct_116byte_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[16];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct_116byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 7 };
|
||||
struct_116byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0, 5.0, 7.0, 9.0, 1.0, 6.0, 4 };
|
||||
struct_116byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 8.0, 6.0, 1.0, 4.0, 0.0, 7.0, 3 };
|
||||
struct_116byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 9.0, 2.0, 6.0, 5.0, 3.0, 8.0, 2 };
|
||||
struct_116byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_double;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = &ffi_type_double;
|
||||
cls_struct_fields[5] = &ffi_type_double;
|
||||
cls_struct_fields[6] = &ffi_type_double;
|
||||
cls_struct_fields[7] = &ffi_type_double;
|
||||
cls_struct_fields[8] = &ffi_type_double;
|
||||
cls_struct_fields[9] = &ffi_type_double;
|
||||
cls_struct_fields[10] = &ffi_type_double;
|
||||
cls_struct_fields[11] = &ffi_type_double;
|
||||
cls_struct_fields[12] = &ffi_type_double;
|
||||
cls_struct_fields[13] = &ffi_type_double;
|
||||
cls_struct_fields[14] = &ffi_type_sint32;
|
||||
cls_struct_fields[15] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = &cls_struct_type;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_116byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
|
||||
res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_116byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((struct_116byte(*)(struct_116byte, struct_116byte,
|
||||
struct_116byte, struct_116byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %g %g %g %g %g %g %d\n", res_dbl.a, res_dbl.b,
|
||||
res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i,
|
||||
res_dbl.j, res_dbl.k, res_dbl.l, res_dbl.m, res_dbl.n, res_dbl.o);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 22 15 17 25 6 26 16" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
124
.pc/msvc-changes/testsuite/libffi.call/stret_medium.c
Normal file
124
.pc/msvc-changes/testsuite/libffi.call/stret_medium.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure returning with different structure size.
|
||||
Depending on the ABI. Check bigger struct which overlaps
|
||||
the gp and fp register count on Darwin/AIX/ppc64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/21/2007 */
|
||||
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct struct_72byte {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
double g;
|
||||
double h;
|
||||
double i;
|
||||
} struct_72byte;
|
||||
|
||||
struct_72byte cls_struct_72byte_fn(
|
||||
struct_72byte b0,
|
||||
struct_72byte b1,
|
||||
struct_72byte b2,
|
||||
struct_72byte b3)
|
||||
{
|
||||
struct_72byte result;
|
||||
|
||||
result.a = b0.a + b1.a + b2.a + b3.a;
|
||||
result.b = b0.b + b1.b + b2.b + b3.b;
|
||||
result.c = b0.c + b1.c + b2.c + b3.c;
|
||||
result.d = b0.d + b1.d + b2.d + b3.d;
|
||||
result.e = b0.e + b1.e + b2.e + b3.e;
|
||||
result.f = b0.f + b1.f + b2.f + b3.f;
|
||||
result.g = b0.g + b1.g + b2.g + b3.g;
|
||||
result.h = b0.h + b1.h + b2.h + b3.h;
|
||||
result.i = b0.i + b1.i + b2.i + b3.i;
|
||||
|
||||
printf("%g %g %g %g %g %g %g %g %g\n", result.a, result.b, result.c,
|
||||
result.d, result.e, result.f, result.g, result.h, result.i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct_72byte b0, b1, b2, b3;
|
||||
|
||||
b0 = *(struct_72byte*)(args[0]);
|
||||
b1 = *(struct_72byte*)(args[1]);
|
||||
b2 = *(struct_72byte*)(args[2]);
|
||||
b3 = *(struct_72byte*)(args[3]);
|
||||
|
||||
*(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[10];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7.0 };
|
||||
struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4.0 };
|
||||
struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3.0 };
|
||||
struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2.0 };
|
||||
struct_72byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_double;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = &ffi_type_double;
|
||||
cls_struct_fields[5] = &ffi_type_double;
|
||||
cls_struct_fields[6] = &ffi_type_double;
|
||||
cls_struct_fields[7] = &ffi_type_double;
|
||||
cls_struct_fields[8] = &ffi_type_double;
|
||||
cls_struct_fields[9] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = &cls_struct_type;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "22 15 17 25 6 13 19 18 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
|
||||
struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
125
.pc/msvc-changes/testsuite/libffi.call/stret_medium2.c
Normal file
125
.pc/msvc-changes/testsuite/libffi.call/stret_medium2.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* Area: ffi_call, closure_call
|
||||
Purpose: Check structure returning with different structure size.
|
||||
Depending on the ABI. Check bigger struct which overlaps
|
||||
the gp and fp register count on Darwin/AIX/ppc64.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: Blake Chaffin 6/21/2007 */
|
||||
|
||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
||||
/* { dg-options "-Wno-format" { target alpha*-dec-osf* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct struct_72byte {
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
double g;
|
||||
double h;
|
||||
long long i;
|
||||
} struct_72byte;
|
||||
|
||||
struct_72byte cls_struct_72byte_fn(
|
||||
struct_72byte b0,
|
||||
struct_72byte b1,
|
||||
struct_72byte b2,
|
||||
struct_72byte b3)
|
||||
{
|
||||
struct_72byte result;
|
||||
|
||||
result.a = b0.a + b1.a + b2.a + b3.a;
|
||||
result.b = b0.b + b1.b + b2.b + b3.b;
|
||||
result.c = b0.c + b1.c + b2.c + b3.c;
|
||||
result.d = b0.d + b1.d + b2.d + b3.d;
|
||||
result.e = b0.e + b1.e + b2.e + b3.e;
|
||||
result.f = b0.f + b1.f + b2.f + b3.f;
|
||||
result.g = b0.g + b1.g + b2.g + b3.g;
|
||||
result.h = b0.h + b1.h + b2.h + b3.h;
|
||||
result.i = b0.i + b1.i + b2.i + b3.i;
|
||||
|
||||
printf("%g %g %g %g %g %g %g %g %" PRIdLL "\n", result.a, result.b, result.c,
|
||||
result.d, result.e, result.f, result.g, result.h, result.i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_72byte_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct_72byte b0, b1, b2, b3;
|
||||
|
||||
b0 = *(struct_72byte*)(args[0]);
|
||||
b1 = *(struct_72byte*)(args[1]);
|
||||
b2 = *(struct_72byte*)(args[2]);
|
||||
b3 = *(struct_72byte*)(args[3]);
|
||||
|
||||
*(struct_72byte*)resp = cls_struct_72byte_fn(b0, b1, b2, b3);
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
void* args_dbl[5];
|
||||
ffi_type* cls_struct_fields[10];
|
||||
ffi_type cls_struct_type;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type.size = 0;
|
||||
cls_struct_type.alignment = 0;
|
||||
cls_struct_type.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type.elements = cls_struct_fields;
|
||||
|
||||
struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7 };
|
||||
struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4 };
|
||||
struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3 };
|
||||
struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2 };
|
||||
struct_72byte res_dbl;
|
||||
|
||||
cls_struct_fields[0] = &ffi_type_double;
|
||||
cls_struct_fields[1] = &ffi_type_double;
|
||||
cls_struct_fields[2] = &ffi_type_double;
|
||||
cls_struct_fields[3] = &ffi_type_double;
|
||||
cls_struct_fields[4] = &ffi_type_double;
|
||||
cls_struct_fields[5] = &ffi_type_double;
|
||||
cls_struct_fields[6] = &ffi_type_double;
|
||||
cls_struct_fields[7] = &ffi_type_double;
|
||||
cls_struct_fields[8] = &ffi_type_sint64;
|
||||
cls_struct_fields[9] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type;
|
||||
dbl_arg_types[1] = &cls_struct_type;
|
||||
dbl_arg_types[2] = &cls_struct_type;
|
||||
dbl_arg_types[3] = &cls_struct_type;
|
||||
dbl_arg_types[4] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
args_dbl[0] = &e_dbl;
|
||||
args_dbl[1] = &f_dbl;
|
||||
args_dbl[2] = &g_dbl;
|
||||
args_dbl[3] = &h_dbl;
|
||||
args_dbl[4] = NULL;
|
||||
|
||||
ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl);
|
||||
/* { dg-output "22 15 17 25 6 13 19 18 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_72byte_gn, NULL, code) == FFI_OK);
|
||||
|
||||
res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte,
|
||||
struct_72byte, struct_72byte))(code))(e_dbl, f_dbl, g_dbl, h_dbl);
|
||||
/* { dg-output "\n22 15 17 25 6 13 19 18 16" } */
|
||||
printf("res: %g %g %g %g %g %g %g %g %" PRIdLL "\n", res_dbl.a, res_dbl.b, res_dbl.c,
|
||||
res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i);
|
||||
/* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
44
.pc/msvc-changes/testsuite/libffi.call/strlen2_win32.c
Normal file
44
.pc/msvc-changes/testsuite/libffi.call/strlen2_win32.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check fastcall strlen call on X86_WIN32 systems.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: From the original ffitest.c */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
|
||||
#include "ffitest.h"
|
||||
|
||||
static size_t __attribute__((fastcall)) my_fastcall_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, FFI_FASTCALL, 1,
|
||||
&ffi_type_sint, args) == FFI_OK);
|
||||
|
||||
s = "a";
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
|
||||
CHECK(rint == 1);
|
||||
|
||||
s = "1234567";
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
|
||||
CHECK(rint == 7);
|
||||
|
||||
s = "1234567890123456789012345";
|
||||
ffi_call(&cif, FFI_FN(my_fastcall_strlen), &rint, values);
|
||||
CHECK(rint == 25);
|
||||
|
||||
printf("fastcall strlen tests passed\n");
|
||||
exit(0);
|
||||
}
|
||||
65
.pc/msvc-changes/testsuite/libffi.call/struct1.c
Normal file
65
.pc/msvc-changes/testsuite/libffi.call/struct1.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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 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];
|
||||
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);
|
||||
}
|
||||
65
.pc/msvc-changes/testsuite/libffi.call/struct1_win32.c
Normal file
65
.pc/msvc-changes/testsuite/libffi.call/struct1_win32.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check structures with fastcall/thiscall convention.
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: From the original ffitest.c */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char uc;
|
||||
double d;
|
||||
unsigned int ui;
|
||||
} test_structure_1;
|
||||
|
||||
static __attribute__ ((fastcall)) 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];
|
||||
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_FASTCALL, 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);
|
||||
}
|
||||
67
.pc/msvc-changes/testsuite/libffi.call/struct2.c
Normal file
67
.pc/msvc-changes/testsuite/libffi.call/struct2.c
Normal file
@@ -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 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];
|
||||
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;
|
||||
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_2 *ts2_result =
|
||||
(test_structure_2 *) malloc (sizeof(test_structure_2));
|
||||
|
||||
args[0] = &ts2_type;
|
||||
values[0] = &ts2_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
67
.pc/msvc-changes/testsuite/libffi.call/struct2_win32.c
Normal file
67
.pc/msvc-changes/testsuite/libffi.call/struct2_win32.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Area: ffi_call
|
||||
Purpose: Check structures in fastcall/stdcall function
|
||||
Limitations: none.
|
||||
PR: none.
|
||||
Originator: From the original ffitest.c */
|
||||
|
||||
/* { dg-do run { target i?86-*-cygwin* i?86-*-mingw* } } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double d1;
|
||||
double d2;
|
||||
} test_structure_2;
|
||||
|
||||
static test_structure_2 __attribute__ ((fastcall)) 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];
|
||||
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;
|
||||
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_2 *ts2_result =
|
||||
(test_structure_2 *) malloc (sizeof(test_structure_2));
|
||||
|
||||
args[0] = &ts2_type;
|
||||
values[0] = &ts2_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_FASTCALL, 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);
|
||||
}
|
||||
59
.pc/msvc-changes/testsuite/libffi.call/struct3.c
Normal file
59
.pc/msvc-changes/testsuite/libffi.call/struct3.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* 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 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];
|
||||
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;
|
||||
|
||||
test_structure_3 ts3_arg;
|
||||
test_structure_3 *ts3_result =
|
||||
(test_structure_3 *) malloc (sizeof(test_structure_3));
|
||||
|
||||
args[0] = &ts3_type;
|
||||
values[0] = &ts3_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
63
.pc/msvc-changes/testsuite/libffi.call/struct4.c
Normal file
63
.pc/msvc-changes/testsuite/libffi.call/struct4.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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 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];
|
||||
ts4_type.size = 0;
|
||||
ts4_type.alignment = 0;
|
||||
ts4_type.type = FFI_TYPE_STRUCT;
|
||||
test_structure_4 ts4_arg;
|
||||
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;
|
||||
|
||||
|
||||
/* This is a hack to get a properly aligned result buffer */
|
||||
test_structure_4 *ts4_result =
|
||||
(test_structure_4 *) malloc (sizeof(test_structure_4));
|
||||
|
||||
args[0] = &ts4_type;
|
||||
values[0] = &ts4_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
65
.pc/msvc-changes/testsuite/libffi.call/struct5.c
Normal file
65
.pc/msvc-changes/testsuite/libffi.call/struct5.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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 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];
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
args[0] = &ts5_type;
|
||||
args[1] = &ts5_type;
|
||||
values[0] = &ts5_arg1;
|
||||
values[1] = &ts5_arg2;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
64
.pc/msvc-changes/testsuite/libffi.call/struct6.c
Normal file
64
.pc/msvc-changes/testsuite/libffi.call/struct6.c
Normal file
@@ -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 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];
|
||||
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;
|
||||
|
||||
|
||||
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));
|
||||
|
||||
args[0] = &ts6_type;
|
||||
values[0] = &ts6_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
74
.pc/msvc-changes/testsuite/libffi.call/struct7.c
Normal file
74
.pc/msvc-changes/testsuite/libffi.call/struct7.c
Normal file
@@ -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 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];
|
||||
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;
|
||||
|
||||
|
||||
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));
|
||||
|
||||
args[0] = &ts7_type;
|
||||
values[0] = &ts7_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
80
.pc/msvc-changes/testsuite/libffi.call/struct8.c
Normal file
80
.pc/msvc-changes/testsuite/libffi.call/struct8.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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 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];
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
args[0] = &ts8_type;
|
||||
values[0] = &ts8_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
67
.pc/msvc-changes/testsuite/libffi.call/struct9.c
Normal file
67
.pc/msvc-changes/testsuite/libffi.call/struct9.c
Normal file
@@ -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
|
||||
{
|
||||
float f;
|
||||
int i;
|
||||
} test_structure_9;
|
||||
|
||||
static test_structure_9 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];
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
args[0] = &ts9_type;
|
||||
values[0] = &ts9_arg;
|
||||
|
||||
/* Initialize the cif */
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 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);
|
||||
}
|
||||
70
.pc/msvc-changes/testsuite/libffi.call/testclosure.c
Normal file
70
.pc/msvc-changes/testsuite/libffi.call/testclosure.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Area: closure_call
|
||||
Purpose: Check return value float.
|
||||
Limitations: none.
|
||||
PR: 41908.
|
||||
Originator: <rfm@gnu.org> 20091102 */
|
||||
|
||||
/* { dg-do run } */
|
||||
#include "ffitest.h"
|
||||
|
||||
typedef struct cls_struct_combined {
|
||||
float a;
|
||||
float b;
|
||||
float c;
|
||||
float d;
|
||||
} cls_struct_combined;
|
||||
|
||||
void cls_struct_combined_fn(struct cls_struct_combined arg)
|
||||
{
|
||||
printf("%g %g %g %g\n",
|
||||
arg.a, arg.b,
|
||||
arg.c, arg.d);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void
|
||||
cls_struct_combined_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
|
||||
void** args, void* userdata __UNUSED__)
|
||||
{
|
||||
struct cls_struct_combined a0;
|
||||
|
||||
a0 = *(struct cls_struct_combined*)(args[0]);
|
||||
|
||||
cls_struct_combined_fn(a0);
|
||||
}
|
||||
|
||||
|
||||
int main (void)
|
||||
{
|
||||
ffi_cif cif;
|
||||
void *code;
|
||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
||||
ffi_type* cls_struct_fields0[5];
|
||||
ffi_type cls_struct_type0;
|
||||
ffi_type* dbl_arg_types[5];
|
||||
|
||||
cls_struct_type0.size = 0;
|
||||
cls_struct_type0.alignment = 0;
|
||||
cls_struct_type0.type = FFI_TYPE_STRUCT;
|
||||
cls_struct_type0.elements = cls_struct_fields0;
|
||||
|
||||
struct cls_struct_combined g_dbl = {4.0, 5.0, 1.0, 8.0};
|
||||
|
||||
cls_struct_fields0[0] = &ffi_type_float;
|
||||
cls_struct_fields0[1] = &ffi_type_float;
|
||||
cls_struct_fields0[2] = &ffi_type_float;
|
||||
cls_struct_fields0[3] = &ffi_type_float;
|
||||
cls_struct_fields0[4] = NULL;
|
||||
|
||||
dbl_arg_types[0] = &cls_struct_type0;
|
||||
dbl_arg_types[1] = NULL;
|
||||
|
||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_void,
|
||||
dbl_arg_types) == FFI_OK);
|
||||
|
||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_combined_gn, NULL, code) == FFI_OK);
|
||||
|
||||
((void(*)(cls_struct_combined)) (code))(g_dbl);
|
||||
/* { dg-output "4 5 1 8" } */
|
||||
exit(0);
|
||||
}
|
||||
591
.pc/stand-alone/doc/libffi.info
Normal file
591
.pc/stand-alone/doc/libffi.info
Normal file
@@ -0,0 +1,591 @@
|
||||
This is /home/green/libffi/doc/libffi.info, produced by makeinfo
|
||||
version 4.13 from /home/green/libffi/doc/libffi.texi.
|
||||
|
||||
This manual is for Libffi, a portable foreign-function interface
|
||||
library.
|
||||
|
||||
Copyright (C) 2008, 2010 Red Hat, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version. A copy of the license is
|
||||
included in the section entitled "GNU General Public License".
|
||||
|
||||
|
||||
INFO-DIR-SECTION Development
|
||||
START-INFO-DIR-ENTRY
|
||||
* libffi: (libffi). Portable foreign-function interface library.
|
||||
END-INFO-DIR-ENTRY
|
||||
|
||||
|
||||
File: libffi.info, Node: Top, Next: Introduction, Up: (dir)
|
||||
|
||||
libffi
|
||||
******
|
||||
|
||||
This manual is for Libffi, a portable foreign-function interface
|
||||
library.
|
||||
|
||||
Copyright (C) 2008, 2010 Red Hat, Inc.
|
||||
|
||||
Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version. A copy of the license is
|
||||
included in the section entitled "GNU General Public License".
|
||||
|
||||
|
||||
* Menu:
|
||||
|
||||
* Introduction:: What is libffi?
|
||||
* Using libffi:: How to use libffi.
|
||||
* Missing Features:: Things libffi can't do.
|
||||
* Index:: Index.
|
||||
|
||||
|
||||
File: libffi.info, Node: Introduction, Next: Using libffi, Prev: Top, Up: Top
|
||||
|
||||
1 What is libffi?
|
||||
*****************
|
||||
|
||||
Compilers for high level languages generate code that follow certain
|
||||
conventions. These conventions are necessary, in part, for separate
|
||||
compilation to work. One such convention is the "calling convention".
|
||||
The calling convention is a set of assumptions made by the compiler
|
||||
about where function arguments will be found on entry to a function. A
|
||||
calling convention also specifies where the return value for a function
|
||||
is found. The calling convention is also sometimes called the "ABI" or
|
||||
"Application Binary Interface".
|
||||
|
||||
Some programs may not know at the time of compilation what arguments
|
||||
are to be passed to a function. For instance, an interpreter may be
|
||||
told at run-time about the number and types of arguments used to call a
|
||||
given function. `Libffi' can be used in such programs to provide a
|
||||
bridge from the interpreter program to compiled code.
|
||||
|
||||
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.
|
||||
|
||||
FFI stands for Foreign Function Interface. A foreign function
|
||||
interface is the popular name for the interface that allows code
|
||||
written in one language to call code written in another language. The
|
||||
`libffi' library really only provides the lowest, machine dependent
|
||||
layer of a fully featured foreign function interface. A layer must
|
||||
exist above `libffi' that handles type conversions for values passed
|
||||
between the two languages.
|
||||
|
||||
|
||||
File: libffi.info, Node: Using libffi, Next: Missing Features, Prev: Introduction, Up: Top
|
||||
|
||||
2 Using libffi
|
||||
**************
|
||||
|
||||
* Menu:
|
||||
|
||||
* The Basics:: The basic libffi API.
|
||||
* Simple Example:: A simple example.
|
||||
* Types:: libffi type descriptions.
|
||||
* Multiple ABIs:: Different passing styles on one platform.
|
||||
* The Closure API:: Writing a generic function.
|
||||
* Closure Example:: A closure example.
|
||||
|
||||
|
||||
File: libffi.info, Node: The Basics, Next: Simple Example, Up: Using libffi
|
||||
|
||||
2.1 The Basics
|
||||
==============
|
||||
|
||||
`Libffi' assumes that you have a pointer to the function you wish to
|
||||
call and that you know the number and types of arguments to pass it, as
|
||||
well as the return type of the function.
|
||||
|
||||
The first thing you must do is create an `ffi_cif' object that
|
||||
matches the signature of the function you wish to call. This is a
|
||||
separate step because it is common to make multiple calls using a
|
||||
single `ffi_cif'. The "cif" in `ffi_cif' stands for Call InterFace.
|
||||
To prepare a call interface object, use the function `ffi_prep_cif'.
|
||||
|
||||
-- Function: ffi_status ffi_prep_cif (ffi_cif *CIF, ffi_abi ABI,
|
||||
unsigned int NARGS, ffi_type *RTYPE, ffi_type **ARGTYPES)
|
||||
This initializes CIF according to the given parameters.
|
||||
|
||||
ABI is the ABI to use; normally `FFI_DEFAULT_ABI' is what you
|
||||
want. *note Multiple ABIs:: for more information.
|
||||
|
||||
NARGS is the number of arguments that this function accepts.
|
||||
`libffi' does not yet handle varargs functions; see *note Missing
|
||||
Features:: for more information.
|
||||
|
||||
RTYPE is a pointer to an `ffi_type' structure that describes the
|
||||
return type of the function. *Note Types::.
|
||||
|
||||
ARGTYPES is a vector of `ffi_type' pointers. ARGTYPES must have
|
||||
NARGS elements. If NARGS is 0, this argument is ignored.
|
||||
|
||||
`ffi_prep_cif' returns a `libffi' status code, of type
|
||||
`ffi_status'. This will be either `FFI_OK' if everything worked
|
||||
properly; `FFI_BAD_TYPEDEF' if one of the `ffi_type' objects is
|
||||
incorrect; or `FFI_BAD_ABI' if the ABI parameter is invalid.
|
||||
|
||||
To call a function using an initialized `ffi_cif', use the
|
||||
`ffi_call' function:
|
||||
|
||||
-- Function: void ffi_call (ffi_cif *CIF, void *FN, void *RVALUE, void
|
||||
**AVALUES)
|
||||
This calls the function FN according to the description given in
|
||||
CIF. CIF must have already been prepared using `ffi_prep_cif'.
|
||||
|
||||
RVALUE is a pointer to a chunk of memory that will hold the result
|
||||
of the function call. This must be large enough to hold the
|
||||
result and must be suitably aligned; it is the caller's
|
||||
responsibility to ensure this. If CIF declares that the function
|
||||
returns `void' (using `ffi_type_void'), then RVALUE is ignored.
|
||||
If RVALUE is `NULL', then the return value is discarded.
|
||||
|
||||
AVALUES is a vector of `void *' pointers that point to the memory
|
||||
locations holding the argument values for a call. If CIF declares
|
||||
that the function has no arguments (i.e., NARGS was 0), then
|
||||
AVALUES is ignored.
|
||||
|
||||
|
||||
File: libffi.info, Node: Simple Example, Next: Types, Prev: The Basics, Up: Using libffi
|
||||
|
||||
2.2 Simple Example
|
||||
==================
|
||||
|
||||
Here is a trivial example that calls `puts' a few times.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[1];
|
||||
void *values[1];
|
||||
char *s;
|
||||
int rc;
|
||||
|
||||
/* 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,
|
||||
&ffi_type_uint, 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
|
||||
value of s */
|
||||
s = "This is cool!";
|
||||
ffi_call(&cif, puts, &rc, values);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File: libffi.info, Node: Types, Next: Multiple ABIs, Prev: Simple Example, Up: Using libffi
|
||||
|
||||
2.3 Types
|
||||
=========
|
||||
|
||||
* Menu:
|
||||
|
||||
* Primitive Types:: Built-in types.
|
||||
* Structures:: Structure types.
|
||||
* Type Example:: Structure type example.
|
||||
|
||||
|
||||
File: libffi.info, Node: Primitive Types, Next: Structures, Up: Types
|
||||
|
||||
2.3.1 Primitive Types
|
||||
---------------------
|
||||
|
||||
`Libffi' provides a number of built-in type descriptors that can be
|
||||
used to describe argument and return types:
|
||||
|
||||
`ffi_type_void'
|
||||
The type `void'. This cannot be used for argument types, only for
|
||||
return values.
|
||||
|
||||
`ffi_type_uint8'
|
||||
An unsigned, 8-bit integer type.
|
||||
|
||||
`ffi_type_sint8'
|
||||
A signed, 8-bit integer type.
|
||||
|
||||
`ffi_type_uint16'
|
||||
An unsigned, 16-bit integer type.
|
||||
|
||||
`ffi_type_sint16'
|
||||
A signed, 16-bit integer type.
|
||||
|
||||
`ffi_type_uint32'
|
||||
An unsigned, 32-bit integer type.
|
||||
|
||||
`ffi_type_sint32'
|
||||
A signed, 32-bit integer type.
|
||||
|
||||
`ffi_type_uint64'
|
||||
An unsigned, 64-bit integer type.
|
||||
|
||||
`ffi_type_sint64'
|
||||
A signed, 64-bit integer type.
|
||||
|
||||
`ffi_type_float'
|
||||
The C `float' type.
|
||||
|
||||
`ffi_type_double'
|
||||
The C `double' type.
|
||||
|
||||
`ffi_type_uchar'
|
||||
The C `unsigned char' type.
|
||||
|
||||
`ffi_type_schar'
|
||||
The C `signed char' type. (Note that there is not an exact
|
||||
equivalent to the C `char' type in `libffi'; ordinarily you should
|
||||
either use `ffi_type_schar' or `ffi_type_uchar' depending on
|
||||
whether `char' is signed.)
|
||||
|
||||
`ffi_type_ushort'
|
||||
The C `unsigned short' type.
|
||||
|
||||
`ffi_type_sshort'
|
||||
The C `short' type.
|
||||
|
||||
`ffi_type_uint'
|
||||
The C `unsigned int' type.
|
||||
|
||||
`ffi_type_sint'
|
||||
The C `int' type.
|
||||
|
||||
`ffi_type_ulong'
|
||||
The C `unsigned long' type.
|
||||
|
||||
`ffi_type_slong'
|
||||
The C `long' type.
|
||||
|
||||
`ffi_type_longdouble'
|
||||
On platforms that have a C `long double' type, this is defined.
|
||||
On other platforms, it is not.
|
||||
|
||||
`ffi_type_pointer'
|
||||
A generic `void *' pointer. You should use this for all pointers,
|
||||
regardless of their real type.
|
||||
|
||||
Each of these is of type `ffi_type', so you must take the address
|
||||
when passing to `ffi_prep_cif'.
|
||||
|
||||
|
||||
File: libffi.info, Node: Structures, Next: Type Example, Prev: Primitive Types, Up: Types
|
||||
|
||||
2.3.2 Structures
|
||||
----------------
|
||||
|
||||
Although `libffi' has no special support for unions or bit-fields, it
|
||||
is perfectly happy passing structures back and forth. You must first
|
||||
describe the structure to `libffi' by creating a new `ffi_type' object
|
||||
for it.
|
||||
|
||||
-- ffi_type:
|
||||
The `ffi_type' has the following members:
|
||||
`size_t size'
|
||||
This is set by `libffi'; you should initialize it to zero.
|
||||
|
||||
`unsigned short alignment'
|
||||
This is set by `libffi'; you should initialize it to zero.
|
||||
|
||||
`unsigned short type'
|
||||
For a structure, this should be set to `FFI_TYPE_STRUCT'.
|
||||
|
||||
`ffi_type **elements'
|
||||
This is a `NULL'-terminated array of pointers to `ffi_type'
|
||||
objects. There is one element per field of the struct.
|
||||
|
||||
|
||||
File: libffi.info, Node: Type Example, Prev: Structures, Up: Types
|
||||
|
||||
2.3.3 Type Example
|
||||
------------------
|
||||
|
||||
The following example initializes a `ffi_type' object representing the
|
||||
`tm' struct from Linux's `time.h'.
|
||||
|
||||
Here is how the struct is defined:
|
||||
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
/* Those are for future use. */
|
||||
long int __tm_gmtoff__;
|
||||
__const char *__tm_zone__;
|
||||
};
|
||||
|
||||
Here is the corresponding code to describe this struct to `libffi':
|
||||
|
||||
{
|
||||
ffi_type tm_type;
|
||||
ffi_type *tm_type_elements[12];
|
||||
int i;
|
||||
|
||||
tm_type.size = tm_type.alignment = 0;
|
||||
tm_type.elements = &tm_type_elements;
|
||||
|
||||
for (i = 0; i < 9; i++)
|
||||
tm_type_elements[i] = &ffi_type_sint;
|
||||
|
||||
tm_type_elements[9] = &ffi_type_slong;
|
||||
tm_type_elements[10] = &ffi_type_pointer;
|
||||
tm_type_elements[11] = NULL;
|
||||
|
||||
/* tm_type can now be used to represent tm argument types and
|
||||
return types for ffi_prep_cif() */
|
||||
}
|
||||
|
||||
|
||||
File: libffi.info, Node: Multiple ABIs, Next: The Closure API, Prev: Types, Up: Using libffi
|
||||
|
||||
2.4 Multiple ABIs
|
||||
=================
|
||||
|
||||
A given platform may provide multiple different ABIs at once. For
|
||||
instance, the x86 platform has both `stdcall' and `fastcall' functions.
|
||||
|
||||
`libffi' provides some support for this. However, this is
|
||||
necessarily platform-specific.
|
||||
|
||||
|
||||
File: libffi.info, Node: The Closure API, Next: Closure Example, Prev: Multiple ABIs, Up: Using libffi
|
||||
|
||||
2.5 The Closure API
|
||||
===================
|
||||
|
||||
`libffi' also provides a way to write a generic function - a function
|
||||
that can accept and decode any combination of arguments. This can be
|
||||
useful when writing an interpreter, or to provide wrappers for
|
||||
arbitrary functions.
|
||||
|
||||
This facility is called the "closure API". Closures are not
|
||||
supported on all platforms; you can check the `FFI_CLOSURES' define to
|
||||
determine whether they are supported on the current platform.
|
||||
|
||||
Because closures work by assembling a tiny function at runtime, they
|
||||
require special allocation on platforms that have a non-executable
|
||||
heap. Memory management for closures is handled by a pair of functions:
|
||||
|
||||
-- Function: void *ffi_closure_alloc (size_t SIZE, void **CODE)
|
||||
Allocate a chunk of memory holding SIZE bytes. This returns a
|
||||
pointer to the writable address, and sets *CODE to the
|
||||
corresponding executable address.
|
||||
|
||||
SIZE should be sufficient to hold a `ffi_closure' object.
|
||||
|
||||
-- Function: void ffi_closure_free (void *WRITABLE)
|
||||
Free memory allocated using `ffi_closure_alloc'. The argument is
|
||||
the writable address that was returned.
|
||||
|
||||
Once you have allocated the memory for a closure, you must construct
|
||||
a `ffi_cif' describing the function call. Finally you can prepare the
|
||||
closure function:
|
||||
|
||||
-- Function: ffi_status ffi_prep_closure_loc (ffi_closure *CLOSURE,
|
||||
ffi_cif *CIF, void (*FUN) (ffi_cif *CIF, void *RET, void
|
||||
**ARGS, void *USER_DATA), void *USER_DATA, void *CODELOC)
|
||||
Prepare a closure function.
|
||||
|
||||
CLOSURE is the address of a `ffi_closure' object; this is the
|
||||
writable address returned by `ffi_closure_alloc'.
|
||||
|
||||
CIF is the `ffi_cif' describing the function parameters.
|
||||
|
||||
USER_DATA is an arbitrary datum that is passed, uninterpreted, to
|
||||
your closure function.
|
||||
|
||||
CODELOC is the executable address returned by `ffi_closure_alloc'.
|
||||
|
||||
FUN is the function which will be called when the closure is
|
||||
invoked. It is called with the arguments:
|
||||
CIF
|
||||
The `ffi_cif' passed to `ffi_prep_closure_loc'.
|
||||
|
||||
RET
|
||||
A pointer to the memory used for the function's return value.
|
||||
FUN must fill this, unless the function is declared as
|
||||
returning `void'.
|
||||
|
||||
ARGS
|
||||
A vector of pointers to memory holding the arguments to the
|
||||
function.
|
||||
|
||||
USER_DATA
|
||||
The same USER_DATA that was passed to `ffi_prep_closure_loc'.
|
||||
|
||||
`ffi_prep_closure_loc' will return `FFI_OK' if everything went ok,
|
||||
and something else on error.
|
||||
|
||||
After calling `ffi_prep_closure_loc', you can cast CODELOC to the
|
||||
appropriate pointer-to-function type.
|
||||
|
||||
You may see old code referring to `ffi_prep_closure'. This function
|
||||
is deprecated, as it cannot handle the need for separate writable and
|
||||
executable addresses.
|
||||
|
||||
|
||||
File: libffi.info, Node: Closure Example, Prev: The Closure API, Up: Using libffi
|
||||
|
||||
2.6 Closure Example
|
||||
===================
|
||||
|
||||
A trivial example that creates a new `puts' by binding `fputs' with
|
||||
`stdin'.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ffi.h>
|
||||
|
||||
/* Acts like puts with the file given at time of enclosure. */
|
||||
void puts_binding(ffi_cif *cif, unsigned int *ret, void* args[],
|
||||
FILE *stream)
|
||||
{
|
||||
*ret = fputs(*(char **)args[0], stream);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
ffi_cif cif;
|
||||
ffi_type *args[1];
|
||||
ffi_closure *closure;
|
||||
|
||||
int (*bound_puts)(char *);
|
||||
int rc;
|
||||
|
||||
/* Allocate closure and bound_puts */
|
||||
closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);
|
||||
|
||||
if (closure)
|
||||
{
|
||||
/* Initialize the argument info vectors */
|
||||
args[0] = &ffi_type_pointer;
|
||||
|
||||
/* Initialize the cif */
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
||||
&ffi_type_uint, args) == FFI_OK)
|
||||
{
|
||||
/* Initialize the closure, setting stream to stdout */
|
||||
if (ffi_prep_closure_loc(closure, &cif, puts_binding,
|
||||
stdout, bound_puts) == FFI_OK)
|
||||
{
|
||||
rc = bound_puts("Hello World!");
|
||||
/* rc now holds the result of the call to fputs */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Deallocate both closure, and bound_puts */
|
||||
ffi_closure_free(closure);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File: libffi.info, Node: Missing Features, Next: Index, Prev: Using libffi, Up: Top
|
||||
|
||||
3 Missing Features
|
||||
******************
|
||||
|
||||
`libffi' is missing a few features. We welcome patches to add support
|
||||
for these.
|
||||
|
||||
* There is no support for calling varargs functions. This may work
|
||||
on some platforms, depending on how the ABI is defined, but it is
|
||||
not reliable.
|
||||
|
||||
* There is no support for bit fields in structures.
|
||||
|
||||
* The closure API is
|
||||
|
||||
* The "raw" API is undocumented.
|
||||
|
||||
|
||||
File: libffi.info, Node: Index, Prev: Missing Features, Up: Top
|
||||
|
||||
Index
|
||||
*****
|
||||
|
||||
| ||||