Merge with GCC. Eliminate quilt bits.
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -16,8 +16,3 @@ libtool
|
|||||||
stamp-h1
|
stamp-h1
|
||||||
libffi*gz
|
libffi*gz
|
||||||
autom4te.cache
|
autom4te.cache
|
||||||
libffi.xcodeproj/xcuserdata
|
|
||||||
libffi.xcodeproj/project.xcworkspace
|
|
||||||
ios/
|
|
||||||
osx/
|
|
||||||
build_*/
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
patches
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
series
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
2
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,212 +0,0 @@
|
|||||||
## 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/bfin/ffi.c \
|
|
||||||
src/bfin/ffitarget.h src/bfin/sysv.S src/frv/eabi.S \
|
|
||||||
src/frv/ffitarget.h src/dlmalloc.c src/tile/ffi.c \
|
|
||||||
src/tile/ffitarget.h src/tile/tile.S libtool-version \
|
|
||||||
ChangeLog.libffi m4/libtool.m4 m4/lt~obsolete.m4 \
|
|
||||||
m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \
|
|
||||||
m4/ltversion.m4 src/arm/gentramp.sh src/debug.c msvcc.sh \
|
|
||||||
generate-ios-source-and-headers.py \
|
|
||||||
generate-osx-source-and-headers.py \
|
|
||||||
libffi.xcodeproj/project.pbxproj src/arm/trampoline.S
|
|
||||||
|
|
||||||
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 BFIN
|
|
||||||
nodist_libffi_la_SOURCES += src/bfin/ffi.c src/bfin/sysv.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
|
|
||||||
if TILE
|
|
||||||
nodist_libffi_la_SOURCES += src/tile/tile.S src/tile/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 -DFFI_BUILDING
|
|
||||||
AM_CCASFLAGS = $(AM_CPPFLAGS) -g
|
|
||||||
|
|
||||||
# No install-html or install-pdf support in automake yet
|
|
||||||
.PHONY: install-html install-pdf
|
|
||||||
install-html:
|
|
||||||
install-pdf:
|
|
||||||
@@ -1,366 +0,0 @@
|
|||||||
Status
|
|
||||||
======
|
|
||||||
|
|
||||||
libffi-3.0.12 was released on XXXXXXX. Check the libffi web page for
|
|
||||||
updates: <URL:http://sourceware.org/libffi/>.
|
|
||||||
|
|
||||||
|
|
||||||
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 essentially 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Supported Platforms
|
|
||||||
===================
|
|
||||||
|
|
||||||
Libffi has been ported to many different platforms.
|
|
||||||
For specific configuration details and testing status, please
|
|
||||||
refer to the wiki page here:
|
|
||||||
|
|
||||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
|
|
||||||
|
|
||||||
At the time of release, the following basic configurations have been
|
|
||||||
tested:
|
|
||||||
|
|
||||||
|-----------------+------------------|
|
|
||||||
| Architecture | Operating System |
|
|
||||||
|-----------------+------------------|
|
|
||||||
| Alpha | Linux |
|
|
||||||
| Alpha | Tru64 |
|
|
||||||
| ARM | Linux |
|
|
||||||
| ARM | iOS |
|
|
||||||
| AVR32 | Linux |
|
|
||||||
| Blackfin | uClinux |
|
|
||||||
| HPPA | HPUX |
|
|
||||||
| IA-64 | Linux |
|
|
||||||
| M68K | FreeMiNT |
|
|
||||||
| M68K | RTEMS |
|
|
||||||
| MIPS | IRIX |
|
|
||||||
| MIPS | Linux |
|
|
||||||
| MIPS | RTEMS |
|
|
||||||
| MIPS64 | Linux |
|
|
||||||
| PowerPC | AMIGA |
|
|
||||||
| PowerPC | Linux |
|
|
||||||
| PowerPC | Mac OSX |
|
|
||||||
| PowerPC | FreeBSD |
|
|
||||||
| PowerPC64 | Linux |
|
|
||||||
| S390 | Linux |
|
|
||||||
| S390X | Linux |
|
|
||||||
| SPARC | Linux |
|
|
||||||
| SPARC | Solaris |
|
|
||||||
| SPARC64 | Linux |
|
|
||||||
| SPARC64 | FreeBSD |
|
|
||||||
| TILE-Gx/TILEPro | Linux |
|
|
||||||
| X86 | FreeBSD |
|
|
||||||
| X86 | Interix |
|
|
||||||
| X86 | kFreeBSD |
|
|
||||||
| X86 | Linux |
|
|
||||||
| X86 | Mac OSX |
|
|
||||||
| X86 | OpenBSD |
|
|
||||||
| X86 | OS/2 |
|
|
||||||
| X86 | Solaris |
|
|
||||||
| X86 | Windows/Cygwin |
|
|
||||||
| X86 | Windows/MingW |
|
|
||||||
| X86-64 | FreeBSD |
|
|
||||||
| X86-64 | Linux |
|
|
||||||
| X86-64 | Linux/x32 |
|
|
||||||
| X86-64 | OpenBSD |
|
|
||||||
| X86-64 | Windows/MingW |
|
|
||||||
|-----------------+------------------|
|
|
||||||
|
|
||||||
Please send additional platform test results to
|
|
||||||
libffi-discuss@sourceware.org and feel free to update the wiki page
|
|
||||||
above.
|
|
||||||
|
|
||||||
Installing libffi
|
|
||||||
=================
|
|
||||||
|
|
||||||
First you must configure the distribution for your particular
|
|
||||||
system. Go to the directory you wish to build libffi in and run the
|
|
||||||
"configure" program found in the root directory of the libffi source
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
You may want to tell configure where to install the libffi library and
|
|
||||||
header files. To do that, use the --prefix configure switch. Libffi
|
|
||||||
will install under /usr/local by default.
|
|
||||||
|
|
||||||
If you want to enable extra run-time debugging checks use the the
|
|
||||||
--enable-debug configure switch. This is useful when your program dies
|
|
||||||
mysteriously while using libffi.
|
|
||||||
|
|
||||||
Another useful configure switch is --enable-purify-safety. Using this
|
|
||||||
will add some extra code which will suppress certain warnings when you
|
|
||||||
are using Purify with libffi. Only use this switch when using
|
|
||||||
Purify, as it will slow down the library.
|
|
||||||
|
|
||||||
It's also possible to build libffi on Windows platforms with
|
|
||||||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
|
||||||
wrapper script during configuration like so:
|
|
||||||
|
|
||||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
|
||||||
|
|
||||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
|
||||||
You may also need to specify --build appropriately. When building with MSVC
|
|
||||||
under a MingW environment, you may need to remove the line in configure
|
|
||||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
|
||||||
present in MingW, and is not required when using MingW-style paths.)
|
|
||||||
|
|
||||||
For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
|
|
||||||
|
|
||||||
Configure has many other options. Use "configure --help" to see them all.
|
|
||||||
|
|
||||||
Once configure has finished, type "make". Note that you must be using
|
|
||||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
|
||||||
|
|
||||||
To ensure that libffi is working as advertised, type "make check".
|
|
||||||
This will require that you have DejaGNU installed.
|
|
||||||
|
|
||||||
To install the library and header files, type "make install".
|
|
||||||
|
|
||||||
|
|
||||||
History
|
|
||||||
=======
|
|
||||||
|
|
||||||
See the ChangeLog files for details.
|
|
||||||
|
|
||||||
3.0.12 XXX-XX-XX
|
|
||||||
Add Blackfin support.
|
|
||||||
Add TILE-Gx/TILEPro support.
|
|
||||||
|
|
||||||
3.0.11 Apr-11-12
|
|
||||||
Lots of build fixes.
|
|
||||||
Add Amiga newer MacOS support.
|
|
||||||
Add support for variadic functions (ffi_prep_cif_var).
|
|
||||||
Add Linux/x32 support.
|
|
||||||
Add thiscall, fastcall and MSVC cdecl support on Windows.
|
|
||||||
Add Amiga and newer MacOS support.
|
|
||||||
Add m68k FreeMiNT support.
|
|
||||||
Integration with iOS' xcode build tools.
|
|
||||||
Fix Octeon and MC68881 support.
|
|
||||||
Fix code pessimizations.
|
|
||||||
Lots of build fixes.
|
|
||||||
|
|
||||||
3.0.10 Aug-23-11
|
|
||||||
Add support for Apple's iOS.
|
|
||||||
Add support for ARM VFP ABI.
|
|
||||||
Add RTEMS support for MIPS and M68K.
|
|
||||||
Fix instruction cache clearing problems on
|
|
||||||
ARM and SPARC.
|
|
||||||
Fix the N64 build on mips-sgi-irix6.5.
|
|
||||||
Enable builds with Microsoft's compiler.
|
|
||||||
Enable x86 builds with Oracle's Solaris compiler.
|
|
||||||
Fix support for calling code compiled with Oracle's Sparc
|
|
||||||
Solaris compiler.
|
|
||||||
Testsuite fixes for Tru64 Unix.
|
|
||||||
Additional platform support.
|
|
||||||
|
|
||||||
3.0.9 Dec-31-09
|
|
||||||
Add AVR32 and win64 ports. Add ARM softfp support.
|
|
||||||
Many fixes for AIX, Solaris, HP-UX, *BSD.
|
|
||||||
Several PowerPC and x86-64 bug fixes.
|
|
||||||
Build DLL for windows.
|
|
||||||
|
|
||||||
3.0.8 Dec-19-08
|
|
||||||
Add *BSD, BeOS, and PA-Linux support.
|
|
||||||
|
|
||||||
3.0.7 Nov-11-08
|
|
||||||
Fix for ppc FreeBSD.
|
|
||||||
(thanks to Andreas Tobler)
|
|
||||||
|
|
||||||
3.0.6 Jul-17-08
|
|
||||||
Fix for closures on sh.
|
|
||||||
Mark the sh/sh64 stack as non-executable.
|
|
||||||
(both thanks to Kaz Kojima)
|
|
||||||
|
|
||||||
3.0.5 Apr-3-08
|
|
||||||
Fix libffi.pc file.
|
|
||||||
Fix #define ARM for IcedTea users.
|
|
||||||
Fix x86 closure bug.
|
|
||||||
|
|
||||||
3.0.4 Feb-24-08
|
|
||||||
Fix x86 OpenBSD configury.
|
|
||||||
|
|
||||||
3.0.3 Feb-22-08
|
|
||||||
Enable x86 OpenBSD thanks to Thomas Heller, and
|
|
||||||
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
|
|
||||||
Clean up test instruction in README.
|
|
||||||
|
|
||||||
3.0.2 Feb-21-08
|
|
||||||
Improved x86 FreeBSD support.
|
|
||||||
Thanks to Björn König.
|
|
||||||
|
|
||||||
3.0.1 Feb-15-08
|
|
||||||
Fix instruction cache flushing bug on MIPS.
|
|
||||||
Thanks to David Daney.
|
|
||||||
|
|
||||||
3.0.0 Feb-15-08
|
|
||||||
Many changes, mostly thanks to the GCC project.
|
|
||||||
Cygnus Solutions is now Red Hat.
|
|
||||||
|
|
||||||
[10 years go by...]
|
|
||||||
|
|
||||||
1.20 Oct-5-98
|
|
||||||
Raffaele Sena produces ARM port.
|
|
||||||
|
|
||||||
1.19 Oct-5-98
|
|
||||||
Fixed x86 long double and long long return support.
|
|
||||||
m68k bug fixes from Andreas Schwab.
|
|
||||||
Patch for DU assembler compatibility for the Alpha from Richard
|
|
||||||
Henderson.
|
|
||||||
|
|
||||||
1.18 Apr-17-98
|
|
||||||
Bug fixes and MIPS configuration changes.
|
|
||||||
|
|
||||||
1.17 Feb-24-98
|
|
||||||
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
|
|
||||||
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
|
|
||||||
|
|
||||||
1.16 Feb-11-98
|
|
||||||
Richard Henderson produces Alpha port.
|
|
||||||
|
|
||||||
1.15 Dec-4-97
|
|
||||||
Fixed an n32 ABI bug. New libtool, auto* support.
|
|
||||||
|
|
||||||
1.14 May-13-97
|
|
||||||
libtool is now used to generate shared and static libraries.
|
|
||||||
Fixed a minor portability problem reported by Russ McManus
|
|
||||||
<mcmanr@eq.gs.com>.
|
|
||||||
|
|
||||||
1.13 Dec-2-96
|
|
||||||
Added --enable-purify-safety to keep Purify from complaining
|
|
||||||
about certain low level code.
|
|
||||||
Sparc fix for calling functions with < 6 args.
|
|
||||||
Linux x86 a.out fix.
|
|
||||||
|
|
||||||
1.12 Nov-22-96
|
|
||||||
Added missing ffi_type_void, needed for supporting void return
|
|
||||||
types. Fixed test case for non MIPS machines. Cygnus Support
|
|
||||||
is now Cygnus Solutions.
|
|
||||||
|
|
||||||
1.11 Oct-30-96
|
|
||||||
Added notes about GNU make.
|
|
||||||
|
|
||||||
1.10 Oct-29-96
|
|
||||||
Added configuration fix for non GNU compilers.
|
|
||||||
|
|
||||||
1.09 Oct-29-96
|
|
||||||
Added --enable-debug configure switch. Clean-ups based on LCLint
|
|
||||||
feedback. ffi_mips.h is always installed. Many configuration
|
|
||||||
fixes. Fixed ffitest.c for sparc builds.
|
|
||||||
|
|
||||||
1.08 Oct-15-96
|
|
||||||
Fixed n32 problem. Many clean-ups.
|
|
||||||
|
|
||||||
1.07 Oct-14-96
|
|
||||||
Gordon Irlam rewrites v8.S again. Bug fixes.
|
|
||||||
|
|
||||||
1.06 Oct-14-96
|
|
||||||
Gordon Irlam improved the sparc port.
|
|
||||||
|
|
||||||
1.05 Oct-14-96
|
|
||||||
Interface changes based on feedback.
|
|
||||||
|
|
||||||
1.04 Oct-11-96
|
|
||||||
Sparc port complete (modulo struct passing bug).
|
|
||||||
|
|
||||||
1.03 Oct-10-96
|
|
||||||
Passing struct args, and returning struct values works for
|
|
||||||
all architectures/calling conventions. Expanded tests.
|
|
||||||
|
|
||||||
1.02 Oct-9-96
|
|
||||||
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
|
|
||||||
Added "make test".
|
|
||||||
|
|
||||||
1.01 Oct-8-96
|
|
||||||
Fixed float passing bug in mips version. Restructured some
|
|
||||||
of the code. Builds cleanly with SGI tools.
|
|
||||||
|
|
||||||
1.00 Oct-7-96
|
|
||||||
First release. No public announcement.
|
|
||||||
|
|
||||||
|
|
||||||
Authors & Credits
|
|
||||||
=================
|
|
||||||
|
|
||||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
|
||||||
|
|
||||||
The developers of the GNU Compiler Collection project have made
|
|
||||||
innumerable valuable contributions. See the ChangeLog file for
|
|
||||||
details.
|
|
||||||
|
|
||||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
|
||||||
gencall library for Silicon Graphics machines.
|
|
||||||
|
|
||||||
The closure mechanism was designed and implemented by Kresten Krab
|
|
||||||
Thorup.
|
|
||||||
|
|
||||||
Major processor architecture ports were contributed by the following
|
|
||||||
developers:
|
|
||||||
|
|
||||||
alpha Richard Henderson
|
|
||||||
arm Raffaele Sena
|
|
||||||
blackfin Alexandre Keunecke I. de Mendonca
|
|
||||||
cris Simon Posnjak, Hans-Peter Nilsson
|
|
||||||
frv Anthony Green
|
|
||||||
ia64 Hans Boehm
|
|
||||||
m32r Kazuhiro Inaoka
|
|
||||||
m68k Andreas Schwab
|
|
||||||
mips Anthony Green, Casey Marshall
|
|
||||||
mips64 David Daney
|
|
||||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
|
||||||
powerpc Geoffrey Keating, Andreas Tobler,
|
|
||||||
David Edelsohn, John Hornkvist
|
|
||||||
powerpc64 Jakub Jelinek
|
|
||||||
s390 Gerhard Tonn, Ulrich Weigand
|
|
||||||
sh Kaz Kojima
|
|
||||||
sh64 Kaz Kojima
|
|
||||||
sparc Anthony Green, Gordon Irlam
|
|
||||||
tile-gx/tilepro Walter Lee
|
|
||||||
x86 Anthony Green, Jon Beniston
|
|
||||||
x86-64 Bo Thorsen
|
|
||||||
|
|
||||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
|
||||||
stepping through the code and tracking down bugs.
|
|
||||||
|
|
||||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
|
||||||
configuration help.
|
|
||||||
|
|
||||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
|
||||||
interface.
|
|
||||||
|
|
||||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
|
||||||
|
|
||||||
Alex Oliva solved the executable page problem for SElinux.
|
|
||||||
|
|
||||||
The list above is almost certainly incomplete and inaccurate. I'm
|
|
||||||
happy to make corrections or additions upon request.
|
|
||||||
|
|
||||||
If you have a problem, or have found a bug, please send a note to the
|
|
||||||
author at green@moxielogic.com, or the project mailing list at
|
|
||||||
libffi-discuss@sourceware.org.
|
|
||||||
1971
.pc/aarch64/aclocal.m4
vendored
1971
.pc/aarch64/aclocal.m4
vendored
File diff suppressed because it is too large
Load Diff
1517
.pc/aarch64/config.guess
vendored
1517
.pc/aarch64/config.guess
vendored
File diff suppressed because it is too large
Load Diff
1779
.pc/aarch64/config.sub
vendored
1779
.pc/aarch64/config.sub
vendored
File diff suppressed because it is too large
Load Diff
17366
.pc/aarch64/configure
vendored
17366
.pc/aarch64/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,512 +0,0 @@
|
|||||||
dnl Process this with autoconf to create configure
|
|
||||||
|
|
||||||
AC_PREREQ(2.68)
|
|
||||||
|
|
||||||
AC_INIT([libffi], [3.0.11], [http://github.com/atgreen/libffi/issues])
|
|
||||||
AC_CONFIG_HEADERS([fficonfig.h])
|
|
||||||
|
|
||||||
AC_CANONICAL_SYSTEM
|
|
||||||
target_alias=${target_alias-$host_alias}
|
|
||||||
|
|
||||||
. ${srcdir}/configure.host
|
|
||||||
|
|
||||||
AX_ENABLE_BUILDDIR
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE
|
|
||||||
|
|
||||||
# The same as in boehm-gc and libstdc++. Have to borrow it from there.
|
|
||||||
# We must force CC to /not/ be precious variables; otherwise
|
|
||||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
|
||||||
# As a side effect, we have to subst CFLAGS ourselves.
|
|
||||||
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
|
|
||||||
# defaults of its own if none are provided.
|
|
||||||
|
|
||||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
|
||||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
|
||||||
save_CFLAGS=$CFLAGS
|
|
||||||
AC_PROG_CC
|
|
||||||
CFLAGS=$save_CFLAGS
|
|
||||||
m4_undefine([_AC_ARG_VAR_PRECIOUS])
|
|
||||||
m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
|
||||||
|
|
||||||
AC_SUBST(CFLAGS)
|
|
||||||
|
|
||||||
AM_PROG_AS
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
|
|
||||||
AX_CC_MAXOPT
|
|
||||||
AX_CFLAGS_WARN_ALL
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
CFLAGS="$CFLAGS -fexceptions"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/mman.h)
|
|
||||||
AC_CHECK_FUNCS(mmap)
|
|
||||||
AC_FUNC_MMAP_BLACKLIST
|
|
||||||
|
|
||||||
dnl The -no-testsuite modules omit the test subdir.
|
|
||||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
|
||||||
|
|
||||||
TARGETDIR="unknown"
|
|
||||||
case "$host" in
|
|
||||||
alpha*-*-*)
|
|
||||||
TARGET=ALPHA; TARGETDIR=alpha;
|
|
||||||
# Support 128-bit long double, changeable via command-line switch.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
|
||||||
;;
|
|
||||||
|
|
||||||
arm*-*-*)
|
|
||||||
TARGET=ARM; TARGETDIR=arm
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd* | amd64-*-openbsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
avr32*-*-*)
|
|
||||||
TARGET=AVR32; TARGETDIR=avr32
|
|
||||||
;;
|
|
||||||
|
|
||||||
bfin*)
|
|
||||||
TARGET=BFIN; TARGETDIR=bfin
|
|
||||||
;;
|
|
||||||
|
|
||||||
cris-*-*)
|
|
||||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
|
||||||
;;
|
|
||||||
|
|
||||||
frv-*-*)
|
|
||||||
TARGET=FRV; TARGETDIR=frv
|
|
||||||
;;
|
|
||||||
|
|
||||||
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
|
|
||||||
TARGET=PA_LINUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*64-*-hpux*)
|
|
||||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*-*-hpux*)
|
|
||||||
TARGET=PA_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
|
|
||||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
|
||||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
|
|
||||||
TARGET=X86_WIN32; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
i?86-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-solaris2.1[[0-9]]*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
ia64*-*-*)
|
|
||||||
TARGET=IA64; TARGETDIR=ia64
|
|
||||||
;;
|
|
||||||
|
|
||||||
m32r*-*-*)
|
|
||||||
TARGET=M32R; TARGETDIR=m32r
|
|
||||||
;;
|
|
||||||
|
|
||||||
m68k-*-*)
|
|
||||||
TARGET=M68K; TARGETDIR=m68k
|
|
||||||
;;
|
|
||||||
|
|
||||||
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
mips*-*-linux* | mips*-*-openbsd*)
|
|
||||||
# Support 128-bit long double for NewABI.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__mips64)'
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
|
|
||||||
moxie-*-*)
|
|
||||||
TARGET=MOXIE; TARGETDIR=moxie
|
|
||||||
;;
|
|
||||||
|
|
||||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-amigaos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-beos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-darwin* | powerpc64-*-darwin*)
|
|
||||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-aix* | rs6000-*-aix*)
|
|
||||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-freebsd* | powerpc-*-openbsd*)
|
|
||||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc64-*-freebsd*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc*-*-rtems*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
|
|
||||||
s390-*-* | s390x-*-*)
|
|
||||||
TARGET=S390; TARGETDIR=s390
|
|
||||||
;;
|
|
||||||
|
|
||||||
sh-*-* | sh[[34]]*-*-*)
|
|
||||||
TARGET=SH; TARGETDIR=sh
|
|
||||||
;;
|
|
||||||
sh64-*-* | sh5*-*-*)
|
|
||||||
TARGET=SH64; TARGETDIR=sh64
|
|
||||||
;;
|
|
||||||
|
|
||||||
sparc*-*-*)
|
|
||||||
TARGET=SPARC; TARGETDIR=sparc
|
|
||||||
;;
|
|
||||||
|
|
||||||
tile*-*)
|
|
||||||
TARGET=TILE; TARGETDIR=tile
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-cygwin* | x86_64-*-mingw*)
|
|
||||||
TARGET=X86_WIN64; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
AC_SUBST(AM_RUNTESTFLAGS)
|
|
||||||
AC_SUBST(AM_LTLDFLAGS)
|
|
||||||
|
|
||||||
if test $TARGETDIR = unknown; then
|
|
||||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
|
||||||
AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
|
|
||||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
|
||||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
|
||||||
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
|
||||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
|
||||||
AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
|
|
||||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
|
||||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
|
||||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
|
||||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
|
||||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
|
||||||
AM_CONDITIONAL(MOXIE, test x$TARGET = xMOXIE)
|
|
||||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
|
||||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
|
||||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
|
||||||
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
|
|
||||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
|
||||||
AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
|
|
||||||
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
|
|
||||||
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
|
|
||||||
AM_CONDITIONAL(S390, test x$TARGET = xS390)
|
|
||||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
|
||||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
|
||||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
|
||||||
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
|
|
||||||
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
|
|
||||||
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
|
|
||||||
AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
|
|
||||||
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_FUNCS(memcpy)
|
|
||||||
AC_FUNC_ALLOCA
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(double)
|
|
||||||
AC_CHECK_SIZEOF(long double)
|
|
||||||
|
|
||||||
# Also AC_SUBST this variable for ffi.h.
|
|
||||||
if test -z "$HAVE_LONG_DOUBLE"; then
|
|
||||||
HAVE_LONG_DOUBLE=0
|
|
||||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
|
||||||
if test $ac_cv_sizeof_long_double != 0; then
|
|
||||||
HAVE_LONG_DOUBLE=1
|
|
||||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
|
||||||
|
|
||||||
GCC_AS_CFI_PSEUDO_OP
|
|
||||||
|
|
||||||
if test x$TARGET = xSPARC; then
|
|
||||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
|
||||||
libffi_cv_as_sparc_ua_pcrel, [
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
save_LDFLAGS="$LDFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -fpic"
|
|
||||||
LDFLAGS="$LDFLAGS -shared"
|
|
||||||
AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=yes],
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=no])
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
LDFLAGS="$save_LDFLAGS"])
|
|
||||||
if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
|
|
||||||
[Define if your assembler and linker support unaligned PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .register pseudo-op support],
|
|
||||||
libffi_cv_as_register_pseudo_op, [
|
|
||||||
libffi_cv_as_register_pseudo_op=unknown
|
|
||||||
# Check if we have .register
|
|
||||||
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
|
|
||||||
[libffi_cv_as_register_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_register_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .register.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports pc related relocs],
|
|
||||||
libffi_cv_as_x86_pcrel, [
|
|
||||||
libffi_cv_as_x86_pcrel=yes
|
|
||||||
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
|
|
||||||
libffi_cv_as_x86_pcrel=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
|
|
||||||
[Define if your assembler supports PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .ascii pseudo-op support],
|
|
||||||
libffi_cv_as_ascii_pseudo_op, [
|
|
||||||
libffi_cv_as_ascii_pseudo_op=unknown
|
|
||||||
# Check if we have .ascii
|
|
||||||
AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .ascii.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .string pseudo-op support],
|
|
||||||
libffi_cv_as_string_pseudo_op, [
|
|
||||||
libffi_cv_as_string_pseudo_op=unknown
|
|
||||||
# Check if we have .string
|
|
||||||
AC_TRY_COMPILE([asm (".string \\"string\\"");],,
|
|
||||||
[libffi_cv_as_string_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_string_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .string.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_WIN64; then
|
|
||||||
LT_SYS_SYMBOL_USCORE
|
|
||||||
if test "x$sys_symbol_underscore" = xyes; then
|
|
||||||
AC_DEFINE(SYMBOL_UNDERSCORE, 1, [Define if symbols are underscored.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=0
|
|
||||||
case "$target" in
|
|
||||||
*arm*-apple-darwin*)
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=1
|
|
||||||
AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1,
|
|
||||||
[Cannot use PROT_EXEC on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
*-apple-darwin1[[10]]* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*)
|
|
||||||
AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1,
|
|
||||||
[Cannot use malloc on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
|
|
||||||
AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports unwind section type],
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type, [
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
|
||||||
echo '.section .eh_frame,"a",@unwind' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
|
|
||||||
[Define if your assembler supports unwind section type.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
|
|
||||||
libffi_cv_ro_eh_frame, [
|
|
||||||
libffi_cv_ro_eh_frame=no
|
|
||||||
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
|
|
||||||
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
|
|
||||||
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
elif grep '.section.*eh_frame.*#alloc' conftest.c \
|
|
||||||
| grep -v '#write' > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_ro_eh_frame" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_RO_EH_FRAME, 1,
|
|
||||||
[Define if .eh_frame sections should be read-only.])
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "a",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
else
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "aw",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
|
|
||||||
libffi_cv_hidden_visibility_attribute, [
|
|
||||||
echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c
|
|
||||||
libffi_cv_hidden_visibility_attribute=no
|
|
||||||
if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
|
||||||
if grep '\.hidden.*foo' conftest.s >/dev/null; then
|
|
||||||
libffi_cv_hidden_visibility_attribute=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test $libffi_cv_hidden_visibility_attribute = yes; then
|
|
||||||
AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
|
|
||||||
[Define if __attribute__((visibility("hidden"))) is supported.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AH_BOTTOM([
|
|
||||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name) .hidden name
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name)
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_SUBST(TARGET)
|
|
||||||
AC_SUBST(TARGETDIR)
|
|
||||||
|
|
||||||
AC_SUBST(SHELL)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(debug,
|
|
||||||
[ --enable-debug debugging mode],
|
|
||||||
if test "$enable_debug" = "yes"; then
|
|
||||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
|
||||||
fi)
|
|
||||||
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(structs,
|
|
||||||
[ --disable-structs omit code for struct support],
|
|
||||||
if test "$enable_structs" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(raw-api,
|
|
||||||
[ --disable-raw-api make the raw api unavailable],
|
|
||||||
if test "$enable_raw_api" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(purify-safety,
|
|
||||||
[ --enable-purify-safety purify-safe mode],
|
|
||||||
if test "$enable_purify_safety" = "yes"; then
|
|
||||||
AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
# These variables are only ever used when we cross-build to X86_WIN32.
|
|
||||||
# And we only support this with GCC, so...
|
|
||||||
if test x"$GCC" != x"no"; then
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
toolexecdir='$(exec_prefix)/$(target_alias)'
|
|
||||||
toolexeclibdir='$(toolexecdir)/lib'
|
|
||||||
else
|
|
||||||
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
|
|
||||||
toolexeclibdir='$(libdir)'
|
|
||||||
fi
|
|
||||||
multi_os_directory=`$CC -print-multi-os-directory`
|
|
||||||
case $multi_os_directory in
|
|
||||||
.) ;; # Avoid trailing /.
|
|
||||||
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
|
|
||||||
esac
|
|
||||||
AC_SUBST(toolexecdir)
|
|
||||||
AC_SUBST(toolexeclibdir)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "${multilib}" = "yes"; then
|
|
||||||
multilib_arg="--enable-multilib"
|
|
||||||
else
|
|
||||||
multilib_arg=
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
|
|
||||||
AC_CONFIG_COMMANDS(src, [
|
|
||||||
test -d src || mkdir src
|
|
||||||
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
|
||||||
], [TARGETDIR="$TARGETDIR"])
|
|
||||||
|
|
||||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
|
||||||
|
|
||||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
|
||||||
|
|
||||||
AC_OUTPUT
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
# Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; see the file COPYING3. If not see
|
|
||||||
# <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
proc load_gcc_lib { filename } {
|
|
||||||
global srcdir
|
|
||||||
load_file $srcdir/lib/$filename
|
|
||||||
}
|
|
||||||
|
|
||||||
load_lib dg.exp
|
|
||||||
load_lib libgloss.exp
|
|
||||||
load_gcc_lib target-libpath.exp
|
|
||||||
load_gcc_lib wrapper.exp
|
|
||||||
|
|
||||||
|
|
||||||
# Define libffi callbacks for dg.exp.
|
|
||||||
|
|
||||||
proc libffi-dg-test-1 { target_compile prog do_what extra_tool_flags } {
|
|
||||||
|
|
||||||
# To get all \n in dg-output test strings to match printf output
|
|
||||||
# in a system that outputs it as \015\012 (i.e. not just \012), we
|
|
||||||
# need to change all \n into \r?\n. As there is no dejagnu flag
|
|
||||||
# or hook to do that, we simply change the text being tested.
|
|
||||||
# Unfortunately, we have to know that the variable is called
|
|
||||||
# dg-output-text and lives in the caller of libffi-dg-test, which
|
|
||||||
# is two calls up. Overriding proc dg-output would be longer and
|
|
||||||
# would necessarily have the same assumption.
|
|
||||||
upvar 2 dg-output-text output_match
|
|
||||||
|
|
||||||
if { [llength $output_match] > 1 } {
|
|
||||||
regsub -all "\n" [lindex $output_match 1] "\r?\n" x
|
|
||||||
set output_match [lreplace $output_match 1 1 $x]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set up the compiler flags, based on what we're going to do.
|
|
||||||
|
|
||||||
set options [list]
|
|
||||||
switch $do_what {
|
|
||||||
"compile" {
|
|
||||||
set compile_type "assembly"
|
|
||||||
set output_file "[file rootname [file tail $prog]].s"
|
|
||||||
}
|
|
||||||
"link" {
|
|
||||||
set compile_type "executable"
|
|
||||||
set output_file "[file rootname [file tail $prog]].exe"
|
|
||||||
# The following line is needed for targets like the i960 where
|
|
||||||
# the default output file is b.out. Sigh.
|
|
||||||
}
|
|
||||||
"run" {
|
|
||||||
set compile_type "executable"
|
|
||||||
# FIXME: "./" is to cope with "." not being in $PATH.
|
|
||||||
# Should this be handled elsewhere?
|
|
||||||
# YES.
|
|
||||||
set output_file "./[file rootname [file tail $prog]].exe"
|
|
||||||
# This is the only place where we care if an executable was
|
|
||||||
# created or not. If it was, dg.exp will try to run it.
|
|
||||||
remote_file build delete $output_file;
|
|
||||||
}
|
|
||||||
default {
|
|
||||||
perror "$do_what: not a valid dg-do keyword"
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if { $extra_tool_flags != "" } {
|
|
||||||
lappend options "additional_flags=$extra_tool_flags"
|
|
||||||
}
|
|
||||||
|
|
||||||
set comp_output [libffi_target_compile "$prog" "$output_file" "$compile_type" $options];
|
|
||||||
|
|
||||||
|
|
||||||
return [list $comp_output $output_file]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
proc libffi-dg-test { prog do_what extra_tool_flags } {
|
|
||||||
return [libffi-dg-test-1 target_compile $prog $do_what $extra_tool_flags]
|
|
||||||
}
|
|
||||||
|
|
||||||
proc libffi-init { args } {
|
|
||||||
global gluefile wrap_flags;
|
|
||||||
global srcdir
|
|
||||||
global blddirffi
|
|
||||||
global objdir
|
|
||||||
global TOOL_OPTIONS
|
|
||||||
global tool
|
|
||||||
global libffi_include
|
|
||||||
global libffi_link_flags
|
|
||||||
global tool_root_dir
|
|
||||||
global ld_library_path
|
|
||||||
|
|
||||||
set blddirffi [pwd]/..
|
|
||||||
verbose "libffi $blddirffi"
|
|
||||||
|
|
||||||
set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a]
|
|
||||||
if {$gccdir != ""} {
|
|
||||||
set gccdir [file dirname $gccdir]
|
|
||||||
}
|
|
||||||
verbose "gccdir $gccdir"
|
|
||||||
|
|
||||||
set ld_library_path "."
|
|
||||||
append ld_library_path ":${gccdir}"
|
|
||||||
|
|
||||||
set compiler "${gccdir}/xgcc"
|
|
||||||
if { [is_remote host] == 0 && [which $compiler] != 0 } {
|
|
||||||
foreach i "[exec $compiler --print-multi-lib]" {
|
|
||||||
set mldir ""
|
|
||||||
regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir
|
|
||||||
set mldir [string trimright $mldir "\;@"]
|
|
||||||
if { "$mldir" == "." } {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } {
|
|
||||||
append ld_library_path ":${gccdir}/${mldir}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# add the library path for libffi.
|
|
||||||
append ld_library_path ":${blddirffi}/.libs"
|
|
||||||
|
|
||||||
verbose "ld_library_path: $ld_library_path"
|
|
||||||
|
|
||||||
# Point to the Libffi headers in libffi.
|
|
||||||
set libffi_include "${blddirffi}/include"
|
|
||||||
verbose "libffi_include $libffi_include"
|
|
||||||
|
|
||||||
set libffi_dir "${blddirffi}/.libs"
|
|
||||||
verbose "libffi_dir $libffi_dir"
|
|
||||||
if { $libffi_dir != "" } {
|
|
||||||
set libffi_dir [file dirname ${libffi_dir}]
|
|
||||||
set libffi_link_flags "-L${libffi_dir}/.libs"
|
|
||||||
}
|
|
||||||
|
|
||||||
set_ld_library_path_env_vars
|
|
||||||
libffi_maybe_build_wrapper "${objdir}/testglue.o"
|
|
||||||
}
|
|
||||||
|
|
||||||
proc libffi_exit { } {
|
|
||||||
global gluefile;
|
|
||||||
|
|
||||||
if [info exists gluefile] {
|
|
||||||
file_on_build delete $gluefile;
|
|
||||||
unset gluefile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc libffi_target_compile { source dest type options } {
|
|
||||||
global gluefile wrap_flags;
|
|
||||||
global srcdir
|
|
||||||
global blddirffi
|
|
||||||
global TOOL_OPTIONS
|
|
||||||
global libffi_link_flags
|
|
||||||
global libffi_include
|
|
||||||
global target_triplet
|
|
||||||
|
|
||||||
|
|
||||||
if { [target_info needs_status_wrapper]!="" && [info exists gluefile] } {
|
|
||||||
lappend options "libs=${gluefile}"
|
|
||||||
lappend options "ldflags=$wrap_flags"
|
|
||||||
}
|
|
||||||
|
|
||||||
# TOOL_OPTIONS must come first, so that it doesn't override testcase
|
|
||||||
# specific options.
|
|
||||||
if [info exists TOOL_OPTIONS] {
|
|
||||||
lappend options [concat "additional_flags=$TOOL_OPTIONS" $options];
|
|
||||||
}
|
|
||||||
|
|
||||||
# search for ffi_mips.h in srcdir, too
|
|
||||||
lappend options "additional_flags=-I${libffi_include} -I${srcdir}/../include -I${libffi_include}/.."
|
|
||||||
lappend options "additional_flags=${libffi_link_flags}"
|
|
||||||
|
|
||||||
# Darwin needs a stack execution allowed flag.
|
|
||||||
|
|
||||||
if { [istarget "*-*-darwin9*"] || [istarget "*-*-darwin1*"]
|
|
||||||
|| [istarget "*-*-darwin2*"] } {
|
|
||||||
lappend options "additional_flags=-Wl,-allow_stack_execute"
|
|
||||||
}
|
|
||||||
|
|
||||||
# If you're building the compiler with --prefix set to a place
|
|
||||||
# where it's not yet installed, then the linker won't be able to
|
|
||||||
# find the libgcc used by libffi.dylib. We could pass the
|
|
||||||
# -dylib_file option, but that's complicated, and it's much easier
|
|
||||||
# to just make the linker find libgcc using -L options.
|
|
||||||
if { [string match "*-*-darwin*" $target_triplet] } {
|
|
||||||
lappend options "libs= -shared-libgcc"
|
|
||||||
}
|
|
||||||
|
|
||||||
if { [string match "*-*-openbsd*" $target_triplet] } {
|
|
||||||
lappend options "libs= -lpthread"
|
|
||||||
}
|
|
||||||
|
|
||||||
lappend options "libs= -lffi"
|
|
||||||
|
|
||||||
verbose "options: $options"
|
|
||||||
return [target_compile $source $dest $type $options]
|
|
||||||
}
|
|
||||||
|
|
||||||
# Utility routines.
|
|
||||||
|
|
||||||
#
|
|
||||||
# search_for -- looks for a string match in a file
|
|
||||||
#
|
|
||||||
proc search_for { file pattern } {
|
|
||||||
set fd [open $file r]
|
|
||||||
while { [gets $fd cur_line]>=0 } {
|
|
||||||
if [string match "*$pattern*" $cur_line] then {
|
|
||||||
close $fd
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close $fd
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# Modified dg-runtest that can cycle through a list of optimization options
|
|
||||||
# as c-torture does.
|
|
||||||
proc libffi-dg-runtest { testcases default-extra-flags } {
|
|
||||||
global runtests
|
|
||||||
|
|
||||||
foreach test $testcases {
|
|
||||||
# If we're only testing specific files and this isn't one of
|
|
||||||
# them, skip it.
|
|
||||||
if ![runtest_file_p $runtests $test] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
# Look for a loop within the source code - if we don't find one,
|
|
||||||
# don't pass -funroll[-all]-loops.
|
|
||||||
global torture_with_loops torture_without_loops
|
|
||||||
if [expr [search_for $test "for*("]+[search_for $test "while*("]] {
|
|
||||||
set option_list $torture_with_loops
|
|
||||||
} else {
|
|
||||||
set option_list $torture_without_loops
|
|
||||||
}
|
|
||||||
|
|
||||||
set nshort [file tail [file dirname $test]]/[file tail $test]
|
|
||||||
|
|
||||||
foreach flags $option_list {
|
|
||||||
verbose "Testing $nshort, $flags" 1
|
|
||||||
dg-test $test $flags ${default-extra-flags}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Like check_conditional_xfail, but callable from a dg test.
|
|
||||||
|
|
||||||
proc dg-xfail-if { args } {
|
|
||||||
set args [lreplace $args 0 0]
|
|
||||||
set selector "target [join [lindex $args 1]]"
|
|
||||||
if { [dg-process-target $selector] == "S" } {
|
|
||||||
global compiler_conditional_xfail_data
|
|
||||||
set compiler_conditional_xfail_data $args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proc check-flags { args } {
|
|
||||||
|
|
||||||
# The args are within another list; pull them out.
|
|
||||||
set args [lindex $args 0]
|
|
||||||
|
|
||||||
# The next two arguments are optional. If they were not specified,
|
|
||||||
# use the defaults.
|
|
||||||
if { [llength $args] == 2 } {
|
|
||||||
lappend $args [list "*"]
|
|
||||||
}
|
|
||||||
if { [llength $args] == 3 } {
|
|
||||||
lappend $args [list ""]
|
|
||||||
}
|
|
||||||
|
|
||||||
# If the option strings are the defaults, or the same as the
|
|
||||||
# defaults, there is no need to call check_conditional_xfail to
|
|
||||||
# compare them to the actual options.
|
|
||||||
if { [string compare [lindex $args 2] "*"] == 0
|
|
||||||
&& [string compare [lindex $args 3] "" ] == 0 } {
|
|
||||||
set result 1
|
|
||||||
} else {
|
|
||||||
# The target list might be an effective-target keyword, so replace
|
|
||||||
# the original list with "*-*-*", since we already know it matches.
|
|
||||||
set result [check_conditional_xfail [lreplace $args 1 1 "*-*-*"]]
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result
|
|
||||||
}
|
|
||||||
|
|
||||||
proc dg-skip-if { args } {
|
|
||||||
# Verify the number of arguments. The last two are optional.
|
|
||||||
set args [lreplace $args 0 0]
|
|
||||||
if { [llength $args] < 2 || [llength $args] > 4 } {
|
|
||||||
error "dg-skip-if 2: need 2, 3, or 4 arguments"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Don't bother if we're already skipping the test.
|
|
||||||
upvar dg-do-what dg-do-what
|
|
||||||
if { [lindex ${dg-do-what} 1] == "N" } {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set selector [list target [lindex $args 1]]
|
|
||||||
if { [dg-process-target $selector] == "S" } {
|
|
||||||
if [check-flags $args] {
|
|
||||||
upvar dg-do-what dg-do-what
|
|
||||||
set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# We need to make sure that additional_files and additional_sources
|
|
||||||
# are both cleared out after every test. It is not enough to clear
|
|
||||||
# them out *before* the next test run because gcc-target-compile gets
|
|
||||||
# run directly from some .exp files (outside of any test). (Those
|
|
||||||
# uses should eventually be eliminated.)
|
|
||||||
|
|
||||||
# Because the DG framework doesn't provide a hook that is run at the
|
|
||||||
# end of a test, we must replace dg-test with a wrapper.
|
|
||||||
|
|
||||||
if { [info procs saved-dg-test] == [list] } {
|
|
||||||
rename dg-test saved-dg-test
|
|
||||||
|
|
||||||
proc dg-test { args } {
|
|
||||||
global additional_files
|
|
||||||
global additional_sources
|
|
||||||
global errorInfo
|
|
||||||
|
|
||||||
if { [ catch { eval saved-dg-test $args } errmsg ] } {
|
|
||||||
set saved_info $errorInfo
|
|
||||||
set additional_files ""
|
|
||||||
set additional_sources ""
|
|
||||||
error $errmsg $saved_info
|
|
||||||
}
|
|
||||||
set additional_files ""
|
|
||||||
set additional_sources ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Local Variables:
|
|
||||||
# tcl-indent-level:4
|
|
||||||
# End:
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,457 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------*-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
|
|
||||||
|
|
||||||
/* Need minimal decorations for DLLs to works on Windows. */
|
|
||||||
/* GCC has autoimport and autoexport. Rely on Libtool to */
|
|
||||||
/* help MSVC export from a DLL, but always declare data */
|
|
||||||
/* to be imported for MSVC clients. This costs an extra */
|
|
||||||
/* indirection for MSVC clients using the static version */
|
|
||||||
/* of the library, but don't worry about that. Besides, */
|
|
||||||
/* as a workaround, they can define FFI_BUILDING if they */
|
|
||||||
/* *know* they are going to link with the static library. */
|
|
||||||
#if defined _MSC_VER && !defined FFI_BUILDING
|
|
||||||
#define FFI_EXTERN extern __declspec(dllimport)
|
|
||||||
#else
|
|
||||||
#define FFI_EXTERN extern
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* These are defined in types.c */
|
|
||||||
FFI_EXTERN ffi_type ffi_type_void;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_uint8;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_sint8;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_uint16;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_sint16;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_uint32;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_sint32;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_uint64;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_sint64;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_float;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_double;
|
|
||||||
FFI_EXTERN ffi_type ffi_type_pointer;
|
|
||||||
|
|
||||||
#if @HAVE_LONG_DOUBLE@
|
|
||||||
FFI_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
|
|
||||||
@@ -1,505 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
|
|
||||||
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
|
|
||||||
|
|
||||||
ARM 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.
|
|
||||||
----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#define LIBFFI_ASM
|
|
||||||
#include <fficonfig.h>
|
|
||||||
#include <ffi.h>
|
|
||||||
#ifdef HAVE_MACHINE_ASM_H
|
|
||||||
#include <machine/asm.h>
|
|
||||||
#else
|
|
||||||
#ifdef __USER_LABEL_PREFIX__
|
|
||||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
|
||||||
#define CONCAT2(a, b) a ## b
|
|
||||||
|
|
||||||
/* Use the right prefix for global labels. */
|
|
||||||
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
|
||||||
#else
|
|
||||||
#define CNAME(x) x
|
|
||||||
#endif
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#define ENTRY(x) .globl CNAME(x); CNAME(x):
|
|
||||||
#else
|
|
||||||
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
|
||||||
#endif /* __APPLE__ */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __ELF__
|
|
||||||
#define LSYM(x) .x
|
|
||||||
#else
|
|
||||||
#define LSYM(x) x
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Use the SOFTFP return value ABI on Mac OS X, as per the iOS ABI
|
|
||||||
Function Call Guide */
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#define __SOFTFP__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We need a better way of testing for this, but for now, this is all
|
|
||||||
we can do. */
|
|
||||||
@ This selects the minimum architecture level required.
|
|
||||||
#define __ARM_ARCH__ 3
|
|
||||||
|
|
||||||
#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
|
||||||
# undef __ARM_ARCH__
|
|
||||||
# define __ARM_ARCH__ 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|
|
||||||
|| defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
|
|
||||||
|| defined(__ARM_ARCH_5TEJ__)
|
|
||||||
# undef __ARM_ARCH__
|
|
||||||
# define __ARM_ARCH__ 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
|
|
||||||
|| defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
|
|
||||||
|| defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
|
|
||||||
|| defined(__ARM_ARCH_6M__)
|
|
||||||
# undef __ARM_ARCH__
|
|
||||||
# define __ARM_ARCH__ 6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
|
|
||||||
|| defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
|
|
||||||
|| defined(__ARM_ARCH_7EM__)
|
|
||||||
# undef __ARM_ARCH__
|
|
||||||
# define __ARM_ARCH__ 7
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __ARM_ARCH__ >= 5
|
|
||||||
# define call_reg(x) blx x
|
|
||||||
#elif defined (__ARM_ARCH_4T__)
|
|
||||||
# define call_reg(x) mov lr, pc ; bx x
|
|
||||||
# if defined(__thumb__) || defined(__THUMB_INTERWORK__)
|
|
||||||
# define __INTERWORKING__
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define call_reg(x) mov lr, pc ; mov pc, x
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Conditionally compile unwinder directives. */
|
|
||||||
#ifdef __ARM_EABI__
|
|
||||||
#define UNWIND
|
|
||||||
#else
|
|
||||||
#define UNWIND @
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
|
|
||||||
.macro ARM_FUNC_START name
|
|
||||||
.text
|
|
||||||
.align 0
|
|
||||||
.thumb
|
|
||||||
.thumb_func
|
|
||||||
#ifdef __APPLE__
|
|
||||||
ENTRY($0)
|
|
||||||
#else
|
|
||||||
ENTRY(\name)
|
|
||||||
#endif
|
|
||||||
bx pc
|
|
||||||
nop
|
|
||||||
.arm
|
|
||||||
UNWIND .fnstart
|
|
||||||
/* A hook to tell gdb that we've switched to ARM mode. Also used to call
|
|
||||||
directly from other local arm routines. */
|
|
||||||
#ifdef __APPLE__
|
|
||||||
_L__$0:
|
|
||||||
#else
|
|
||||||
_L__\name:
|
|
||||||
#endif
|
|
||||||
.endm
|
|
||||||
#else
|
|
||||||
.macro ARM_FUNC_START name
|
|
||||||
.text
|
|
||||||
.align 0
|
|
||||||
.arm
|
|
||||||
#ifdef __APPLE__
|
|
||||||
ENTRY($0)
|
|
||||||
#else
|
|
||||||
ENTRY(\name)
|
|
||||||
#endif
|
|
||||||
UNWIND .fnstart
|
|
||||||
.endm
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.macro RETLDM regs=, cond=, dirn=ia
|
|
||||||
#if defined (__INTERWORKING__)
|
|
||||||
.ifc "\regs",""
|
|
||||||
ldr\cond lr, [sp], #4
|
|
||||||
.else
|
|
||||||
ldm\cond\dirn sp!, {\regs, lr}
|
|
||||||
.endif
|
|
||||||
bx\cond lr
|
|
||||||
#else
|
|
||||||
.ifc "\regs",""
|
|
||||||
ldr\cond pc, [sp], #4
|
|
||||||
.else
|
|
||||||
ldm\cond\dirn sp!, {\regs, pc}
|
|
||||||
.endif
|
|
||||||
#endif
|
|
||||||
.endm
|
|
||||||
|
|
||||||
@ r0: ffi_prep_args
|
|
||||||
@ r1: &ecif
|
|
||||||
@ r2: cif->bytes
|
|
||||||
@ r3: fig->flags
|
|
||||||
@ sp+0: ecif.rvalue
|
|
||||||
|
|
||||||
@ This assumes we are using gas.
|
|
||||||
ARM_FUNC_START ffi_call_SYSV
|
|
||||||
@ Save registers
|
|
||||||
stmfd sp!, {r0-r3, fp, lr}
|
|
||||||
UNWIND .save {r0-r3, fp, lr}
|
|
||||||
mov fp, sp
|
|
||||||
|
|
||||||
UNWIND .setfp fp, sp
|
|
||||||
|
|
||||||
@ Make room for all of the new args.
|
|
||||||
sub sp, fp, r2
|
|
||||||
|
|
||||||
@ Place all of the ffi_prep_args in position
|
|
||||||
mov r0, sp
|
|
||||||
@ r1 already set
|
|
||||||
|
|
||||||
@ Call ffi_prep_args(stack, &ecif)
|
|
||||||
bl ffi_prep_args
|
|
||||||
|
|
||||||
@ move first 4 parameters in registers
|
|
||||||
ldmia sp, {r0-r3}
|
|
||||||
|
|
||||||
@ and adjust stack
|
|
||||||
sub lr, fp, sp @ cif->bytes == fp - sp
|
|
||||||
ldr ip, [fp] @ load fn() in advance
|
|
||||||
cmp lr, #16
|
|
||||||
movhs lr, #16
|
|
||||||
add sp, sp, lr
|
|
||||||
|
|
||||||
@ call (fn) (...)
|
|
||||||
call_reg(ip)
|
|
||||||
|
|
||||||
@ Remove the space we pushed for the args
|
|
||||||
mov sp, fp
|
|
||||||
|
|
||||||
@ Load r2 with the pointer to storage for the return value
|
|
||||||
ldr r2, [sp, #24]
|
|
||||||
|
|
||||||
@ Load r3 with the return type code
|
|
||||||
ldr r3, [sp, #12]
|
|
||||||
|
|
||||||
@ If the return value pointer is NULL, assume no return value.
|
|
||||||
cmp r2, #0
|
|
||||||
beq LSYM(Lepilogue)
|
|
||||||
|
|
||||||
@ return INT
|
|
||||||
cmp r3, #FFI_TYPE_INT
|
|
||||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
|
||||||
cmpne r3, #FFI_TYPE_FLOAT
|
|
||||||
#endif
|
|
||||||
streq r0, [r2]
|
|
||||||
beq LSYM(Lepilogue)
|
|
||||||
|
|
||||||
@ return INT64
|
|
||||||
cmp r3, #FFI_TYPE_SINT64
|
|
||||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
|
||||||
cmpne r3, #FFI_TYPE_DOUBLE
|
|
||||||
#endif
|
|
||||||
stmeqia r2, {r0, r1}
|
|
||||||
|
|
||||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
|
||||||
beq LSYM(Lepilogue)
|
|
||||||
|
|
||||||
@ return FLOAT
|
|
||||||
cmp r3, #FFI_TYPE_FLOAT
|
|
||||||
stfeqs f0, [r2]
|
|
||||||
beq LSYM(Lepilogue)
|
|
||||||
|
|
||||||
@ return DOUBLE or LONGDOUBLE
|
|
||||||
cmp r3, #FFI_TYPE_DOUBLE
|
|
||||||
stfeqd f0, [r2]
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LSYM(Lepilogue):
|
|
||||||
#if defined (__INTERWORKING__)
|
|
||||||
ldmia sp!, {r0-r3,fp, lr}
|
|
||||||
bx lr
|
|
||||||
#else
|
|
||||||
ldmia sp!, {r0-r3,fp, pc}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.ffi_call_SYSV_end:
|
|
||||||
UNWIND .fnend
|
|
||||||
#ifdef __ELF__
|
|
||||||
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
unsigned int FFI_HIDDEN
|
|
||||||
ffi_closure_SYSV_inner (closure, respp, args)
|
|
||||||
ffi_closure *closure;
|
|
||||||
void **respp;
|
|
||||||
void *args;
|
|
||||||
*/
|
|
||||||
|
|
||||||
ARM_FUNC_START ffi_closure_SYSV
|
|
||||||
UNWIND .pad #16
|
|
||||||
add ip, sp, #16
|
|
||||||
stmfd sp!, {ip, lr}
|
|
||||||
UNWIND .save {r0, lr}
|
|
||||||
add r2, sp, #8
|
|
||||||
UNWIND .pad #16
|
|
||||||
sub sp, sp, #16
|
|
||||||
str sp, [sp, #8]
|
|
||||||
add r1, sp, #8
|
|
||||||
bl CNAME(ffi_closure_SYSV_inner)
|
|
||||||
cmp r0, #FFI_TYPE_INT
|
|
||||||
beq .Lretint
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_FLOAT
|
|
||||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
|
||||||
beq .Lretint
|
|
||||||
#else
|
|
||||||
beq .Lretfloat
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_DOUBLE
|
|
||||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
|
||||||
beq .Lretlonglong
|
|
||||||
#else
|
|
||||||
beq .Lretdouble
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_LONGDOUBLE
|
|
||||||
#if defined(__SOFTFP__) || defined(__ARM_EABI__)
|
|
||||||
beq .Lretlonglong
|
|
||||||
#else
|
|
||||||
beq .Lretlongdouble
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_SINT64
|
|
||||||
beq .Lretlonglong
|
|
||||||
.Lclosure_epilogue:
|
|
||||||
add sp, sp, #16
|
|
||||||
ldmfd sp, {sp, pc}
|
|
||||||
.Lretint:
|
|
||||||
ldr r0, [sp]
|
|
||||||
b .Lclosure_epilogue
|
|
||||||
.Lretlonglong:
|
|
||||||
ldr r0, [sp]
|
|
||||||
ldr r1, [sp, #4]
|
|
||||||
b .Lclosure_epilogue
|
|
||||||
|
|
||||||
#if !defined(__SOFTFP__) && !defined(__ARM_EABI__)
|
|
||||||
.Lretfloat:
|
|
||||||
ldfs f0, [sp]
|
|
||||||
b .Lclosure_epilogue
|
|
||||||
.Lretdouble:
|
|
||||||
ldfd f0, [sp]
|
|
||||||
b .Lclosure_epilogue
|
|
||||||
.Lretlongdouble:
|
|
||||||
ldfd f0, [sp]
|
|
||||||
b .Lclosure_epilogue
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.ffi_closure_SYSV_end:
|
|
||||||
UNWIND .fnend
|
|
||||||
#ifdef __ELF__
|
|
||||||
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Below are VFP hard-float ABI call and closure implementations.
|
|
||||||
Add VFP FPU directive here. This is only compiled into the library
|
|
||||||
under EABI. */
|
|
||||||
#ifdef __ARM_EABI__
|
|
||||||
.fpu vfp
|
|
||||||
|
|
||||||
@ r0: fn
|
|
||||||
@ r1: &ecif
|
|
||||||
@ r2: cif->bytes
|
|
||||||
@ r3: fig->flags
|
|
||||||
@ sp+0: ecif.rvalue
|
|
||||||
|
|
||||||
ARM_FUNC_START ffi_call_VFP
|
|
||||||
@ Save registers
|
|
||||||
stmfd sp!, {r0-r3, fp, lr}
|
|
||||||
UNWIND .save {r0-r3, fp, lr}
|
|
||||||
mov fp, sp
|
|
||||||
UNWIND .setfp fp, sp
|
|
||||||
|
|
||||||
@ Make room for all of the new args.
|
|
||||||
sub sp, sp, r2
|
|
||||||
|
|
||||||
@ Make room for loading VFP args
|
|
||||||
sub sp, sp, #64
|
|
||||||
|
|
||||||
@ Place all of the ffi_prep_args in position
|
|
||||||
mov r0, sp
|
|
||||||
@ r1 already set
|
|
||||||
sub r2, fp, #64 @ VFP scratch space
|
|
||||||
|
|
||||||
@ Call ffi_prep_args(stack, &ecif, vfp_space)
|
|
||||||
bl ffi_prep_args
|
|
||||||
|
|
||||||
@ Load VFP register args if needed
|
|
||||||
cmp r0, #0
|
|
||||||
beq LSYM(Lbase_args)
|
|
||||||
|
|
||||||
@ Load only d0 if possible
|
|
||||||
cmp r0, #3
|
|
||||||
sub ip, fp, #64
|
|
||||||
flddle d0, [ip]
|
|
||||||
fldmiadgt ip, {d0-d7}
|
|
||||||
|
|
||||||
LSYM(Lbase_args):
|
|
||||||
@ move first 4 parameters in registers
|
|
||||||
ldmia sp, {r0-r3}
|
|
||||||
|
|
||||||
@ and adjust stack
|
|
||||||
sub lr, ip, sp @ cif->bytes == (fp - 64) - sp
|
|
||||||
ldr ip, [fp] @ load fn() in advance
|
|
||||||
cmp lr, #16
|
|
||||||
movhs lr, #16
|
|
||||||
add sp, sp, lr
|
|
||||||
|
|
||||||
@ call (fn) (...)
|
|
||||||
call_reg(ip)
|
|
||||||
|
|
||||||
@ Remove the space we pushed for the args
|
|
||||||
mov sp, fp
|
|
||||||
|
|
||||||
@ Load r2 with the pointer to storage for
|
|
||||||
@ the return value
|
|
||||||
ldr r2, [sp, #24]
|
|
||||||
|
|
||||||
@ Load r3 with the return type code
|
|
||||||
ldr r3, [sp, #12]
|
|
||||||
|
|
||||||
@ If the return value pointer is NULL,
|
|
||||||
@ assume no return value.
|
|
||||||
cmp r2, #0
|
|
||||||
beq LSYM(Lepilogue_vfp)
|
|
||||||
|
|
||||||
cmp r3, #FFI_TYPE_INT
|
|
||||||
streq r0, [r2]
|
|
||||||
beq LSYM(Lepilogue_vfp)
|
|
||||||
|
|
||||||
cmp r3, #FFI_TYPE_SINT64
|
|
||||||
stmeqia r2, {r0, r1}
|
|
||||||
beq LSYM(Lepilogue_vfp)
|
|
||||||
|
|
||||||
cmp r3, #FFI_TYPE_FLOAT
|
|
||||||
fstseq s0, [r2]
|
|
||||||
beq LSYM(Lepilogue_vfp)
|
|
||||||
|
|
||||||
cmp r3, #FFI_TYPE_DOUBLE
|
|
||||||
fstdeq d0, [r2]
|
|
||||||
beq LSYM(Lepilogue_vfp)
|
|
||||||
|
|
||||||
cmp r3, #FFI_TYPE_STRUCT_VFP_FLOAT
|
|
||||||
cmpne r3, #FFI_TYPE_STRUCT_VFP_DOUBLE
|
|
||||||
fstmiadeq r2, {d0-d3}
|
|
||||||
|
|
||||||
LSYM(Lepilogue_vfp):
|
|
||||||
RETLDM "r0-r3,fp"
|
|
||||||
|
|
||||||
.ffi_call_VFP_end:
|
|
||||||
UNWIND .fnend
|
|
||||||
.size CNAME(ffi_call_VFP),.ffi_call_VFP_end-CNAME(ffi_call_VFP)
|
|
||||||
|
|
||||||
|
|
||||||
ARM_FUNC_START ffi_closure_VFP
|
|
||||||
fstmfdd sp!, {d0-d7}
|
|
||||||
@ r0-r3, then d0-d7
|
|
||||||
UNWIND .pad #80
|
|
||||||
add ip, sp, #80
|
|
||||||
stmfd sp!, {ip, lr}
|
|
||||||
UNWIND .save {r0, lr}
|
|
||||||
add r2, sp, #72
|
|
||||||
add r3, sp, #8
|
|
||||||
UNWIND .pad #72
|
|
||||||
sub sp, sp, #72
|
|
||||||
str sp, [sp, #64]
|
|
||||||
add r1, sp, #64
|
|
||||||
bl ffi_closure_SYSV_inner
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_INT
|
|
||||||
beq .Lretint_vfp
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_FLOAT
|
|
||||||
beq .Lretfloat_vfp
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_DOUBLE
|
|
||||||
cmpne r0, #FFI_TYPE_LONGDOUBLE
|
|
||||||
beq .Lretdouble_vfp
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_SINT64
|
|
||||||
beq .Lretlonglong_vfp
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_STRUCT_VFP_FLOAT
|
|
||||||
beq .Lretfloat_struct_vfp
|
|
||||||
|
|
||||||
cmp r0, #FFI_TYPE_STRUCT_VFP_DOUBLE
|
|
||||||
beq .Lretdouble_struct_vfp
|
|
||||||
|
|
||||||
.Lclosure_epilogue_vfp:
|
|
||||||
add sp, sp, #72
|
|
||||||
ldmfd sp, {sp, pc}
|
|
||||||
|
|
||||||
.Lretfloat_vfp:
|
|
||||||
flds s0, [sp]
|
|
||||||
b .Lclosure_epilogue_vfp
|
|
||||||
.Lretdouble_vfp:
|
|
||||||
fldd d0, [sp]
|
|
||||||
b .Lclosure_epilogue_vfp
|
|
||||||
.Lretint_vfp:
|
|
||||||
ldr r0, [sp]
|
|
||||||
b .Lclosure_epilogue_vfp
|
|
||||||
.Lretlonglong_vfp:
|
|
||||||
ldmia sp, {r0, r1}
|
|
||||||
b .Lclosure_epilogue_vfp
|
|
||||||
.Lretfloat_struct_vfp:
|
|
||||||
fldmiad sp, {d0-d1}
|
|
||||||
b .Lclosure_epilogue_vfp
|
|
||||||
.Lretdouble_struct_vfp:
|
|
||||||
fldmiad sp, {d0-d3}
|
|
||||||
b .Lclosure_epilogue_vfp
|
|
||||||
|
|
||||||
.ffi_closure_VFP_end:
|
|
||||||
UNWIND .fnend
|
|
||||||
.size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ENTRY(ffi_arm_trampoline)
|
|
||||||
stmfd sp!, {r0-r3}
|
|
||||||
ldr r0, [pc]
|
|
||||||
ldr pc, [pc]
|
|
||||||
|
|
||||||
#if defined __ELF__ && defined __linux__
|
|
||||||
.section .note.GNU-stack,"",%progbits
|
|
||||||
#endif
|
|
||||||
@@ -1,841 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|| ecif->cif->flags == FFI_TYPE_MS_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
|
|
||||||
{
|
|
||||||
if (cif->abi == FFI_MS_CDECL)
|
|
||||||
cif->flags = FFI_TYPE_MS_STRUCT;
|
|
||||||
else
|
|
||||||
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
|
|
||||||
|| cif->flags == FFI_TYPE_MS_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:
|
|
||||||
case FFI_MS_CDECL:
|
|
||||||
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
|
|
||||||
|| cif->flags == FFI_TYPE_MS_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);
|
|
||||||
}
|
|
||||||
else if (cif->abi == FFI_MS_CDECL)
|
|
||||||
{
|
|
||||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0],
|
|
||||||
&ffi_closure_SYSV,
|
|
||||||
(void*)codeloc);
|
|
||||||
}
|
|
||||||
#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->flags == FFI_TYPE_STRUCT
|
|
||||||
|| cif->flags == FFI_TYPE_MS_STRUCT))
|
|
||||||
{
|
|
||||||
ecif.rvalue = alloca(cif->rtype->size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ecif.rvalue = rvalue;
|
|
||||||
|
|
||||||
|
|
||||||
switch (cif->abi)
|
|
||||||
{
|
|
||||||
#ifdef X86_WIN32
|
|
||||||
case FFI_SYSV:
|
|
||||||
case FFI_STDCALL:
|
|
||||||
case FFI_MS_CDECL:
|
|
||||||
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 */
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
stand-alone
|
|
||||||
aix-fix
|
|
||||||
mint
|
|
||||||
win32
|
|
||||||
win32_tests
|
|
||||||
vararg_float_test_fix
|
|
||||||
vfp-eabi
|
|
||||||
msvc-changes
|
|
||||||
win32-return-sign
|
|
||||||
apple-fixes
|
|
||||||
dist-tests
|
|
||||||
icc128
|
|
||||||
x32libtool
|
|
||||||
arm-test-fix
|
|
||||||
xcode
|
|
||||||
darwin-missing-semi
|
|
||||||
xcode-improvements
|
|
||||||
update-disty
|
|
||||||
v3_0_11
|
|
||||||
bfin
|
|
||||||
ios-fix
|
|
||||||
mingw-check-fix
|
|
||||||
whitespace-fix
|
|
||||||
tile
|
|
||||||
aarch64
|
|
||||||
darwin12
|
|
||||||
emutramp
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/* Area: ffi_call, closure_call
|
|
||||||
Purpose: Test doubles passed in variable argument lists.
|
|
||||||
Limitations: none.
|
|
||||||
PR: none.
|
|
||||||
Originator: Blake Chaffin 6/6/2007 */
|
|
||||||
|
|
||||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
|
||||||
/* { dg-output "" { xfail avr32*-*-* } } */
|
|
||||||
/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */
|
|
||||||
/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */
|
|
||||||
|
|
||||||
#include "ffitest.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
cls_double_va_fn(ffi_cif* cif __UNUSED__, void* resp,
|
|
||||||
void** args, void* userdata __UNUSED__)
|
|
||||||
{
|
|
||||||
char* format = *(char**)args[0];
|
|
||||||
double doubleValue = *(double*)args[1];
|
|
||||||
|
|
||||||
*(ffi_arg*)resp = printf(format, doubleValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main (void)
|
|
||||||
{
|
|
||||||
ffi_cif cif;
|
|
||||||
void *code;
|
|
||||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
|
||||||
void* args[3];
|
|
||||||
ffi_type* arg_types[3];
|
|
||||||
|
|
||||||
char* format = "%.1f\n";
|
|
||||||
double doubleArg = 7;
|
|
||||||
ffi_arg res = 0;
|
|
||||||
|
|
||||||
arg_types[0] = &ffi_type_pointer;
|
|
||||||
arg_types[1] = &ffi_type_double;
|
|
||||||
arg_types[2] = NULL;
|
|
||||||
|
|
||||||
/* This printf call is variadic */
|
|
||||||
CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
|
|
||||||
arg_types) == FFI_OK);
|
|
||||||
|
|
||||||
args[0] = &format;
|
|
||||||
args[1] = &doubleArg;
|
|
||||||
args[2] = NULL;
|
|
||||||
|
|
||||||
ffi_call(&cif, FFI_FN(printf), &res, args);
|
|
||||||
// { dg-output "7.0" }
|
|
||||||
printf("res: %d\n", (int) res);
|
|
||||||
// { dg-output "\nres: 4" }
|
|
||||||
|
|
||||||
/* The call to cls_double_va_fn is static, so have to use a normal prep_cif */
|
|
||||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint, arg_types) == FFI_OK);
|
|
||||||
|
|
||||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, code) == FFI_OK);
|
|
||||||
|
|
||||||
res = ((int(*)(char*, double))(code))(format, doubleArg);
|
|
||||||
// { dg-output "\n7.0" }
|
|
||||||
printf("res: %d\n", (int) res);
|
|
||||||
// { dg-output "\nres: 4" }
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/* Area: ffi_call, closure_call
|
|
||||||
Purpose: Test long doubles passed in variable argument lists.
|
|
||||||
Limitations: none.
|
|
||||||
PR: none.
|
|
||||||
Originator: Blake Chaffin 6/6/2007 */
|
|
||||||
|
|
||||||
/* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */
|
|
||||||
/* { dg-output "" { xfail avr32*-*-* x86_64-*-mingw* } } */
|
|
||||||
/* { dg-output "" { xfail mips-sgi-irix6* } } PR libffi/46660 */
|
|
||||||
/* { dg-skip-if "" arm*-*-* { "-mfloat-abi=hard" } { "" } } */
|
|
||||||
|
|
||||||
#include "ffitest.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
cls_longdouble_va_fn(ffi_cif* cif __UNUSED__, void* resp,
|
|
||||||
void** args, void* userdata __UNUSED__)
|
|
||||||
{
|
|
||||||
char* format = *(char**)args[0];
|
|
||||||
long double ldValue = *(long double*)args[1];
|
|
||||||
|
|
||||||
*(ffi_arg*)resp = printf(format, ldValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main (void)
|
|
||||||
{
|
|
||||||
ffi_cif cif;
|
|
||||||
void *code;
|
|
||||||
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
|
|
||||||
void* args[3];
|
|
||||||
ffi_type* arg_types[3];
|
|
||||||
|
|
||||||
char* format = "%.1Lf\n";
|
|
||||||
long double ldArg = 7;
|
|
||||||
ffi_arg res = 0;
|
|
||||||
|
|
||||||
arg_types[0] = &ffi_type_pointer;
|
|
||||||
arg_types[1] = &ffi_type_longdouble;
|
|
||||||
arg_types[2] = NULL;
|
|
||||||
|
|
||||||
/* This printf call is variadic */
|
|
||||||
CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2, &ffi_type_sint,
|
|
||||||
arg_types) == FFI_OK);
|
|
||||||
|
|
||||||
args[0] = &format;
|
|
||||||
args[1] = &ldArg;
|
|
||||||
args[2] = NULL;
|
|
||||||
|
|
||||||
ffi_call(&cif, FFI_FN(printf), &res, args);
|
|
||||||
// { dg-output "7.0" }
|
|
||||||
printf("res: %d\n", (int) res);
|
|
||||||
// { dg-output "\nres: 4" }
|
|
||||||
|
|
||||||
/* The call to cls_longdouble_va_fn is static, so have to use a normal prep_cif */
|
|
||||||
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
|
|
||||||
arg_types) == FFI_OK);
|
|
||||||
|
|
||||||
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, code) == FFI_OK);
|
|
||||||
|
|
||||||
res = ((int(*)(char*, long double))(code))(format, ldArg);
|
|
||||||
// { dg-output "\n7.0" }
|
|
||||||
printf("res: %d\n", (int) res);
|
|
||||||
// { dg-output "\nres: 4" }
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
5097
.pc/bfin/ChangeLog
5097
.pc/bfin/ChangeLog
File diff suppressed because it is too large
Load Diff
@@ -1,205 +0,0 @@
|
|||||||
## 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 \
|
|
||||||
m4/ltversion.m4 src/arm/gentramp.sh src/debug.c \
|
|
||||||
msvcc.sh generate-ios-source-and-headers.py \
|
|
||||||
generate-osx-source-and-headers.py \
|
|
||||||
libffi.xcodeproj/project.pbxproj \
|
|
||||||
src/arm/trampoline.S
|
|
||||||
|
|
||||||
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 -DFFI_BUILDING
|
|
||||||
AM_CCASFLAGS = $(AM_CPPFLAGS) -g
|
|
||||||
|
|
||||||
# No install-html or install-pdf support in automake yet
|
|
||||||
.PHONY: install-html install-pdf
|
|
||||||
install-html:
|
|
||||||
install-pdf:
|
|
||||||
1912
.pc/bfin/Makefile.in
1912
.pc/bfin/Makefile.in
File diff suppressed because it is too large
Load Diff
359
.pc/bfin/README
359
.pc/bfin/README
@@ -1,359 +0,0 @@
|
|||||||
Status
|
|
||||||
======
|
|
||||||
|
|
||||||
libffi-3.0.12 was released on *****************. Check the libffi web
|
|
||||||
page for updates: <URL:http://sourceware.org/libffi/>.
|
|
||||||
|
|
||||||
|
|
||||||
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 essentially 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Supported Platforms
|
|
||||||
===================
|
|
||||||
|
|
||||||
Libffi has been ported to many different platforms.
|
|
||||||
For specific configuration details and testing status, please
|
|
||||||
refer to the wiki page here:
|
|
||||||
|
|
||||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
|
|
||||||
|
|
||||||
At the time of release, the following basic configurations have been
|
|
||||||
tested:
|
|
||||||
|
|
||||||
|--------------+------------------|
|
|
||||||
| Architecture | Operating System |
|
|
||||||
|--------------+------------------|
|
|
||||||
| Alpha | Linux |
|
|
||||||
| Alpha | Tru64 |
|
|
||||||
| ARM | Linux |
|
|
||||||
| ARM | iOS |
|
|
||||||
| AVR32 | Linux |
|
|
||||||
| HPPA | HPUX |
|
|
||||||
| IA-64 | Linux |
|
|
||||||
| M68K | FreeMiNT |
|
|
||||||
| M68K | RTEMS |
|
|
||||||
| MIPS | IRIX |
|
|
||||||
| MIPS | Linux |
|
|
||||||
| MIPS | RTEMS |
|
|
||||||
| MIPS64 | Linux |
|
|
||||||
| PowerPC | AMIGA |
|
|
||||||
| PowerPC | Linux |
|
|
||||||
| PowerPC | Mac OSX |
|
|
||||||
| PowerPC | FreeBSD |
|
|
||||||
| PowerPC64 | Linux |
|
|
||||||
| S390 | Linux |
|
|
||||||
| S390X | Linux |
|
|
||||||
| SPARC | Linux |
|
|
||||||
| SPARC | Solaris |
|
|
||||||
| SPARC64 | Linux |
|
|
||||||
| SPARC64 | FreeBSD |
|
|
||||||
| X86 | FreeBSD |
|
|
||||||
| X86 | Interix |
|
|
||||||
| X86 | kFreeBSD |
|
|
||||||
| X86 | Linux |
|
|
||||||
| X86 | Mac OSX |
|
|
||||||
| X86 | OpenBSD |
|
|
||||||
| X86 | OS/2 |
|
|
||||||
| X86 | Solaris |
|
|
||||||
| X86 | Windows/Cygwin |
|
|
||||||
| X86 | Windows/MingW |
|
|
||||||
| X86-64 | FreeBSD |
|
|
||||||
| X86-64 | Linux |
|
|
||||||
| X86-64 | Linux/x32 |
|
|
||||||
| X86-64 | OpenBSD |
|
|
||||||
| X86-64 | Windows/MingW |
|
|
||||||
|--------------+------------------|
|
|
||||||
|
|
||||||
Please send additional platform test results to
|
|
||||||
libffi-discuss@sourceware.org and feel free to update the wiki page
|
|
||||||
above.
|
|
||||||
|
|
||||||
Installing libffi
|
|
||||||
=================
|
|
||||||
|
|
||||||
First you must configure the distribution for your particular
|
|
||||||
system. Go to the directory you wish to build libffi in and run the
|
|
||||||
"configure" program found in the root directory of the libffi source
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
You may want to tell configure where to install the libffi library and
|
|
||||||
header files. To do that, use the --prefix configure switch. Libffi
|
|
||||||
will install under /usr/local by default.
|
|
||||||
|
|
||||||
If you want to enable extra run-time debugging checks use the the
|
|
||||||
--enable-debug configure switch. This is useful when your program dies
|
|
||||||
mysteriously while using libffi.
|
|
||||||
|
|
||||||
Another useful configure switch is --enable-purify-safety. Using this
|
|
||||||
will add some extra code which will suppress certain warnings when you
|
|
||||||
are using Purify with libffi. Only use this switch when using
|
|
||||||
Purify, as it will slow down the library.
|
|
||||||
|
|
||||||
It's also possible to build libffi on Windows platforms with
|
|
||||||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
|
||||||
wrapper script during configuration like so:
|
|
||||||
|
|
||||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
|
||||||
|
|
||||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
|
||||||
You may also need to specify --build appropriately. When building with MSVC
|
|
||||||
under a MingW environment, you may need to remove the line in configure
|
|
||||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
|
||||||
present in MingW, and is not required when using MingW-style paths.)
|
|
||||||
|
|
||||||
For iOS builds, run generate-ios-source-and-headers.py and then
|
|
||||||
libffi.xcodeproj should work.
|
|
||||||
|
|
||||||
Configure has many other options. Use "configure --help" to see them all.
|
|
||||||
|
|
||||||
Once configure has finished, type "make". Note that you must be using
|
|
||||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
|
||||||
|
|
||||||
To ensure that libffi is working as advertised, type "make check".
|
|
||||||
This will require that you have DejaGNU installed.
|
|
||||||
|
|
||||||
To install the library and header files, type "make install".
|
|
||||||
|
|
||||||
|
|
||||||
History
|
|
||||||
=======
|
|
||||||
|
|
||||||
See the ChangeLog files for details.
|
|
||||||
|
|
||||||
3.0.11 MMM-DD-YY
|
|
||||||
Lots of build fixes.
|
|
||||||
Add Amiga newer MacOS support.
|
|
||||||
Add support for variadic functions (ffi_prep_cif_var).
|
|
||||||
Add Linux/x32 support.
|
|
||||||
Add thiscall, fastcall and MSVC cdecl support on Windows.
|
|
||||||
Add Amiga and newer MacOS support.
|
|
||||||
Add m68k FreeMiNT support.
|
|
||||||
Integration with iOS' xcode build tools.
|
|
||||||
Fix Octeon and MC68881 support.
|
|
||||||
Fix code pessimizations.
|
|
||||||
Lots of build fixes.
|
|
||||||
|
|
||||||
3.0.10 Aug-23-11
|
|
||||||
Add support for Apple's iOS.
|
|
||||||
Add support for ARM VFP ABI.
|
|
||||||
Add RTEMS support for MIPS and M68K.
|
|
||||||
Fix instruction cache clearing problems on
|
|
||||||
ARM and SPARC.
|
|
||||||
Fix the N64 build on mips-sgi-irix6.5.
|
|
||||||
Enable builds with Microsoft's compiler.
|
|
||||||
Enable x86 builds with Oracle's Solaris compiler.
|
|
||||||
Fix support for calling code compiled with Oracle's Sparc
|
|
||||||
Solaris compiler.
|
|
||||||
Testsuite fixes for Tru64 Unix.
|
|
||||||
Additional platform support.
|
|
||||||
|
|
||||||
3.0.9 Dec-31-09
|
|
||||||
Add AVR32 and win64 ports. Add ARM softfp support.
|
|
||||||
Many fixes for AIX, Solaris, HP-UX, *BSD.
|
|
||||||
Several PowerPC and x86-64 bug fixes.
|
|
||||||
Build DLL for windows.
|
|
||||||
|
|
||||||
3.0.8 Dec-19-08
|
|
||||||
Add *BSD, BeOS, and PA-Linux support.
|
|
||||||
|
|
||||||
3.0.7 Nov-11-08
|
|
||||||
Fix for ppc FreeBSD.
|
|
||||||
(thanks to Andreas Tobler)
|
|
||||||
|
|
||||||
3.0.6 Jul-17-08
|
|
||||||
Fix for closures on sh.
|
|
||||||
Mark the sh/sh64 stack as non-executable.
|
|
||||||
(both thanks to Kaz Kojima)
|
|
||||||
|
|
||||||
3.0.5 Apr-3-08
|
|
||||||
Fix libffi.pc file.
|
|
||||||
Fix #define ARM for IcedTea users.
|
|
||||||
Fix x86 closure bug.
|
|
||||||
|
|
||||||
3.0.4 Feb-24-08
|
|
||||||
Fix x86 OpenBSD configury.
|
|
||||||
|
|
||||||
3.0.3 Feb-22-08
|
|
||||||
Enable x86 OpenBSD thanks to Thomas Heller, and
|
|
||||||
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
|
|
||||||
Clean up test instruction in README.
|
|
||||||
|
|
||||||
3.0.2 Feb-21-08
|
|
||||||
Improved x86 FreeBSD support.
|
|
||||||
Thanks to Björn König.
|
|
||||||
|
|
||||||
3.0.1 Feb-15-08
|
|
||||||
Fix instruction cache flushing bug on MIPS.
|
|
||||||
Thanks to David Daney.
|
|
||||||
|
|
||||||
3.0.0 Feb-15-08
|
|
||||||
Many changes, mostly thanks to the GCC project.
|
|
||||||
Cygnus Solutions is now Red Hat.
|
|
||||||
|
|
||||||
[10 years go by...]
|
|
||||||
|
|
||||||
1.20 Oct-5-98
|
|
||||||
Raffaele Sena produces ARM port.
|
|
||||||
|
|
||||||
1.19 Oct-5-98
|
|
||||||
Fixed x86 long double and long long return support.
|
|
||||||
m68k bug fixes from Andreas Schwab.
|
|
||||||
Patch for DU assembler compatibility for the Alpha from Richard
|
|
||||||
Henderson.
|
|
||||||
|
|
||||||
1.18 Apr-17-98
|
|
||||||
Bug fixes and MIPS configuration changes.
|
|
||||||
|
|
||||||
1.17 Feb-24-98
|
|
||||||
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
|
|
||||||
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
|
|
||||||
|
|
||||||
1.16 Feb-11-98
|
|
||||||
Richard Henderson produces Alpha port.
|
|
||||||
|
|
||||||
1.15 Dec-4-97
|
|
||||||
Fixed an n32 ABI bug. New libtool, auto* support.
|
|
||||||
|
|
||||||
1.14 May-13-97
|
|
||||||
libtool is now used to generate shared and static libraries.
|
|
||||||
Fixed a minor portability problem reported by Russ McManus
|
|
||||||
<mcmanr@eq.gs.com>.
|
|
||||||
|
|
||||||
1.13 Dec-2-96
|
|
||||||
Added --enable-purify-safety to keep Purify from complaining
|
|
||||||
about certain low level code.
|
|
||||||
Sparc fix for calling functions with < 6 args.
|
|
||||||
Linux x86 a.out fix.
|
|
||||||
|
|
||||||
1.12 Nov-22-96
|
|
||||||
Added missing ffi_type_void, needed for supporting void return
|
|
||||||
types. Fixed test case for non MIPS machines. Cygnus Support
|
|
||||||
is now Cygnus Solutions.
|
|
||||||
|
|
||||||
1.11 Oct-30-96
|
|
||||||
Added notes about GNU make.
|
|
||||||
|
|
||||||
1.10 Oct-29-96
|
|
||||||
Added configuration fix for non GNU compilers.
|
|
||||||
|
|
||||||
1.09 Oct-29-96
|
|
||||||
Added --enable-debug configure switch. Clean-ups based on LCLint
|
|
||||||
feedback. ffi_mips.h is always installed. Many configuration
|
|
||||||
fixes. Fixed ffitest.c for sparc builds.
|
|
||||||
|
|
||||||
1.08 Oct-15-96
|
|
||||||
Fixed n32 problem. Many clean-ups.
|
|
||||||
|
|
||||||
1.07 Oct-14-96
|
|
||||||
Gordon Irlam rewrites v8.S again. Bug fixes.
|
|
||||||
|
|
||||||
1.06 Oct-14-96
|
|
||||||
Gordon Irlam improved the sparc port.
|
|
||||||
|
|
||||||
1.05 Oct-14-96
|
|
||||||
Interface changes based on feedback.
|
|
||||||
|
|
||||||
1.04 Oct-11-96
|
|
||||||
Sparc port complete (modulo struct passing bug).
|
|
||||||
|
|
||||||
1.03 Oct-10-96
|
|
||||||
Passing struct args, and returning struct values works for
|
|
||||||
all architectures/calling conventions. Expanded tests.
|
|
||||||
|
|
||||||
1.02 Oct-9-96
|
|
||||||
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
|
|
||||||
Added "make test".
|
|
||||||
|
|
||||||
1.01 Oct-8-96
|
|
||||||
Fixed float passing bug in mips version. Restructured some
|
|
||||||
of the code. Builds cleanly with SGI tools.
|
|
||||||
|
|
||||||
1.00 Oct-7-96
|
|
||||||
First release. No public announcement.
|
|
||||||
|
|
||||||
|
|
||||||
Authors & Credits
|
|
||||||
=================
|
|
||||||
|
|
||||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
|
||||||
|
|
||||||
The developers of the GNU Compiler Collection project have made
|
|
||||||
innumerable valuable contributions. See the ChangeLog file for
|
|
||||||
details.
|
|
||||||
|
|
||||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
|
||||||
gencall library for Silicon Graphics machines.
|
|
||||||
|
|
||||||
The closure mechanism was designed and implemented by Kresten Krab
|
|
||||||
Thorup.
|
|
||||||
|
|
||||||
Major processor architecture ports were contributed by the following
|
|
||||||
developers:
|
|
||||||
|
|
||||||
alpha Richard Henderson
|
|
||||||
arm Raffaele Sena
|
|
||||||
cris Simon Posnjak, Hans-Peter Nilsson
|
|
||||||
frv Anthony Green
|
|
||||||
ia64 Hans Boehm
|
|
||||||
m32r Kazuhiro Inaoka
|
|
||||||
m68k Andreas Schwab
|
|
||||||
mips Anthony Green, Casey Marshall
|
|
||||||
mips64 David Daney
|
|
||||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
|
||||||
powerpc Geoffrey Keating, Andreas Tobler,
|
|
||||||
David Edelsohn, John Hornkvist
|
|
||||||
powerpc64 Jakub Jelinek
|
|
||||||
s390 Gerhard Tonn, Ulrich Weigand
|
|
||||||
sh Kaz Kojima
|
|
||||||
sh64 Kaz Kojima
|
|
||||||
sparc Anthony Green, Gordon Irlam
|
|
||||||
x86 Anthony Green, Jon Beniston
|
|
||||||
x86-64 Bo Thorsen
|
|
||||||
|
|
||||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
|
||||||
stepping through the code and tracking down bugs.
|
|
||||||
|
|
||||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
|
||||||
configuration help.
|
|
||||||
|
|
||||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
|
||||||
interface.
|
|
||||||
|
|
||||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
|
||||||
|
|
||||||
Alex Oliva solved the executable page problem for SElinux.
|
|
||||||
|
|
||||||
The list above is almost certainly incomplete and inaccurate. I'm
|
|
||||||
happy to make corrections or additions upon request.
|
|
||||||
|
|
||||||
If you have a problem, or have found a bug, please send a note to the
|
|
||||||
author at green@moxielogic.com, or the project mailing list at
|
|
||||||
libffi-discuss@sourceware.org.
|
|
||||||
17337
.pc/bfin/configure
vendored
17337
.pc/bfin/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,502 +0,0 @@
|
|||||||
dnl Process this with autoconf to create configure
|
|
||||||
|
|
||||||
AC_PREREQ(2.68)
|
|
||||||
|
|
||||||
AC_INIT([libffi], [3.0.11], [http://github.com/atgreen/libffi/issues])
|
|
||||||
AC_CONFIG_HEADERS([fficonfig.h])
|
|
||||||
|
|
||||||
AC_CANONICAL_SYSTEM
|
|
||||||
target_alias=${target_alias-$host_alias}
|
|
||||||
|
|
||||||
. ${srcdir}/configure.host
|
|
||||||
|
|
||||||
AX_ENABLE_BUILDDIR
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE
|
|
||||||
|
|
||||||
# The same as in boehm-gc and libstdc++. Have to borrow it from there.
|
|
||||||
# We must force CC to /not/ be precious variables; otherwise
|
|
||||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
|
||||||
# As a side effect, we have to subst CFLAGS ourselves.
|
|
||||||
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
|
|
||||||
# defaults of its own if none are provided.
|
|
||||||
|
|
||||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
|
||||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
|
||||||
save_CFLAGS=$CFLAGS
|
|
||||||
AC_PROG_CC
|
|
||||||
CFLAGS=$save_CFLAGS
|
|
||||||
m4_undefine([_AC_ARG_VAR_PRECIOUS])
|
|
||||||
m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
|
||||||
|
|
||||||
AC_SUBST(CFLAGS)
|
|
||||||
|
|
||||||
AM_PROG_AS
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
|
|
||||||
AX_CC_MAXOPT
|
|
||||||
AX_CFLAGS_WARN_ALL
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
CFLAGS="$CFLAGS -fexceptions"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/mman.h)
|
|
||||||
AC_CHECK_FUNCS(mmap)
|
|
||||||
AC_FUNC_MMAP_BLACKLIST
|
|
||||||
|
|
||||||
dnl The -no-testsuite modules omit the test subdir.
|
|
||||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
|
||||||
|
|
||||||
TARGETDIR="unknown"
|
|
||||||
case "$host" in
|
|
||||||
alpha*-*-*)
|
|
||||||
TARGET=ALPHA; TARGETDIR=alpha;
|
|
||||||
# Support 128-bit long double, changeable via command-line switch.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
|
||||||
;;
|
|
||||||
|
|
||||||
arm*-*-*)
|
|
||||||
TARGET=ARM; TARGETDIR=arm
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd* | amd64-*-openbsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
avr32*-*-*)
|
|
||||||
TARGET=AVR32; TARGETDIR=avr32
|
|
||||||
;;
|
|
||||||
|
|
||||||
cris-*-*)
|
|
||||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
|
||||||
;;
|
|
||||||
|
|
||||||
frv-*-*)
|
|
||||||
TARGET=FRV; TARGETDIR=frv
|
|
||||||
;;
|
|
||||||
|
|
||||||
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
|
|
||||||
TARGET=PA_LINUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*64-*-hpux*)
|
|
||||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*-*-hpux*)
|
|
||||||
TARGET=PA_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
|
|
||||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
|
||||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
|
|
||||||
TARGET=X86_WIN32; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
i?86-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-solaris2.1[[0-9]]*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
ia64*-*-*)
|
|
||||||
TARGET=IA64; TARGETDIR=ia64
|
|
||||||
;;
|
|
||||||
|
|
||||||
m32r*-*-*)
|
|
||||||
TARGET=M32R; TARGETDIR=m32r
|
|
||||||
;;
|
|
||||||
|
|
||||||
m68k-*-*)
|
|
||||||
TARGET=M68K; TARGETDIR=m68k
|
|
||||||
;;
|
|
||||||
|
|
||||||
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
mips*-*-linux* | mips*-*-openbsd*)
|
|
||||||
# Support 128-bit long double for NewABI.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__mips64)'
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
|
|
||||||
moxie-*-*)
|
|
||||||
TARGET=MOXIE; TARGETDIR=moxie
|
|
||||||
;;
|
|
||||||
|
|
||||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-amigaos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-beos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-darwin* | powerpc64-*-darwin*)
|
|
||||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-aix* | rs6000-*-aix*)
|
|
||||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-freebsd* | powerpc-*-openbsd*)
|
|
||||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc64-*-freebsd*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc*-*-rtems*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
|
|
||||||
s390-*-* | s390x-*-*)
|
|
||||||
TARGET=S390; TARGETDIR=s390
|
|
||||||
;;
|
|
||||||
|
|
||||||
sh-*-* | sh[[34]]*-*-*)
|
|
||||||
TARGET=SH; TARGETDIR=sh
|
|
||||||
;;
|
|
||||||
sh64-*-* | sh5*-*-*)
|
|
||||||
TARGET=SH64; TARGETDIR=sh64
|
|
||||||
;;
|
|
||||||
|
|
||||||
sparc*-*-*)
|
|
||||||
TARGET=SPARC; TARGETDIR=sparc
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-cygwin* | x86_64-*-mingw*)
|
|
||||||
TARGET=X86_WIN64; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
AC_SUBST(AM_RUNTESTFLAGS)
|
|
||||||
AC_SUBST(AM_LTLDFLAGS)
|
|
||||||
|
|
||||||
if test $TARGETDIR = unknown; then
|
|
||||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
|
||||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
|
||||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
|
||||||
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
|
||||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
|
||||||
AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
|
|
||||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
|
||||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
|
||||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
|
||||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
|
||||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
|
||||||
AM_CONDITIONAL(MOXIE, test x$TARGET = xMOXIE)
|
|
||||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
|
||||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
|
||||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
|
||||||
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
|
|
||||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
|
||||||
AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
|
|
||||||
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
|
|
||||||
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
|
|
||||||
AM_CONDITIONAL(S390, test x$TARGET = xS390)
|
|
||||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
|
||||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
|
||||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
|
||||||
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
|
|
||||||
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
|
|
||||||
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
|
|
||||||
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_FUNCS(memcpy)
|
|
||||||
AC_FUNC_ALLOCA
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(double)
|
|
||||||
AC_CHECK_SIZEOF(long double)
|
|
||||||
|
|
||||||
# Also AC_SUBST this variable for ffi.h.
|
|
||||||
if test -z "$HAVE_LONG_DOUBLE"; then
|
|
||||||
HAVE_LONG_DOUBLE=0
|
|
||||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
|
||||||
if test $ac_cv_sizeof_long_double != 0; then
|
|
||||||
HAVE_LONG_DOUBLE=1
|
|
||||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
|
||||||
|
|
||||||
GCC_AS_CFI_PSEUDO_OP
|
|
||||||
|
|
||||||
if test x$TARGET = xSPARC; then
|
|
||||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
|
||||||
libffi_cv_as_sparc_ua_pcrel, [
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
save_LDFLAGS="$LDFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -fpic"
|
|
||||||
LDFLAGS="$LDFLAGS -shared"
|
|
||||||
AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=yes],
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=no])
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
LDFLAGS="$save_LDFLAGS"])
|
|
||||||
if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
|
|
||||||
[Define if your assembler and linker support unaligned PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .register pseudo-op support],
|
|
||||||
libffi_cv_as_register_pseudo_op, [
|
|
||||||
libffi_cv_as_register_pseudo_op=unknown
|
|
||||||
# Check if we have .register
|
|
||||||
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
|
|
||||||
[libffi_cv_as_register_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_register_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .register.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports pc related relocs],
|
|
||||||
libffi_cv_as_x86_pcrel, [
|
|
||||||
libffi_cv_as_x86_pcrel=yes
|
|
||||||
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
|
|
||||||
libffi_cv_as_x86_pcrel=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
|
|
||||||
[Define if your assembler supports PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .ascii pseudo-op support],
|
|
||||||
libffi_cv_as_ascii_pseudo_op, [
|
|
||||||
libffi_cv_as_ascii_pseudo_op=unknown
|
|
||||||
# Check if we have .ascii
|
|
||||||
AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .ascii.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .string pseudo-op support],
|
|
||||||
libffi_cv_as_string_pseudo_op, [
|
|
||||||
libffi_cv_as_string_pseudo_op=unknown
|
|
||||||
# Check if we have .string
|
|
||||||
AC_TRY_COMPILE([asm (".string \\"string\\"");],,
|
|
||||||
[libffi_cv_as_string_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_string_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .string.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_WIN64; then
|
|
||||||
LT_SYS_SYMBOL_USCORE
|
|
||||||
if test "x$sys_symbol_underscore" = xyes; then
|
|
||||||
AC_DEFINE(SYMBOL_UNDERSCORE, 1, [Define if symbols are underscored.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=0
|
|
||||||
case "$target" in
|
|
||||||
*arm*-apple-darwin*)
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=1
|
|
||||||
AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1,
|
|
||||||
[Cannot use PROT_EXEC on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
*-apple-darwin1[[10]]* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*)
|
|
||||||
AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1,
|
|
||||||
[Cannot use malloc on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
|
|
||||||
AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports unwind section type],
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type, [
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
|
||||||
echo '.section .eh_frame,"a",@unwind' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
|
|
||||||
[Define if your assembler supports unwind section type.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
|
|
||||||
libffi_cv_ro_eh_frame, [
|
|
||||||
libffi_cv_ro_eh_frame=no
|
|
||||||
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
|
|
||||||
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
|
|
||||||
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
elif grep '.section.*eh_frame.*#alloc' conftest.c \
|
|
||||||
| grep -v '#write' > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_ro_eh_frame" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_RO_EH_FRAME, 1,
|
|
||||||
[Define if .eh_frame sections should be read-only.])
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "a",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
else
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "aw",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
|
|
||||||
libffi_cv_hidden_visibility_attribute, [
|
|
||||||
echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c
|
|
||||||
libffi_cv_hidden_visibility_attribute=no
|
|
||||||
if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
|
||||||
if grep '\.hidden.*foo' conftest.s >/dev/null; then
|
|
||||||
libffi_cv_hidden_visibility_attribute=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test $libffi_cv_hidden_visibility_attribute = yes; then
|
|
||||||
AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
|
|
||||||
[Define if __attribute__((visibility("hidden"))) is supported.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AH_BOTTOM([
|
|
||||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name) .hidden name
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name)
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_SUBST(TARGET)
|
|
||||||
AC_SUBST(TARGETDIR)
|
|
||||||
|
|
||||||
AC_SUBST(SHELL)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(debug,
|
|
||||||
[ --enable-debug debugging mode],
|
|
||||||
if test "$enable_debug" = "yes"; then
|
|
||||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
|
||||||
fi)
|
|
||||||
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(structs,
|
|
||||||
[ --disable-structs omit code for struct support],
|
|
||||||
if test "$enable_structs" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(raw-api,
|
|
||||||
[ --disable-raw-api make the raw api unavailable],
|
|
||||||
if test "$enable_raw_api" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(purify-safety,
|
|
||||||
[ --enable-purify-safety purify-safe mode],
|
|
||||||
if test "$enable_purify_safety" = "yes"; then
|
|
||||||
AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
# These variables are only ever used when we cross-build to X86_WIN32.
|
|
||||||
# And we only support this with GCC, so...
|
|
||||||
if test x"$GCC" != x"no"; then
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
toolexecdir='$(exec_prefix)/$(target_alias)'
|
|
||||||
toolexeclibdir='$(toolexecdir)/lib'
|
|
||||||
else
|
|
||||||
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
|
|
||||||
toolexeclibdir='$(libdir)'
|
|
||||||
fi
|
|
||||||
multi_os_directory=`$CC -print-multi-os-directory`
|
|
||||||
case $multi_os_directory in
|
|
||||||
.) ;; # Avoid trailing /.
|
|
||||||
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
|
|
||||||
esac
|
|
||||||
AC_SUBST(toolexecdir)
|
|
||||||
AC_SUBST(toolexeclibdir)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "${multilib}" = "yes"; then
|
|
||||||
multilib_arg="--enable-multilib"
|
|
||||||
else
|
|
||||||
multilib_arg=
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
|
|
||||||
AC_CONFIG_COMMANDS(src, [
|
|
||||||
test -d src || mkdir src
|
|
||||||
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
|
||||||
], [TARGETDIR="$TARGETDIR"])
|
|
||||||
|
|
||||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
|
||||||
|
|
||||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
|
||||||
|
|
||||||
AC_OUTPUT
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
17404
.pc/darwin12/configure
vendored
17404
.pc/darwin12/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,517 +0,0 @@
|
|||||||
dnl Process this with autoconf to create configure
|
|
||||||
|
|
||||||
AC_PREREQ(2.68)
|
|
||||||
|
|
||||||
AC_INIT([libffi], [3.0.11], [http://github.com/atgreen/libffi/issues])
|
|
||||||
AC_CONFIG_HEADERS([fficonfig.h])
|
|
||||||
|
|
||||||
AC_CANONICAL_SYSTEM
|
|
||||||
target_alias=${target_alias-$host_alias}
|
|
||||||
|
|
||||||
. ${srcdir}/configure.host
|
|
||||||
|
|
||||||
AX_ENABLE_BUILDDIR
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE
|
|
||||||
|
|
||||||
# The same as in boehm-gc and libstdc++. Have to borrow it from there.
|
|
||||||
# We must force CC to /not/ be precious variables; otherwise
|
|
||||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
|
||||||
# As a side effect, we have to subst CFLAGS ourselves.
|
|
||||||
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
|
|
||||||
# defaults of its own if none are provided.
|
|
||||||
|
|
||||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
|
||||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
|
||||||
save_CFLAGS=$CFLAGS
|
|
||||||
AC_PROG_CC
|
|
||||||
CFLAGS=$save_CFLAGS
|
|
||||||
m4_undefine([_AC_ARG_VAR_PRECIOUS])
|
|
||||||
m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
|
||||||
|
|
||||||
AC_SUBST(CFLAGS)
|
|
||||||
|
|
||||||
AM_PROG_AS
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
|
|
||||||
AX_CC_MAXOPT
|
|
||||||
AX_CFLAGS_WARN_ALL
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
CFLAGS="$CFLAGS -fexceptions"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/mman.h)
|
|
||||||
AC_CHECK_FUNCS(mmap)
|
|
||||||
AC_FUNC_MMAP_BLACKLIST
|
|
||||||
|
|
||||||
dnl The -no-testsuite modules omit the test subdir.
|
|
||||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
|
||||||
|
|
||||||
TARGETDIR="unknown"
|
|
||||||
case "$host" in
|
|
||||||
aarch64*-*-*)
|
|
||||||
TARGET=AARCH64; TARGETDIR=aarch64
|
|
||||||
;;
|
|
||||||
|
|
||||||
alpha*-*-*)
|
|
||||||
TARGET=ALPHA; TARGETDIR=alpha;
|
|
||||||
# Support 128-bit long double, changeable via command-line switch.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
|
||||||
;;
|
|
||||||
|
|
||||||
arm*-*-*)
|
|
||||||
TARGET=ARM; TARGETDIR=arm
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd* | amd64-*-openbsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
avr32*-*-*)
|
|
||||||
TARGET=AVR32; TARGETDIR=avr32
|
|
||||||
;;
|
|
||||||
|
|
||||||
bfin*)
|
|
||||||
TARGET=BFIN; TARGETDIR=bfin
|
|
||||||
;;
|
|
||||||
|
|
||||||
cris-*-*)
|
|
||||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
|
||||||
;;
|
|
||||||
|
|
||||||
frv-*-*)
|
|
||||||
TARGET=FRV; TARGETDIR=frv
|
|
||||||
;;
|
|
||||||
|
|
||||||
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
|
|
||||||
TARGET=PA_LINUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*64-*-hpux*)
|
|
||||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*-*-hpux*)
|
|
||||||
TARGET=PA_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
|
|
||||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
|
||||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
|
|
||||||
TARGET=X86_WIN32; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
i?86-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-solaris2.1[[0-9]]*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
ia64*-*-*)
|
|
||||||
TARGET=IA64; TARGETDIR=ia64
|
|
||||||
;;
|
|
||||||
|
|
||||||
m32r*-*-*)
|
|
||||||
TARGET=M32R; TARGETDIR=m32r
|
|
||||||
;;
|
|
||||||
|
|
||||||
m68k-*-*)
|
|
||||||
TARGET=M68K; TARGETDIR=m68k
|
|
||||||
;;
|
|
||||||
|
|
||||||
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
mips*-*-linux* | mips*-*-openbsd*)
|
|
||||||
# Support 128-bit long double for NewABI.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__mips64)'
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
|
|
||||||
moxie-*-*)
|
|
||||||
TARGET=MOXIE; TARGETDIR=moxie
|
|
||||||
;;
|
|
||||||
|
|
||||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-amigaos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-beos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-darwin* | powerpc64-*-darwin*)
|
|
||||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-aix* | rs6000-*-aix*)
|
|
||||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-freebsd* | powerpc-*-openbsd*)
|
|
||||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc64-*-freebsd*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc*-*-rtems*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
|
|
||||||
s390-*-* | s390x-*-*)
|
|
||||||
TARGET=S390; TARGETDIR=s390
|
|
||||||
;;
|
|
||||||
|
|
||||||
sh-*-* | sh[[34]]*-*-*)
|
|
||||||
TARGET=SH; TARGETDIR=sh
|
|
||||||
;;
|
|
||||||
sh64-*-* | sh5*-*-*)
|
|
||||||
TARGET=SH64; TARGETDIR=sh64
|
|
||||||
;;
|
|
||||||
|
|
||||||
sparc*-*-*)
|
|
||||||
TARGET=SPARC; TARGETDIR=sparc
|
|
||||||
;;
|
|
||||||
|
|
||||||
tile*-*)
|
|
||||||
TARGET=TILE; TARGETDIR=tile
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-cygwin* | x86_64-*-mingw*)
|
|
||||||
TARGET=X86_WIN64; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
AC_SUBST(AM_RUNTESTFLAGS)
|
|
||||||
AC_SUBST(AM_LTLDFLAGS)
|
|
||||||
|
|
||||||
if test $TARGETDIR = unknown; then
|
|
||||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
|
||||||
AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
|
|
||||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
|
||||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
|
||||||
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
|
||||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
|
||||||
AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
|
|
||||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
|
||||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
|
||||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
|
||||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
|
||||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
|
||||||
AM_CONDITIONAL(MOXIE, test x$TARGET = xMOXIE)
|
|
||||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
|
||||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
|
||||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
|
||||||
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
|
|
||||||
AM_CONDITIONAL(AARCH64, test x$TARGET = xAARCH64)
|
|
||||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
|
||||||
AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
|
|
||||||
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
|
|
||||||
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
|
|
||||||
AM_CONDITIONAL(S390, test x$TARGET = xS390)
|
|
||||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
|
||||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
|
||||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
|
||||||
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
|
|
||||||
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
|
|
||||||
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
|
|
||||||
AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
|
|
||||||
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_FUNCS(memcpy)
|
|
||||||
AC_FUNC_ALLOCA
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(double)
|
|
||||||
AC_CHECK_SIZEOF(long double)
|
|
||||||
|
|
||||||
# Also AC_SUBST this variable for ffi.h.
|
|
||||||
if test -z "$HAVE_LONG_DOUBLE"; then
|
|
||||||
HAVE_LONG_DOUBLE=0
|
|
||||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
|
||||||
if test $ac_cv_sizeof_long_double != 0; then
|
|
||||||
HAVE_LONG_DOUBLE=1
|
|
||||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
|
||||||
|
|
||||||
GCC_AS_CFI_PSEUDO_OP
|
|
||||||
|
|
||||||
if test x$TARGET = xSPARC; then
|
|
||||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
|
||||||
libffi_cv_as_sparc_ua_pcrel, [
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
save_LDFLAGS="$LDFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -fpic"
|
|
||||||
LDFLAGS="$LDFLAGS -shared"
|
|
||||||
AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=yes],
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=no])
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
LDFLAGS="$save_LDFLAGS"])
|
|
||||||
if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
|
|
||||||
[Define if your assembler and linker support unaligned PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .register pseudo-op support],
|
|
||||||
libffi_cv_as_register_pseudo_op, [
|
|
||||||
libffi_cv_as_register_pseudo_op=unknown
|
|
||||||
# Check if we have .register
|
|
||||||
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
|
|
||||||
[libffi_cv_as_register_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_register_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .register.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports pc related relocs],
|
|
||||||
libffi_cv_as_x86_pcrel, [
|
|
||||||
libffi_cv_as_x86_pcrel=yes
|
|
||||||
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
|
|
||||||
libffi_cv_as_x86_pcrel=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
|
|
||||||
[Define if your assembler supports PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .ascii pseudo-op support],
|
|
||||||
libffi_cv_as_ascii_pseudo_op, [
|
|
||||||
libffi_cv_as_ascii_pseudo_op=unknown
|
|
||||||
# Check if we have .ascii
|
|
||||||
AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .ascii.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .string pseudo-op support],
|
|
||||||
libffi_cv_as_string_pseudo_op, [
|
|
||||||
libffi_cv_as_string_pseudo_op=unknown
|
|
||||||
# Check if we have .string
|
|
||||||
AC_TRY_COMPILE([asm (".string \\"string\\"");],,
|
|
||||||
[libffi_cv_as_string_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_string_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .string.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_WIN64; then
|
|
||||||
LT_SYS_SYMBOL_USCORE
|
|
||||||
if test "x$sys_symbol_underscore" = xyes; then
|
|
||||||
AC_DEFINE(SYMBOL_UNDERSCORE, 1, [Define if symbols are underscored.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=0
|
|
||||||
case "$target" in
|
|
||||||
*arm*-apple-darwin*)
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=1
|
|
||||||
AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1,
|
|
||||||
[Cannot use PROT_EXEC on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
*-apple-darwin1[[10]]* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*)
|
|
||||||
AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1,
|
|
||||||
[Cannot use malloc on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
|
|
||||||
AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports unwind section type],
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type, [
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
|
||||||
echo '.section .eh_frame,"a",@unwind' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
|
|
||||||
[Define if your assembler supports unwind section type.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
|
|
||||||
libffi_cv_ro_eh_frame, [
|
|
||||||
libffi_cv_ro_eh_frame=no
|
|
||||||
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
|
|
||||||
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
|
|
||||||
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
elif grep '.section.*eh_frame.*#alloc' conftest.c \
|
|
||||||
| grep -v '#write' > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_ro_eh_frame" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_RO_EH_FRAME, 1,
|
|
||||||
[Define if .eh_frame sections should be read-only.])
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "a",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
else
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "aw",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
|
|
||||||
libffi_cv_hidden_visibility_attribute, [
|
|
||||||
echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c
|
|
||||||
libffi_cv_hidden_visibility_attribute=no
|
|
||||||
if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
|
||||||
if grep '\.hidden.*foo' conftest.s >/dev/null; then
|
|
||||||
libffi_cv_hidden_visibility_attribute=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test $libffi_cv_hidden_visibility_attribute = yes; then
|
|
||||||
AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
|
|
||||||
[Define if __attribute__((visibility("hidden"))) is supported.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AH_BOTTOM([
|
|
||||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name) .hidden name
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name)
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_SUBST(TARGET)
|
|
||||||
AC_SUBST(TARGETDIR)
|
|
||||||
|
|
||||||
AC_SUBST(SHELL)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(debug,
|
|
||||||
[ --enable-debug debugging mode],
|
|
||||||
if test "$enable_debug" = "yes"; then
|
|
||||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
|
||||||
fi)
|
|
||||||
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(structs,
|
|
||||||
[ --disable-structs omit code for struct support],
|
|
||||||
if test "$enable_structs" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(raw-api,
|
|
||||||
[ --disable-raw-api make the raw api unavailable],
|
|
||||||
if test "$enable_raw_api" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(purify-safety,
|
|
||||||
[ --enable-purify-safety purify-safe mode],
|
|
||||||
if test "$enable_purify_safety" = "yes"; then
|
|
||||||
AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
# These variables are only ever used when we cross-build to X86_WIN32.
|
|
||||||
# And we only support this with GCC, so...
|
|
||||||
if test x"$GCC" != x"no"; then
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
toolexecdir='$(exec_prefix)/$(target_alias)'
|
|
||||||
toolexeclibdir='$(toolexecdir)/lib'
|
|
||||||
else
|
|
||||||
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
|
|
||||||
toolexeclibdir='$(libdir)'
|
|
||||||
fi
|
|
||||||
multi_os_directory=`$CC -print-multi-os-directory`
|
|
||||||
case $multi_os_directory in
|
|
||||||
.) ;; # Avoid trailing /.
|
|
||||||
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
|
|
||||||
esac
|
|
||||||
AC_SUBST(toolexecdir)
|
|
||||||
AC_SUBST(toolexeclibdir)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "${multilib}" = "yes"; then
|
|
||||||
multilib_arg="--enable-multilib"
|
|
||||||
else
|
|
||||||
multilib_arg=
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
|
|
||||||
AC_CONFIG_COMMANDS(src, [
|
|
||||||
test -d src || mkdir src
|
|
||||||
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
|
||||||
], [TARGETDIR="$TARGETDIR"])
|
|
||||||
|
|
||||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
|
||||||
|
|
||||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
|
||||||
|
|
||||||
AC_OUTPUT
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,80 +0,0 @@
|
|||||||
## Process this file with automake to produce Makefile.in.
|
|
||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign dejagnu
|
|
||||||
|
|
||||||
# Setup the testing framework, if you have one
|
|
||||||
EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
|
|
||||||
echo $(top_builddir)/../expect/expect ; \
|
|
||||||
else echo expect ; fi`
|
|
||||||
|
|
||||||
RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
|
|
||||||
echo $(top_srcdir)/../dejagnu/runtest ; \
|
|
||||||
else echo runtest; fi`
|
|
||||||
|
|
||||||
AM_RUNTESTFLAGS =
|
|
||||||
|
|
||||||
CLEANFILES = *.exe core* *.log *.sum
|
|
||||||
|
|
||||||
EXTRA_DIST = libffi.special/special.exp \
|
|
||||||
libffi.special/unwindtest_ffi_call.cc libffi.special/unwindtest.cc \
|
|
||||||
libffi.special/ffitestcxx.h config/default.exp lib/target-libpath.exp \
|
|
||||||
lib/libffi.exp lib/wrapper.exp libffi.call/float.c \
|
|
||||||
libffi.call/cls_multi_schar.c libffi.call/float3.c \
|
|
||||||
libffi.call/cls_3_1byte.c libffi.call/stret_large2.c \
|
|
||||||
libffi.call/cls_5_1_byte.c libffi.call/stret_medium.c \
|
|
||||||
libffi.call/promotion.c libffi.call/cls_dbls_struct.c \
|
|
||||||
libffi.call/nested_struct.c libffi.call/closure_fn1.c \
|
|
||||||
libffi.call/cls_4_1byte.c libffi.call/cls_float.c \
|
|
||||||
libffi.call/cls_2byte.c libffi.call/closure_fn4.c \
|
|
||||||
libffi.call/return_fl2.c libffi.call/nested_struct7.c \
|
|
||||||
libffi.call/cls_uint.c libffi.call/cls_align_sint64.c \
|
|
||||||
libffi.call/float1.c libffi.call/cls_19byte.c \
|
|
||||||
libffi.call/nested_struct1.c libffi.call/cls_4byte.c \
|
|
||||||
libffi.call/return_fl1.c libffi.call/cls_align_pointer.c \
|
|
||||||
libffi.call/nested_struct4.c libffi.call/nested_struct3.c \
|
|
||||||
libffi.call/struct7.c libffi.call/nested_struct9.c \
|
|
||||||
libffi.call/cls_sshort.c libffi.call/cls_ulonglong.c \
|
|
||||||
libffi.call/cls_pointer_stack.c libffi.call/cls_multi_uchar.c \
|
|
||||||
libffi.call/testclosure.c libffi.call/cls_3byte1.c \
|
|
||||||
libffi.call/struct6.c libffi.call/return_uc.c libffi.call/return_ll1.c \
|
|
||||||
libffi.call/cls_ushort.c libffi.call/stret_medium2.c \
|
|
||||||
libffi.call/cls_multi_ushortchar.c libffi.call/return_dbl2.c \
|
|
||||||
libffi.call/closure_loc_fn0.c libffi.call/return_sc.c \
|
|
||||||
libffi.call/nested_struct8.c libffi.call/cls_7_1_byte.c \
|
|
||||||
libffi.call/return_ll.c libffi.call/cls_pointer.c \
|
|
||||||
libffi.call/err_bad_abi.c libffi.call/return_dbl1.c \
|
|
||||||
libffi.call/call.exp libffi.call/ffitest.h libffi.call/strlen.c \
|
|
||||||
libffi.call/return_sl.c libffi.call/cls_1_1byte.c \
|
|
||||||
libffi.call/struct1.c libffi.call/cls_64byte.c libffi.call/return_ul.c \
|
|
||||||
libffi.call/cls_double.c libffi.call/many_win32.c \
|
|
||||||
libffi.call/cls_16byte.c libffi.call/cls_align_double.c \
|
|
||||||
libffi.call/cls_align_uint16.c libffi.call/cls_9byte1.c \
|
|
||||||
libffi.call/cls_multi_sshortchar.c libffi.call/cls_multi_ushort.c \
|
|
||||||
libffi.call/closure_stdcall.c libffi.call/return_fl.c \
|
|
||||||
libffi.call/strlen_win32.c libffi.call/return_ldl.c \
|
|
||||||
libffi.call/cls_align_float.c libffi.call/struct3.c \
|
|
||||||
libffi.call/cls_uchar.c libffi.call/cls_sint.c libffi.call/float2.c \
|
|
||||||
libffi.call/cls_align_longdouble_split.c \
|
|
||||||
libffi.call/cls_longdouble_va.c libffi.call/cls_multi_sshort.c \
|
|
||||||
libffi.call/stret_large.c libffi.call/cls_align_sint16.c \
|
|
||||||
libffi.call/nested_struct6.c libffi.call/cls_5byte.c \
|
|
||||||
libffi.call/return_dbl.c libffi.call/cls_20byte.c \
|
|
||||||
libffi.call/cls_8byte.c libffi.call/pyobjc-tc.c \
|
|
||||||
libffi.call/cls_24byte.c libffi.call/cls_align_longdouble_split2.c \
|
|
||||||
libffi.call/cls_6_1_byte.c libffi.call/cls_schar.c \
|
|
||||||
libffi.call/cls_18byte.c libffi.call/closure_fn3.c \
|
|
||||||
libffi.call/err_bad_typedef.c libffi.call/closure_fn2.c \
|
|
||||||
libffi.call/struct2.c libffi.call/cls_3byte2.c \
|
|
||||||
libffi.call/cls_align_longdouble.c libffi.call/cls_20byte1.c \
|
|
||||||
libffi.call/return_fl3.c libffi.call/cls_align_uint32.c \
|
|
||||||
libffi.call/problem1.c libffi.call/float4.c \
|
|
||||||
libffi.call/cls_align_uint64.c libffi.call/struct9.c \
|
|
||||||
libffi.call/closure_fn5.c libffi.call/cls_align_sint32.c \
|
|
||||||
libffi.call/closure_fn0.c libffi.call/closure_fn6.c \
|
|
||||||
libffi.call/struct4.c libffi.call/nested_struct2.c \
|
|
||||||
libffi.call/cls_6byte.c libffi.call/cls_7byte.c libffi.call/many.c \
|
|
||||||
libffi.call/struct8.c libffi.call/negint.c libffi.call/struct5.c \
|
|
||||||
libffi.call/cls_12byte.c libffi.call/cls_double_va.c \
|
|
||||||
libffi.call/cls_longdouble.c libffi.call/cls_9byte2.c \
|
|
||||||
libffi.call/nested_struct10.c libffi.call/nested_struct5.c \
|
|
||||||
libffi.call/huge_struct.c
|
|
||||||
@@ -1,535 +0,0 @@
|
|||||||
# Makefile.in generated by automake 1.11.6 from Makefile.am.
|
|
||||||
# @configure_input@
|
|
||||||
|
|
||||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
|
||||||
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
|
|
||||||
# Foundation, Inc.
|
|
||||||
# This Makefile.in is free software; the Free Software Foundation
|
|
||||||
# gives unlimited permission to copy and/or distribute it,
|
|
||||||
# with or without modifications, as long as this notice is preserved.
|
|
||||||
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
|
||||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
# PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
@SET_MAKE@
|
|
||||||
VPATH = @srcdir@
|
|
||||||
am__make_dryrun = \
|
|
||||||
{ \
|
|
||||||
am__dry=no; \
|
|
||||||
case $$MAKEFLAGS in \
|
|
||||||
*\\[\ \ ]*) \
|
|
||||||
echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
|
|
||||||
| grep '^AM OK$$' >/dev/null || am__dry=yes;; \
|
|
||||||
*) \
|
|
||||||
for am__flg in $$MAKEFLAGS; do \
|
|
||||||
case $$am__flg in \
|
|
||||||
*=*|--*) ;; \
|
|
||||||
*n*) am__dry=yes; break;; \
|
|
||||||
esac; \
|
|
||||||
done;; \
|
|
||||||
esac; \
|
|
||||||
test $$am__dry = yes; \
|
|
||||||
}
|
|
||||||
pkgdatadir = $(datadir)/@PACKAGE@
|
|
||||||
pkgincludedir = $(includedir)/@PACKAGE@
|
|
||||||
pkglibdir = $(libdir)/@PACKAGE@
|
|
||||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
|
||||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
|
||||||
install_sh_DATA = $(install_sh) -c -m 644
|
|
||||||
install_sh_PROGRAM = $(install_sh) -c
|
|
||||||
install_sh_SCRIPT = $(install_sh) -c
|
|
||||||
INSTALL_HEADER = $(INSTALL_DATA)
|
|
||||||
transform = $(program_transform_name)
|
|
||||||
NORMAL_INSTALL = :
|
|
||||||
PRE_INSTALL = :
|
|
||||||
POST_INSTALL = :
|
|
||||||
NORMAL_UNINSTALL = :
|
|
||||||
PRE_UNINSTALL = :
|
|
||||||
POST_UNINSTALL = :
|
|
||||||
build_triplet = @build@
|
|
||||||
host_triplet = @host@
|
|
||||||
target_triplet = @target@
|
|
||||||
subdir = testsuite
|
|
||||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
|
||||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
|
||||||
am__aclocal_m4_deps = $(top_srcdir)/m4/asmcfi.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_cc_maxopt.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_compiler_vendor.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_configure_args.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_enable_builddir.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_gcc_archflag.m4 \
|
|
||||||
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
|
|
||||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
|
||||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
|
||||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
|
|
||||||
$(top_srcdir)/configure.ac
|
|
||||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
|
||||||
$(ACLOCAL_M4)
|
|
||||||
mkinstalldirs = $(install_sh) -d
|
|
||||||
CONFIG_HEADER = $(top_builddir)/fficonfig.h
|
|
||||||
CONFIG_CLEAN_FILES =
|
|
||||||
CONFIG_CLEAN_VPATH_FILES =
|
|
||||||
SOURCES =
|
|
||||||
DIST_SOURCES =
|
|
||||||
am__can_run_installinfo = \
|
|
||||||
case $$AM_UPDATE_INFO_DIR in \
|
|
||||||
n|no|NO) false;; \
|
|
||||||
*) (install-info --version) >/dev/null 2>&1;; \
|
|
||||||
esac
|
|
||||||
DEJATOOL = $(PACKAGE)
|
|
||||||
RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
|
|
||||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
|
||||||
ACLOCAL = @ACLOCAL@
|
|
||||||
ALLOCA = @ALLOCA@
|
|
||||||
AMTAR = @AMTAR@
|
|
||||||
AM_LTLDFLAGS = @AM_LTLDFLAGS@
|
|
||||||
AM_RUNTESTFLAGS =
|
|
||||||
AR = @AR@
|
|
||||||
AUTOCONF = @AUTOCONF@
|
|
||||||
AUTOHEADER = @AUTOHEADER@
|
|
||||||
AUTOMAKE = @AUTOMAKE@
|
|
||||||
AWK = @AWK@
|
|
||||||
CC = @CC@
|
|
||||||
CCAS = @CCAS@
|
|
||||||
CCASDEPMODE = @CCASDEPMODE@
|
|
||||||
CCASFLAGS = @CCASFLAGS@
|
|
||||||
CCDEPMODE = @CCDEPMODE@
|
|
||||||
CFLAGS = @CFLAGS@
|
|
||||||
CPP = @CPP@
|
|
||||||
CPPFLAGS = @CPPFLAGS@
|
|
||||||
CYGPATH_W = @CYGPATH_W@
|
|
||||||
DEFS = @DEFS@
|
|
||||||
DEPDIR = @DEPDIR@
|
|
||||||
DLLTOOL = @DLLTOOL@
|
|
||||||
DSYMUTIL = @DSYMUTIL@
|
|
||||||
DUMPBIN = @DUMPBIN@
|
|
||||||
ECHO_C = @ECHO_C@
|
|
||||||
ECHO_N = @ECHO_N@
|
|
||||||
ECHO_T = @ECHO_T@
|
|
||||||
EGREP = @EGREP@
|
|
||||||
EXEEXT = @EXEEXT@
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE = @FFI_EXEC_TRAMPOLINE_TABLE@
|
|
||||||
FGREP = @FGREP@
|
|
||||||
GREP = @GREP@
|
|
||||||
HAVE_LONG_DOUBLE = @HAVE_LONG_DOUBLE@
|
|
||||||
INSTALL = @INSTALL@
|
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
|
||||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
|
||||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
|
||||||
LD = @LD@
|
|
||||||
LDFLAGS = @LDFLAGS@
|
|
||||||
LIBOBJS = @LIBOBJS@
|
|
||||||
LIBS = @LIBS@
|
|
||||||
LIBTOOL = @LIBTOOL@
|
|
||||||
LIPO = @LIPO@
|
|
||||||
LN_S = @LN_S@
|
|
||||||
LTLIBOBJS = @LTLIBOBJS@
|
|
||||||
MAINT = @MAINT@
|
|
||||||
MAKEINFO = @MAKEINFO@
|
|
||||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
|
||||||
MKDIR_P = @MKDIR_P@
|
|
||||||
NM = @NM@
|
|
||||||
NMEDIT = @NMEDIT@
|
|
||||||
OBJDUMP = @OBJDUMP@
|
|
||||||
OBJEXT = @OBJEXT@
|
|
||||||
OTOOL = @OTOOL@
|
|
||||||
OTOOL64 = @OTOOL64@
|
|
||||||
PACKAGE = @PACKAGE@
|
|
||||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
|
||||||
PACKAGE_NAME = @PACKAGE_NAME@
|
|
||||||
PACKAGE_STRING = @PACKAGE_STRING@
|
|
||||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
|
||||||
PACKAGE_URL = @PACKAGE_URL@
|
|
||||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
|
||||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
|
||||||
PRTDIAG = @PRTDIAG@
|
|
||||||
RANLIB = @RANLIB@
|
|
||||||
SED = @SED@
|
|
||||||
SET_MAKE = @SET_MAKE@
|
|
||||||
SHELL = @SHELL@
|
|
||||||
STRIP = @STRIP@
|
|
||||||
TARGET = @TARGET@
|
|
||||||
TARGETDIR = @TARGETDIR@
|
|
||||||
VERSION = @VERSION@
|
|
||||||
abs_builddir = @abs_builddir@
|
|
||||||
abs_srcdir = @abs_srcdir@
|
|
||||||
abs_top_builddir = @abs_top_builddir@
|
|
||||||
abs_top_srcdir = @abs_top_srcdir@
|
|
||||||
ac_ct_AR = @ac_ct_AR@
|
|
||||||
ac_ct_CC = @ac_ct_CC@
|
|
||||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
|
||||||
am__include = @am__include@
|
|
||||||
am__leading_dot = @am__leading_dot@
|
|
||||||
am__quote = @am__quote@
|
|
||||||
am__tar = @am__tar@
|
|
||||||
am__untar = @am__untar@
|
|
||||||
ax_enable_builddir_sed = @ax_enable_builddir_sed@
|
|
||||||
bindir = @bindir@
|
|
||||||
build = @build@
|
|
||||||
build_alias = @build_alias@
|
|
||||||
build_cpu = @build_cpu@
|
|
||||||
build_os = @build_os@
|
|
||||||
build_vendor = @build_vendor@
|
|
||||||
builddir = @builddir@
|
|
||||||
datadir = @datadir@
|
|
||||||
datarootdir = @datarootdir@
|
|
||||||
docdir = @docdir@
|
|
||||||
dvidir = @dvidir@
|
|
||||||
exec_prefix = @exec_prefix@
|
|
||||||
host = @host@
|
|
||||||
host_alias = @host_alias@
|
|
||||||
host_cpu = @host_cpu@
|
|
||||||
host_os = @host_os@
|
|
||||||
host_vendor = @host_vendor@
|
|
||||||
htmldir = @htmldir@
|
|
||||||
includedir = @includedir@
|
|
||||||
infodir = @infodir@
|
|
||||||
install_sh = @install_sh@
|
|
||||||
libdir = @libdir@
|
|
||||||
libexecdir = @libexecdir@
|
|
||||||
localedir = @localedir@
|
|
||||||
localstatedir = @localstatedir@
|
|
||||||
mandir = @mandir@
|
|
||||||
mkdir_p = @mkdir_p@
|
|
||||||
oldincludedir = @oldincludedir@
|
|
||||||
pdfdir = @pdfdir@
|
|
||||||
prefix = @prefix@
|
|
||||||
program_transform_name = @program_transform_name@
|
|
||||||
psdir = @psdir@
|
|
||||||
sbindir = @sbindir@
|
|
||||||
sharedstatedir = @sharedstatedir@
|
|
||||||
srcdir = @srcdir@
|
|
||||||
sys_symbol_underscore = @sys_symbol_underscore@
|
|
||||||
sysconfdir = @sysconfdir@
|
|
||||||
target = @target@
|
|
||||||
target_alias = @target_alias@
|
|
||||||
target_cpu = @target_cpu@
|
|
||||||
target_os = @target_os@
|
|
||||||
target_vendor = @target_vendor@
|
|
||||||
toolexecdir = @toolexecdir@
|
|
||||||
toolexeclibdir = @toolexeclibdir@
|
|
||||||
top_build_prefix = @top_build_prefix@
|
|
||||||
top_builddir = @top_builddir@
|
|
||||||
top_srcdir = @top_srcdir@
|
|
||||||
AUTOMAKE_OPTIONS = foreign dejagnu
|
|
||||||
|
|
||||||
# Setup the testing framework, if you have one
|
|
||||||
EXPECT = `if [ -f $(top_builddir)/../expect/expect ] ; then \
|
|
||||||
echo $(top_builddir)/../expect/expect ; \
|
|
||||||
else echo expect ; fi`
|
|
||||||
|
|
||||||
RUNTEST = `if [ -f $(top_srcdir)/../dejagnu/runtest ] ; then \
|
|
||||||
echo $(top_srcdir)/../dejagnu/runtest ; \
|
|
||||||
else echo runtest; fi`
|
|
||||||
|
|
||||||
CLEANFILES = *.exe core* *.log *.sum
|
|
||||||
EXTRA_DIST = libffi.special/special.exp \
|
|
||||||
libffi.special/unwindtest_ffi_call.cc libffi.special/unwindtest.cc \
|
|
||||||
libffi.special/ffitestcxx.h config/default.exp lib/target-libpath.exp \
|
|
||||||
lib/libffi.exp lib/wrapper.exp libffi.call/float.c \
|
|
||||||
libffi.call/cls_multi_schar.c libffi.call/float3.c \
|
|
||||||
libffi.call/cls_3_1byte.c libffi.call/stret_large2.c \
|
|
||||||
libffi.call/cls_5_1_byte.c libffi.call/stret_medium.c \
|
|
||||||
libffi.call/promotion.c libffi.call/cls_dbls_struct.c \
|
|
||||||
libffi.call/nested_struct.c libffi.call/closure_fn1.c \
|
|
||||||
libffi.call/cls_4_1byte.c libffi.call/cls_float.c \
|
|
||||||
libffi.call/cls_2byte.c libffi.call/closure_fn4.c \
|
|
||||||
libffi.call/return_fl2.c libffi.call/nested_struct7.c \
|
|
||||||
libffi.call/cls_uint.c libffi.call/cls_align_sint64.c \
|
|
||||||
libffi.call/float1.c libffi.call/cls_19byte.c \
|
|
||||||
libffi.call/nested_struct1.c libffi.call/cls_4byte.c \
|
|
||||||
libffi.call/return_fl1.c libffi.call/cls_align_pointer.c \
|
|
||||||
libffi.call/nested_struct4.c libffi.call/nested_struct3.c \
|
|
||||||
libffi.call/struct7.c libffi.call/nested_struct9.c \
|
|
||||||
libffi.call/cls_sshort.c libffi.call/cls_ulonglong.c \
|
|
||||||
libffi.call/cls_pointer_stack.c libffi.call/cls_multi_uchar.c \
|
|
||||||
libffi.call/testclosure.c libffi.call/cls_3byte1.c \
|
|
||||||
libffi.call/struct6.c libffi.call/return_uc.c libffi.call/return_ll1.c \
|
|
||||||
libffi.call/cls_ushort.c libffi.call/stret_medium2.c \
|
|
||||||
libffi.call/cls_multi_ushortchar.c libffi.call/return_dbl2.c \
|
|
||||||
libffi.call/closure_loc_fn0.c libffi.call/return_sc.c \
|
|
||||||
libffi.call/nested_struct8.c libffi.call/cls_7_1_byte.c \
|
|
||||||
libffi.call/return_ll.c libffi.call/cls_pointer.c \
|
|
||||||
libffi.call/err_bad_abi.c libffi.call/return_dbl1.c \
|
|
||||||
libffi.call/call.exp libffi.call/ffitest.h libffi.call/strlen.c \
|
|
||||||
libffi.call/return_sl.c libffi.call/cls_1_1byte.c \
|
|
||||||
libffi.call/struct1.c libffi.call/cls_64byte.c libffi.call/return_ul.c \
|
|
||||||
libffi.call/cls_double.c libffi.call/many_win32.c \
|
|
||||||
libffi.call/cls_16byte.c libffi.call/cls_align_double.c \
|
|
||||||
libffi.call/cls_align_uint16.c libffi.call/cls_9byte1.c \
|
|
||||||
libffi.call/cls_multi_sshortchar.c libffi.call/cls_multi_ushort.c \
|
|
||||||
libffi.call/closure_stdcall.c libffi.call/return_fl.c \
|
|
||||||
libffi.call/strlen_win32.c libffi.call/return_ldl.c \
|
|
||||||
libffi.call/cls_align_float.c libffi.call/struct3.c \
|
|
||||||
libffi.call/cls_uchar.c libffi.call/cls_sint.c libffi.call/float2.c \
|
|
||||||
libffi.call/cls_align_longdouble_split.c \
|
|
||||||
libffi.call/cls_longdouble_va.c libffi.call/cls_multi_sshort.c \
|
|
||||||
libffi.call/stret_large.c libffi.call/cls_align_sint16.c \
|
|
||||||
libffi.call/nested_struct6.c libffi.call/cls_5byte.c \
|
|
||||||
libffi.call/return_dbl.c libffi.call/cls_20byte.c \
|
|
||||||
libffi.call/cls_8byte.c libffi.call/pyobjc-tc.c \
|
|
||||||
libffi.call/cls_24byte.c libffi.call/cls_align_longdouble_split2.c \
|
|
||||||
libffi.call/cls_6_1_byte.c libffi.call/cls_schar.c \
|
|
||||||
libffi.call/cls_18byte.c libffi.call/closure_fn3.c \
|
|
||||||
libffi.call/err_bad_typedef.c libffi.call/closure_fn2.c \
|
|
||||||
libffi.call/struct2.c libffi.call/cls_3byte2.c \
|
|
||||||
libffi.call/cls_align_longdouble.c libffi.call/cls_20byte1.c \
|
|
||||||
libffi.call/return_fl3.c libffi.call/cls_align_uint32.c \
|
|
||||||
libffi.call/problem1.c libffi.call/float4.c \
|
|
||||||
libffi.call/cls_align_uint64.c libffi.call/struct9.c \
|
|
||||||
libffi.call/closure_fn5.c libffi.call/cls_align_sint32.c \
|
|
||||||
libffi.call/closure_fn0.c libffi.call/closure_fn6.c \
|
|
||||||
libffi.call/struct4.c libffi.call/nested_struct2.c \
|
|
||||||
libffi.call/cls_6byte.c libffi.call/cls_7byte.c libffi.call/many.c \
|
|
||||||
libffi.call/struct8.c libffi.call/negint.c libffi.call/struct5.c \
|
|
||||||
libffi.call/cls_12byte.c libffi.call/cls_double_va.c \
|
|
||||||
libffi.call/cls_longdouble.c libffi.call/cls_9byte2.c \
|
|
||||||
libffi.call/nested_struct10.c libffi.call/nested_struct5.c \
|
|
||||||
libffi.call/huge_struct.c
|
|
||||||
|
|
||||||
all: all-am
|
|
||||||
|
|
||||||
.SUFFIXES:
|
|
||||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
|
||||||
@for dep in $?; do \
|
|
||||||
case '$(am__configure_deps)' in \
|
|
||||||
*$$dep*) \
|
|
||||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
|
||||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
|
||||||
exit 1;; \
|
|
||||||
esac; \
|
|
||||||
done; \
|
|
||||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \
|
|
||||||
$(am__cd) $(top_srcdir) && \
|
|
||||||
$(AUTOMAKE) --foreign testsuite/Makefile
|
|
||||||
.PRECIOUS: Makefile
|
|
||||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
|
||||||
@case '$?' in \
|
|
||||||
*config.status*) \
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
|
||||||
*) \
|
|
||||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
|
||||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
|
||||||
esac;
|
|
||||||
|
|
||||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
|
||||||
|
|
||||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
|
||||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
|
||||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
|
||||||
$(am__aclocal_m4_deps):
|
|
||||||
|
|
||||||
mostlyclean-libtool:
|
|
||||||
-rm -f *.lo
|
|
||||||
|
|
||||||
clean-libtool:
|
|
||||||
-rm -rf .libs _libs
|
|
||||||
tags: TAGS
|
|
||||||
TAGS:
|
|
||||||
|
|
||||||
ctags: CTAGS
|
|
||||||
CTAGS:
|
|
||||||
|
|
||||||
|
|
||||||
check-DEJAGNU: site.exp
|
|
||||||
srcdir='$(srcdir)'; export srcdir; \
|
|
||||||
EXPECT=$(EXPECT); export EXPECT; \
|
|
||||||
runtest=$(RUNTEST); \
|
|
||||||
if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \
|
|
||||||
exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \
|
|
||||||
if $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \
|
|
||||||
then :; else exit_status=1; fi; \
|
|
||||||
done; \
|
|
||||||
else echo "WARNING: could not find \`runtest'" 1>&2; :;\
|
|
||||||
fi; \
|
|
||||||
exit $$exit_status
|
|
||||||
site.exp: Makefile $(EXTRA_DEJAGNU_SITE_CONFIG)
|
|
||||||
@echo 'Making a new site.exp file...'
|
|
||||||
@echo '## these variables are automatically generated by make ##' >site.tmp
|
|
||||||
@echo '# Do not edit here. If you wish to override these values' >>site.tmp
|
|
||||||
@echo '# edit the last section' >>site.tmp
|
|
||||||
@echo 'set srcdir "$(srcdir)"' >>site.tmp
|
|
||||||
@echo "set objdir `pwd`" >>site.tmp
|
|
||||||
@echo 'set build_alias "$(build_alias)"' >>site.tmp
|
|
||||||
@echo 'set build_triplet $(build_triplet)' >>site.tmp
|
|
||||||
@echo 'set host_alias "$(host_alias)"' >>site.tmp
|
|
||||||
@echo 'set host_triplet $(host_triplet)' >>site.tmp
|
|
||||||
@echo 'set target_alias "$(target_alias)"' >>site.tmp
|
|
||||||
@echo 'set target_triplet $(target_triplet)' >>site.tmp
|
|
||||||
@list='$(EXTRA_DEJAGNU_SITE_CONFIG)'; for f in $$list; do \
|
|
||||||
echo "## Begin content included from file $$f. Do not modify. ##" \
|
|
||||||
&& cat `test -f "$$f" || echo '$(srcdir)/'`$$f \
|
|
||||||
&& echo "## End content included from file $$f. ##" \
|
|
||||||
|| exit 1; \
|
|
||||||
done >> site.tmp
|
|
||||||
@echo "## End of auto-generated content; you can edit from here. ##" >> site.tmp
|
|
||||||
@if test -f site.exp; then \
|
|
||||||
sed -e '1,/^## End of auto-generated content.*##/d' site.exp >> site.tmp; \
|
|
||||||
fi
|
|
||||||
@-rm -f site.bak
|
|
||||||
@test ! -f site.exp || mv site.exp site.bak
|
|
||||||
@mv site.tmp site.exp
|
|
||||||
|
|
||||||
distclean-DEJAGNU:
|
|
||||||
-rm -f site.exp site.bak
|
|
||||||
-l='$(DEJATOOL)'; for tool in $$l; do \
|
|
||||||
rm -f $$tool.sum $$tool.log; \
|
|
||||||
done
|
|
||||||
|
|
||||||
distdir: $(DISTFILES)
|
|
||||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
|
||||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
|
||||||
list='$(DISTFILES)'; \
|
|
||||||
dist_files=`for file in $$list; do echo $$file; done | \
|
|
||||||
sed -e "s|^$$srcdirstrip/||;t" \
|
|
||||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
|
||||||
case $$dist_files in \
|
|
||||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
|
||||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
|
||||||
sort -u` ;; \
|
|
||||||
esac; \
|
|
||||||
for file in $$dist_files; do \
|
|
||||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
|
||||||
if test -d $$d/$$file; then \
|
|
||||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
|
||||||
if test -d "$(distdir)/$$file"; then \
|
|
||||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
|
||||||
fi; \
|
|
||||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
|
||||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
|
||||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
|
||||||
fi; \
|
|
||||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
|
||||||
else \
|
|
||||||
test -f "$(distdir)/$$file" \
|
|
||||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
|
||||||
|| exit 1; \
|
|
||||||
fi; \
|
|
||||||
done
|
|
||||||
check-am: all-am
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) check-DEJAGNU
|
|
||||||
check: check-am
|
|
||||||
all-am: Makefile
|
|
||||||
installdirs:
|
|
||||||
install: install-am
|
|
||||||
install-exec: install-exec-am
|
|
||||||
install-data: install-data-am
|
|
||||||
uninstall: uninstall-am
|
|
||||||
|
|
||||||
install-am: all-am
|
|
||||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
|
||||||
|
|
||||||
installcheck: installcheck-am
|
|
||||||
install-strip:
|
|
||||||
if test -z '$(STRIP)'; then \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
|
||||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
|
||||||
install; \
|
|
||||||
else \
|
|
||||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
|
||||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
|
||||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
|
||||||
fi
|
|
||||||
mostlyclean-generic:
|
|
||||||
|
|
||||||
clean-generic:
|
|
||||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
|
||||||
|
|
||||||
distclean-generic:
|
|
||||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
|
||||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
|
||||||
|
|
||||||
maintainer-clean-generic:
|
|
||||||
@echo "This command is intended for maintainers to use"
|
|
||||||
@echo "it deletes files that may require special tools to rebuild."
|
|
||||||
clean: clean-am
|
|
||||||
|
|
||||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
|
||||||
|
|
||||||
distclean: distclean-am
|
|
||||||
-rm -f Makefile
|
|
||||||
distclean-am: clean-am distclean-DEJAGNU distclean-generic
|
|
||||||
|
|
||||||
dvi: dvi-am
|
|
||||||
|
|
||||||
dvi-am:
|
|
||||||
|
|
||||||
html: html-am
|
|
||||||
|
|
||||||
html-am:
|
|
||||||
|
|
||||||
info: info-am
|
|
||||||
|
|
||||||
info-am:
|
|
||||||
|
|
||||||
install-data-am:
|
|
||||||
|
|
||||||
install-dvi: install-dvi-am
|
|
||||||
|
|
||||||
install-dvi-am:
|
|
||||||
|
|
||||||
install-exec-am:
|
|
||||||
|
|
||||||
install-html: install-html-am
|
|
||||||
|
|
||||||
install-html-am:
|
|
||||||
|
|
||||||
install-info: install-info-am
|
|
||||||
|
|
||||||
install-info-am:
|
|
||||||
|
|
||||||
install-man:
|
|
||||||
|
|
||||||
install-pdf: install-pdf-am
|
|
||||||
|
|
||||||
install-pdf-am:
|
|
||||||
|
|
||||||
install-ps: install-ps-am
|
|
||||||
|
|
||||||
install-ps-am:
|
|
||||||
|
|
||||||
installcheck-am:
|
|
||||||
|
|
||||||
maintainer-clean: maintainer-clean-am
|
|
||||||
-rm -f Makefile
|
|
||||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
|
||||||
|
|
||||||
mostlyclean: mostlyclean-am
|
|
||||||
|
|
||||||
mostlyclean-am: mostlyclean-generic mostlyclean-libtool
|
|
||||||
|
|
||||||
pdf: pdf-am
|
|
||||||
|
|
||||||
pdf-am:
|
|
||||||
|
|
||||||
ps: ps-am
|
|
||||||
|
|
||||||
ps-am:
|
|
||||||
|
|
||||||
uninstall-am:
|
|
||||||
|
|
||||||
.MAKE: check-am install-am install-strip
|
|
||||||
|
|
||||||
.PHONY: all all-am check check-DEJAGNU check-am clean clean-generic \
|
|
||||||
clean-libtool distclean distclean-DEJAGNU distclean-generic \
|
|
||||||
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
|
||||||
install install-am install-data install-data-am install-dvi \
|
|
||||||
install-dvi-am install-exec install-exec-am install-html \
|
|
||||||
install-html-am install-info install-info-am install-man \
|
|
||||||
install-pdf install-pdf-am install-ps install-ps-am \
|
|
||||||
install-strip installcheck installcheck-am installdirs \
|
|
||||||
maintainer-clean maintainer-clean-generic mostlyclean \
|
|
||||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
|
||||||
uninstall uninstall-am
|
|
||||||
|
|
||||||
|
|
||||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
|
||||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
|
||||||
.NOEXPORT:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,369 +0,0 @@
|
|||||||
Status
|
|
||||||
======
|
|
||||||
|
|
||||||
libffi-3.0.12 was released on XXXXXXX. Check the libffi web page for
|
|
||||||
updates: <URL:http://sourceware.org/libffi/>.
|
|
||||||
|
|
||||||
|
|
||||||
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 essentially 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Supported Platforms
|
|
||||||
===================
|
|
||||||
|
|
||||||
Libffi has been ported to many different platforms.
|
|
||||||
For specific configuration details and testing status, please
|
|
||||||
refer to the wiki page here:
|
|
||||||
|
|
||||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
|
|
||||||
|
|
||||||
At the time of release, the following basic configurations have been
|
|
||||||
tested:
|
|
||||||
|
|
||||||
|-----------------+------------------|
|
|
||||||
| Architecture | Operating System |
|
|
||||||
|-----------------+------------------|
|
|
||||||
| AArch64 | Linux |
|
|
||||||
| Alpha | Linux |
|
|
||||||
| Alpha | Tru64 |
|
|
||||||
| ARM | Linux |
|
|
||||||
| ARM | iOS |
|
|
||||||
| AVR32 | Linux |
|
|
||||||
| Blackfin | uClinux |
|
|
||||||
| HPPA | HPUX |
|
|
||||||
| IA-64 | Linux |
|
|
||||||
| M68K | FreeMiNT |
|
|
||||||
| M68K | RTEMS |
|
|
||||||
| MIPS | IRIX |
|
|
||||||
| MIPS | Linux |
|
|
||||||
| MIPS | RTEMS |
|
|
||||||
| MIPS64 | Linux |
|
|
||||||
| PowerPC | AMIGA |
|
|
||||||
| PowerPC | Linux |
|
|
||||||
| PowerPC | Mac OSX |
|
|
||||||
| PowerPC | FreeBSD |
|
|
||||||
| PowerPC64 | Linux |
|
|
||||||
| S390 | Linux |
|
|
||||||
| S390X | Linux |
|
|
||||||
| SPARC | Linux |
|
|
||||||
| SPARC | Solaris |
|
|
||||||
| SPARC64 | Linux |
|
|
||||||
| SPARC64 | FreeBSD |
|
|
||||||
| TILE-Gx/TILEPro | Linux |
|
|
||||||
| X86 | FreeBSD |
|
|
||||||
| X86 | Interix |
|
|
||||||
| X86 | kFreeBSD |
|
|
||||||
| X86 | Linux |
|
|
||||||
| X86 | Mac OSX |
|
|
||||||
| X86 | OpenBSD |
|
|
||||||
| X86 | OS/2 |
|
|
||||||
| X86 | Solaris |
|
|
||||||
| X86 | Windows/Cygwin |
|
|
||||||
| X86 | Windows/MingW |
|
|
||||||
| X86-64 | FreeBSD |
|
|
||||||
| X86-64 | Linux |
|
|
||||||
| X86-64 | Linux/x32 |
|
|
||||||
| X86-64 | OpenBSD |
|
|
||||||
| X86-64 | Windows/MingW |
|
|
||||||
|-----------------+------------------|
|
|
||||||
|
|
||||||
Please send additional platform test results to
|
|
||||||
libffi-discuss@sourceware.org and feel free to update the wiki page
|
|
||||||
above.
|
|
||||||
|
|
||||||
Installing libffi
|
|
||||||
=================
|
|
||||||
|
|
||||||
First you must configure the distribution for your particular
|
|
||||||
system. Go to the directory you wish to build libffi in and run the
|
|
||||||
"configure" program found in the root directory of the libffi source
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
You may want to tell configure where to install the libffi library and
|
|
||||||
header files. To do that, use the --prefix configure switch. Libffi
|
|
||||||
will install under /usr/local by default.
|
|
||||||
|
|
||||||
If you want to enable extra run-time debugging checks use the the
|
|
||||||
--enable-debug configure switch. This is useful when your program dies
|
|
||||||
mysteriously while using libffi.
|
|
||||||
|
|
||||||
Another useful configure switch is --enable-purify-safety. Using this
|
|
||||||
will add some extra code which will suppress certain warnings when you
|
|
||||||
are using Purify with libffi. Only use this switch when using
|
|
||||||
Purify, as it will slow down the library.
|
|
||||||
|
|
||||||
It's also possible to build libffi on Windows platforms with
|
|
||||||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
|
||||||
wrapper script during configuration like so:
|
|
||||||
|
|
||||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
|
||||||
|
|
||||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
|
||||||
You may also need to specify --build appropriately. When building with MSVC
|
|
||||||
under a MingW environment, you may need to remove the line in configure
|
|
||||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
|
||||||
present in MingW, and is not required when using MingW-style paths.)
|
|
||||||
|
|
||||||
For iOS builds, the 'libffi.xcodeproj' Xcode project is available.
|
|
||||||
|
|
||||||
Configure has many other options. Use "configure --help" to see them all.
|
|
||||||
|
|
||||||
Once configure has finished, type "make". Note that you must be using
|
|
||||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
|
||||||
|
|
||||||
To ensure that libffi is working as advertised, type "make check".
|
|
||||||
This will require that you have DejaGNU installed.
|
|
||||||
|
|
||||||
To install the library and header files, type "make install".
|
|
||||||
|
|
||||||
|
|
||||||
History
|
|
||||||
=======
|
|
||||||
|
|
||||||
See the ChangeLog files for details.
|
|
||||||
|
|
||||||
3.0.12 XXX-XX-XX
|
|
||||||
Add Blackfin support.
|
|
||||||
Add TILE-Gx/TILEPro support.
|
|
||||||
Add AArch64 support.
|
|
||||||
|
|
||||||
3.0.11 Apr-11-12
|
|
||||||
Lots of build fixes.
|
|
||||||
Add Amiga newer MacOS support.
|
|
||||||
Add support for variadic functions (ffi_prep_cif_var).
|
|
||||||
Add Linux/x32 support.
|
|
||||||
Add thiscall, fastcall and MSVC cdecl support on Windows.
|
|
||||||
Add Amiga and newer MacOS support.
|
|
||||||
Add m68k FreeMiNT support.
|
|
||||||
Integration with iOS' xcode build tools.
|
|
||||||
Fix Octeon and MC68881 support.
|
|
||||||
Fix code pessimizations.
|
|
||||||
Lots of build fixes.
|
|
||||||
|
|
||||||
3.0.10 Aug-23-11
|
|
||||||
Add support for Apple's iOS.
|
|
||||||
Add support for ARM VFP ABI.
|
|
||||||
Add RTEMS support for MIPS and M68K.
|
|
||||||
Fix instruction cache clearing problems on
|
|
||||||
ARM and SPARC.
|
|
||||||
Fix the N64 build on mips-sgi-irix6.5.
|
|
||||||
Enable builds with Microsoft's compiler.
|
|
||||||
Enable x86 builds with Oracle's Solaris compiler.
|
|
||||||
Fix support for calling code compiled with Oracle's Sparc
|
|
||||||
Solaris compiler.
|
|
||||||
Testsuite fixes for Tru64 Unix.
|
|
||||||
Additional platform support.
|
|
||||||
|
|
||||||
3.0.9 Dec-31-09
|
|
||||||
Add AVR32 and win64 ports. Add ARM softfp support.
|
|
||||||
Many fixes for AIX, Solaris, HP-UX, *BSD.
|
|
||||||
Several PowerPC and x86-64 bug fixes.
|
|
||||||
Build DLL for windows.
|
|
||||||
|
|
||||||
3.0.8 Dec-19-08
|
|
||||||
Add *BSD, BeOS, and PA-Linux support.
|
|
||||||
|
|
||||||
3.0.7 Nov-11-08
|
|
||||||
Fix for ppc FreeBSD.
|
|
||||||
(thanks to Andreas Tobler)
|
|
||||||
|
|
||||||
3.0.6 Jul-17-08
|
|
||||||
Fix for closures on sh.
|
|
||||||
Mark the sh/sh64 stack as non-executable.
|
|
||||||
(both thanks to Kaz Kojima)
|
|
||||||
|
|
||||||
3.0.5 Apr-3-08
|
|
||||||
Fix libffi.pc file.
|
|
||||||
Fix #define ARM for IcedTea users.
|
|
||||||
Fix x86 closure bug.
|
|
||||||
|
|
||||||
3.0.4 Feb-24-08
|
|
||||||
Fix x86 OpenBSD configury.
|
|
||||||
|
|
||||||
3.0.3 Feb-22-08
|
|
||||||
Enable x86 OpenBSD thanks to Thomas Heller, and
|
|
||||||
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
|
|
||||||
Clean up test instruction in README.
|
|
||||||
|
|
||||||
3.0.2 Feb-21-08
|
|
||||||
Improved x86 FreeBSD support.
|
|
||||||
Thanks to Björn König.
|
|
||||||
|
|
||||||
3.0.1 Feb-15-08
|
|
||||||
Fix instruction cache flushing bug on MIPS.
|
|
||||||
Thanks to David Daney.
|
|
||||||
|
|
||||||
3.0.0 Feb-15-08
|
|
||||||
Many changes, mostly thanks to the GCC project.
|
|
||||||
Cygnus Solutions is now Red Hat.
|
|
||||||
|
|
||||||
[10 years go by...]
|
|
||||||
|
|
||||||
1.20 Oct-5-98
|
|
||||||
Raffaele Sena produces ARM port.
|
|
||||||
|
|
||||||
1.19 Oct-5-98
|
|
||||||
Fixed x86 long double and long long return support.
|
|
||||||
m68k bug fixes from Andreas Schwab.
|
|
||||||
Patch for DU assembler compatibility for the Alpha from Richard
|
|
||||||
Henderson.
|
|
||||||
|
|
||||||
1.18 Apr-17-98
|
|
||||||
Bug fixes and MIPS configuration changes.
|
|
||||||
|
|
||||||
1.17 Feb-24-98
|
|
||||||
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
|
|
||||||
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
|
|
||||||
|
|
||||||
1.16 Feb-11-98
|
|
||||||
Richard Henderson produces Alpha port.
|
|
||||||
|
|
||||||
1.15 Dec-4-97
|
|
||||||
Fixed an n32 ABI bug. New libtool, auto* support.
|
|
||||||
|
|
||||||
1.14 May-13-97
|
|
||||||
libtool is now used to generate shared and static libraries.
|
|
||||||
Fixed a minor portability problem reported by Russ McManus
|
|
||||||
<mcmanr@eq.gs.com>.
|
|
||||||
|
|
||||||
1.13 Dec-2-96
|
|
||||||
Added --enable-purify-safety to keep Purify from complaining
|
|
||||||
about certain low level code.
|
|
||||||
Sparc fix for calling functions with < 6 args.
|
|
||||||
Linux x86 a.out fix.
|
|
||||||
|
|
||||||
1.12 Nov-22-96
|
|
||||||
Added missing ffi_type_void, needed for supporting void return
|
|
||||||
types. Fixed test case for non MIPS machines. Cygnus Support
|
|
||||||
is now Cygnus Solutions.
|
|
||||||
|
|
||||||
1.11 Oct-30-96
|
|
||||||
Added notes about GNU make.
|
|
||||||
|
|
||||||
1.10 Oct-29-96
|
|
||||||
Added configuration fix for non GNU compilers.
|
|
||||||
|
|
||||||
1.09 Oct-29-96
|
|
||||||
Added --enable-debug configure switch. Clean-ups based on LCLint
|
|
||||||
feedback. ffi_mips.h is always installed. Many configuration
|
|
||||||
fixes. Fixed ffitest.c for sparc builds.
|
|
||||||
|
|
||||||
1.08 Oct-15-96
|
|
||||||
Fixed n32 problem. Many clean-ups.
|
|
||||||
|
|
||||||
1.07 Oct-14-96
|
|
||||||
Gordon Irlam rewrites v8.S again. Bug fixes.
|
|
||||||
|
|
||||||
1.06 Oct-14-96
|
|
||||||
Gordon Irlam improved the sparc port.
|
|
||||||
|
|
||||||
1.05 Oct-14-96
|
|
||||||
Interface changes based on feedback.
|
|
||||||
|
|
||||||
1.04 Oct-11-96
|
|
||||||
Sparc port complete (modulo struct passing bug).
|
|
||||||
|
|
||||||
1.03 Oct-10-96
|
|
||||||
Passing struct args, and returning struct values works for
|
|
||||||
all architectures/calling conventions. Expanded tests.
|
|
||||||
|
|
||||||
1.02 Oct-9-96
|
|
||||||
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
|
|
||||||
Added "make test".
|
|
||||||
|
|
||||||
1.01 Oct-8-96
|
|
||||||
Fixed float passing bug in mips version. Restructured some
|
|
||||||
of the code. Builds cleanly with SGI tools.
|
|
||||||
|
|
||||||
1.00 Oct-7-96
|
|
||||||
First release. No public announcement.
|
|
||||||
|
|
||||||
|
|
||||||
Authors & Credits
|
|
||||||
=================
|
|
||||||
|
|
||||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
|
||||||
|
|
||||||
The developers of the GNU Compiler Collection project have made
|
|
||||||
innumerable valuable contributions. See the ChangeLog file for
|
|
||||||
details.
|
|
||||||
|
|
||||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
|
||||||
gencall library for Silicon Graphics machines.
|
|
||||||
|
|
||||||
The closure mechanism was designed and implemented by Kresten Krab
|
|
||||||
Thorup.
|
|
||||||
|
|
||||||
Major processor architecture ports were contributed by the following
|
|
||||||
developers:
|
|
||||||
|
|
||||||
aarch64 Marcus Shawcroft, James Greenhalgh
|
|
||||||
alpha Richard Henderson
|
|
||||||
arm Raffaele Sena
|
|
||||||
blackfin Alexandre Keunecke I. de Mendonca
|
|
||||||
cris Simon Posnjak, Hans-Peter Nilsson
|
|
||||||
frv Anthony Green
|
|
||||||
ia64 Hans Boehm
|
|
||||||
m32r Kazuhiro Inaoka
|
|
||||||
m68k Andreas Schwab
|
|
||||||
mips Anthony Green, Casey Marshall
|
|
||||||
mips64 David Daney
|
|
||||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
|
||||||
powerpc Geoffrey Keating, Andreas Tobler,
|
|
||||||
David Edelsohn, John Hornkvist
|
|
||||||
powerpc64 Jakub Jelinek
|
|
||||||
s390 Gerhard Tonn, Ulrich Weigand
|
|
||||||
sh Kaz Kojima
|
|
||||||
sh64 Kaz Kojima
|
|
||||||
sparc Anthony Green, Gordon Irlam
|
|
||||||
tile-gx/tilepro Walter Lee
|
|
||||||
x86 Anthony Green, Jon Beniston
|
|
||||||
x86-64 Bo Thorsen
|
|
||||||
|
|
||||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
|
||||||
stepping through the code and tracking down bugs.
|
|
||||||
|
|
||||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
|
||||||
configuration help.
|
|
||||||
|
|
||||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
|
||||||
interface.
|
|
||||||
|
|
||||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
|
||||||
|
|
||||||
Alex Oliva solved the executable page problem for SElinux.
|
|
||||||
|
|
||||||
The list above is almost certainly incomplete and inaccurate. I'm
|
|
||||||
happy to make corrections or additions upon request.
|
|
||||||
|
|
||||||
If you have a problem, or have found a bug, please send a note to the
|
|
||||||
author at green@moxielogic.com, or the project mailing list at
|
|
||||||
libffi-discuss@sourceware.org.
|
|
||||||
17404
.pc/emutramp/configure
vendored
17404
.pc/emutramp/configure
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,517 +0,0 @@
|
|||||||
dnl Process this with autoconf to create configure
|
|
||||||
|
|
||||||
AC_PREREQ(2.68)
|
|
||||||
|
|
||||||
AC_INIT([libffi], [3.0.11], [http://github.com/atgreen/libffi/issues])
|
|
||||||
AC_CONFIG_HEADERS([fficonfig.h])
|
|
||||||
|
|
||||||
AC_CANONICAL_SYSTEM
|
|
||||||
target_alias=${target_alias-$host_alias}
|
|
||||||
|
|
||||||
. ${srcdir}/configure.host
|
|
||||||
|
|
||||||
AX_ENABLE_BUILDDIR
|
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE
|
|
||||||
|
|
||||||
# The same as in boehm-gc and libstdc++. Have to borrow it from there.
|
|
||||||
# We must force CC to /not/ be precious variables; otherwise
|
|
||||||
# the wrong, non-multilib-adjusted value will be used in multilibs.
|
|
||||||
# As a side effect, we have to subst CFLAGS ourselves.
|
|
||||||
# Also save and restore CFLAGS, since AC_PROG_CC will come up with
|
|
||||||
# defaults of its own if none are provided.
|
|
||||||
|
|
||||||
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
|
|
||||||
m4_define([_AC_ARG_VAR_PRECIOUS],[])
|
|
||||||
save_CFLAGS=$CFLAGS
|
|
||||||
AC_PROG_CC
|
|
||||||
CFLAGS=$save_CFLAGS
|
|
||||||
m4_undefine([_AC_ARG_VAR_PRECIOUS])
|
|
||||||
m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
|
|
||||||
|
|
||||||
AC_SUBST(CFLAGS)
|
|
||||||
|
|
||||||
AM_PROG_AS
|
|
||||||
AM_PROG_CC_C_O
|
|
||||||
AC_PROG_LIBTOOL
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
|
|
||||||
AX_CC_MAXOPT
|
|
||||||
AX_CFLAGS_WARN_ALL
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
CFLAGS="$CFLAGS -fexceptions"
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_MAINTAINER_MODE
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS(sys/mman.h)
|
|
||||||
AC_CHECK_FUNCS(mmap)
|
|
||||||
AC_FUNC_MMAP_BLACKLIST
|
|
||||||
|
|
||||||
dnl The -no-testsuite modules omit the test subdir.
|
|
||||||
AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite)
|
|
||||||
|
|
||||||
TARGETDIR="unknown"
|
|
||||||
case "$host" in
|
|
||||||
aarch64*-*-*)
|
|
||||||
TARGET=AARCH64; TARGETDIR=aarch64
|
|
||||||
;;
|
|
||||||
|
|
||||||
alpha*-*-*)
|
|
||||||
TARGET=ALPHA; TARGETDIR=alpha;
|
|
||||||
# Support 128-bit long double, changeable via command-line switch.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)'
|
|
||||||
;;
|
|
||||||
|
|
||||||
arm*-*-*)
|
|
||||||
TARGET=ARM; TARGETDIR=arm
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd* | amd64-*-openbsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
amd64-*-freebsd*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
avr32*-*-*)
|
|
||||||
TARGET=AVR32; TARGETDIR=avr32
|
|
||||||
;;
|
|
||||||
|
|
||||||
bfin*)
|
|
||||||
TARGET=BFIN; TARGETDIR=bfin
|
|
||||||
;;
|
|
||||||
|
|
||||||
cris-*-*)
|
|
||||||
TARGET=LIBFFI_CRIS; TARGETDIR=cris
|
|
||||||
;;
|
|
||||||
|
|
||||||
frv-*-*)
|
|
||||||
TARGET=FRV; TARGETDIR=frv
|
|
||||||
;;
|
|
||||||
|
|
||||||
hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*)
|
|
||||||
TARGET=PA_LINUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*64-*-hpux*)
|
|
||||||
TARGET=PA64_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
hppa*-*-hpux*)
|
|
||||||
TARGET=PA_HPUX; TARGETDIR=pa
|
|
||||||
;;
|
|
||||||
|
|
||||||
i?86-*-freebsd* | i?86-*-openbsd*)
|
|
||||||
TARGET=X86_FREEBSD; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-win32* | i?86-*-cygwin* | i?86-*-mingw* | i?86-*-os2* | i?86-*-interix*)
|
|
||||||
TARGET=X86_WIN32; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
i?86-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-solaris2.1[[0-9]]*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
i?86-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
ia64*-*-*)
|
|
||||||
TARGET=IA64; TARGETDIR=ia64
|
|
||||||
;;
|
|
||||||
|
|
||||||
m32r*-*-*)
|
|
||||||
TARGET=M32R; TARGETDIR=m32r
|
|
||||||
;;
|
|
||||||
|
|
||||||
m68k-*-*)
|
|
||||||
TARGET=M68K; TARGETDIR=m68k
|
|
||||||
;;
|
|
||||||
|
|
||||||
mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*)
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
mips*-*-linux* | mips*-*-openbsd*)
|
|
||||||
# Support 128-bit long double for NewABI.
|
|
||||||
HAVE_LONG_DOUBLE='defined(__mips64)'
|
|
||||||
TARGET=MIPS; TARGETDIR=mips
|
|
||||||
;;
|
|
||||||
|
|
||||||
moxie-*-*)
|
|
||||||
TARGET=MOXIE; TARGETDIR=moxie
|
|
||||||
;;
|
|
||||||
|
|
||||||
powerpc*-*-linux* | powerpc-*-sysv*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-amigaos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-beos*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-darwin* | powerpc64-*-darwin*)
|
|
||||||
TARGET=POWERPC_DARWIN; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-aix* | rs6000-*-aix*)
|
|
||||||
TARGET=POWERPC_AIX; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc-*-freebsd* | powerpc-*-openbsd*)
|
|
||||||
TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc64-*-freebsd*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
powerpc*-*-rtems*)
|
|
||||||
TARGET=POWERPC; TARGETDIR=powerpc
|
|
||||||
;;
|
|
||||||
|
|
||||||
s390-*-* | s390x-*-*)
|
|
||||||
TARGET=S390; TARGETDIR=s390
|
|
||||||
;;
|
|
||||||
|
|
||||||
sh-*-* | sh[[34]]*-*-*)
|
|
||||||
TARGET=SH; TARGETDIR=sh
|
|
||||||
;;
|
|
||||||
sh64-*-* | sh5*-*-*)
|
|
||||||
TARGET=SH64; TARGETDIR=sh64
|
|
||||||
;;
|
|
||||||
|
|
||||||
sparc*-*-*)
|
|
||||||
TARGET=SPARC; TARGETDIR=sparc
|
|
||||||
;;
|
|
||||||
|
|
||||||
tile*-*)
|
|
||||||
TARGET=TILE; TARGETDIR=tile
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-darwin*)
|
|
||||||
TARGET=X86_DARWIN; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-cygwin* | x86_64-*-mingw*)
|
|
||||||
TARGET=X86_WIN64; TARGETDIR=x86
|
|
||||||
# All mingw/cygwin/win32 builds require -no-undefined for sharedlib.
|
|
||||||
# We must also check with_cross_host to decide if this is a native
|
|
||||||
# or cross-build and select where to install dlls appropriately.
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"';
|
|
||||||
else
|
|
||||||
AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"';
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
x86_64-*-*)
|
|
||||||
TARGET=X86_64; TARGETDIR=x86
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
AC_SUBST(AM_RUNTESTFLAGS)
|
|
||||||
AC_SUBST(AM_LTLDFLAGS)
|
|
||||||
|
|
||||||
if test $TARGETDIR = unknown; then
|
|
||||||
AC_MSG_ERROR(["libffi has not been ported to $host."])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS)
|
|
||||||
AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN)
|
|
||||||
AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC)
|
|
||||||
AM_CONDITIONAL(X86, test x$TARGET = xX86)
|
|
||||||
AM_CONDITIONAL(X86_FREEBSD, test x$TARGET = xX86_FREEBSD)
|
|
||||||
AM_CONDITIONAL(X86_WIN32, test x$TARGET = xX86_WIN32)
|
|
||||||
AM_CONDITIONAL(X86_WIN64, test x$TARGET = xX86_WIN64)
|
|
||||||
AM_CONDITIONAL(X86_DARWIN, test x$TARGET = xX86_DARWIN)
|
|
||||||
AM_CONDITIONAL(ALPHA, test x$TARGET = xALPHA)
|
|
||||||
AM_CONDITIONAL(IA64, test x$TARGET = xIA64)
|
|
||||||
AM_CONDITIONAL(M32R, test x$TARGET = xM32R)
|
|
||||||
AM_CONDITIONAL(M68K, test x$TARGET = xM68K)
|
|
||||||
AM_CONDITIONAL(MOXIE, test x$TARGET = xMOXIE)
|
|
||||||
AM_CONDITIONAL(POWERPC, test x$TARGET = xPOWERPC)
|
|
||||||
AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX)
|
|
||||||
AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN)
|
|
||||||
AM_CONDITIONAL(POWERPC_FREEBSD, test x$TARGET = xPOWERPC_FREEBSD)
|
|
||||||
AM_CONDITIONAL(AARCH64, test x$TARGET = xAARCH64)
|
|
||||||
AM_CONDITIONAL(ARM, test x$TARGET = xARM)
|
|
||||||
AM_CONDITIONAL(AVR32, test x$TARGET = xAVR32)
|
|
||||||
AM_CONDITIONAL(LIBFFI_CRIS, test x$TARGET = xLIBFFI_CRIS)
|
|
||||||
AM_CONDITIONAL(FRV, test x$TARGET = xFRV)
|
|
||||||
AM_CONDITIONAL(S390, test x$TARGET = xS390)
|
|
||||||
AM_CONDITIONAL(X86_64, test x$TARGET = xX86_64)
|
|
||||||
AM_CONDITIONAL(SH, test x$TARGET = xSH)
|
|
||||||
AM_CONDITIONAL(SH64, test x$TARGET = xSH64)
|
|
||||||
AM_CONDITIONAL(PA_LINUX, test x$TARGET = xPA_LINUX)
|
|
||||||
AM_CONDITIONAL(PA_HPUX, test x$TARGET = xPA_HPUX)
|
|
||||||
AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX)
|
|
||||||
AM_CONDITIONAL(TILE, test x$TARGET = xTILE)
|
|
||||||
|
|
||||||
AC_HEADER_STDC
|
|
||||||
AC_CHECK_FUNCS(memcpy)
|
|
||||||
AC_FUNC_ALLOCA
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF(double)
|
|
||||||
AC_CHECK_SIZEOF(long double)
|
|
||||||
|
|
||||||
# Also AC_SUBST this variable for ffi.h.
|
|
||||||
if test -z "$HAVE_LONG_DOUBLE"; then
|
|
||||||
HAVE_LONG_DOUBLE=0
|
|
||||||
if test $ac_cv_sizeof_double != $ac_cv_sizeof_long_double; then
|
|
||||||
if test $ac_cv_sizeof_long_double != 0; then
|
|
||||||
HAVE_LONG_DOUBLE=1
|
|
||||||
AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if you have the long double type and it is bigger than a double])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(HAVE_LONG_DOUBLE)
|
|
||||||
|
|
||||||
AC_C_BIGENDIAN
|
|
||||||
|
|
||||||
GCC_AS_CFI_PSEUDO_OP
|
|
||||||
|
|
||||||
if test x$TARGET = xSPARC; then
|
|
||||||
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
|
|
||||||
libffi_cv_as_sparc_ua_pcrel, [
|
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
save_LDFLAGS="$LDFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -fpic"
|
|
||||||
LDFLAGS="$LDFLAGS -shared"
|
|
||||||
AC_TRY_LINK([asm (".text; foo: nop; .data; .align 4; .byte 0; .uaword %r_disp32(foo); .text");],,
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=yes],
|
|
||||||
[libffi_cv_as_sparc_ua_pcrel=no])
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
LDFLAGS="$save_LDFLAGS"])
|
|
||||||
if test "x$libffi_cv_as_sparc_ua_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
|
|
||||||
[Define if your assembler and linker support unaligned PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .register pseudo-op support],
|
|
||||||
libffi_cv_as_register_pseudo_op, [
|
|
||||||
libffi_cv_as_register_pseudo_op=unknown
|
|
||||||
# Check if we have .register
|
|
||||||
AC_TRY_COMPILE([asm (".register %g2, #scratch");],,
|
|
||||||
[libffi_cv_as_register_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_register_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_register_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .register.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports pc related relocs],
|
|
||||||
libffi_cv_as_x86_pcrel, [
|
|
||||||
libffi_cv_as_x86_pcrel=yes
|
|
||||||
echo '.text; foo: nop; .data; .long foo-.; .text' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | $EGREP -i 'illegal|warning' > /dev/null; then
|
|
||||||
libffi_cv_as_x86_pcrel=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_pcrel" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_PCREL, 1,
|
|
||||||
[Define if your assembler supports PC relative relocs.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .ascii pseudo-op support],
|
|
||||||
libffi_cv_as_ascii_pseudo_op, [
|
|
||||||
libffi_cv_as_ascii_pseudo_op=unknown
|
|
||||||
# Check if we have .ascii
|
|
||||||
AC_TRY_COMPILE([asm (".ascii \\"string\\"");],,
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_ascii_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .ascii.])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([assembler .string pseudo-op support],
|
|
||||||
libffi_cv_as_string_pseudo_op, [
|
|
||||||
libffi_cv_as_string_pseudo_op=unknown
|
|
||||||
# Check if we have .string
|
|
||||||
AC_TRY_COMPILE([asm (".string \\"string\\"");],,
|
|
||||||
[libffi_cv_as_string_pseudo_op=yes],
|
|
||||||
[libffi_cv_as_string_pseudo_op=no])
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_string_pseudo_op" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1,
|
|
||||||
[Define if your assembler supports .string.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_WIN64; then
|
|
||||||
LT_SYS_SYMBOL_USCORE
|
|
||||||
if test "x$sys_symbol_underscore" = xyes; then
|
|
||||||
AC_DEFINE(SYMBOL_UNDERSCORE, 1, [Define if symbols are underscored.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=0
|
|
||||||
case "$target" in
|
|
||||||
*arm*-apple-darwin*)
|
|
||||||
FFI_EXEC_TRAMPOLINE_TABLE=1
|
|
||||||
AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1,
|
|
||||||
[Cannot use PROT_EXEC on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
*-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*)
|
|
||||||
AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1,
|
|
||||||
[Cannot use malloc on this target, so, we revert to
|
|
||||||
alternative means])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AM_CONDITIONAL(FFI_EXEC_TRAMPOLINE_TABLE, test x$FFI_EXEC_TRAMPOLINE_TABLE = x1)
|
|
||||||
AC_SUBST(FFI_EXEC_TRAMPOLINE_TABLE)
|
|
||||||
|
|
||||||
if test x$TARGET = xX86_64; then
|
|
||||||
AC_CACHE_CHECK([assembler supports unwind section type],
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type, [
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=yes
|
|
||||||
echo '.section .eh_frame,"a",@unwind' > conftest.s
|
|
||||||
if $CC $CFLAGS -c conftest.s 2>&1 | grep -i warning > /dev/null; then
|
|
||||||
libffi_cv_as_x86_64_unwind_section_type=no
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_as_x86_64_unwind_section_type" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_AS_X86_64_UNWIND_SECTION_TYPE, 1,
|
|
||||||
[Define if your assembler supports unwind section type.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
AC_CACHE_CHECK([whether .eh_frame section should be read-only],
|
|
||||||
libffi_cv_ro_eh_frame, [
|
|
||||||
libffi_cv_ro_eh_frame=no
|
|
||||||
echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c
|
|
||||||
if $CC $CFLAGS -S -fpic -fexceptions -o conftest.s conftest.c > /dev/null 2>&1; then
|
|
||||||
if grep '.section.*eh_frame.*"a"' conftest.s > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
elif grep '.section.*eh_frame.*#alloc' conftest.c \
|
|
||||||
| grep -v '#write' > /dev/null; then
|
|
||||||
libffi_cv_ro_eh_frame=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test "x$libffi_cv_ro_eh_frame" = xyes; then
|
|
||||||
AC_DEFINE(HAVE_RO_EH_FRAME, 1,
|
|
||||||
[Define if .eh_frame sections should be read-only.])
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "a",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
else
|
|
||||||
AC_DEFINE(EH_FRAME_FLAGS, "aw",
|
|
||||||
[Define to the flags needed for the .section .eh_frame directive. ])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for __attribute__((visibility("hidden")))],
|
|
||||||
libffi_cv_hidden_visibility_attribute, [
|
|
||||||
echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c
|
|
||||||
libffi_cv_hidden_visibility_attribute=no
|
|
||||||
if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
|
|
||||||
if grep '\.hidden.*foo' conftest.s >/dev/null; then
|
|
||||||
libffi_cv_hidden_visibility_attribute=yes
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f conftest.*
|
|
||||||
])
|
|
||||||
if test $libffi_cv_hidden_visibility_attribute = yes; then
|
|
||||||
AC_DEFINE(HAVE_HIDDEN_VISIBILITY_ATTRIBUTE, 1,
|
|
||||||
[Define if __attribute__((visibility("hidden"))) is supported.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
AH_BOTTOM([
|
|
||||||
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name) .hidden name
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef LIBFFI_ASM
|
|
||||||
#define FFI_HIDDEN(name)
|
|
||||||
#else
|
|
||||||
#define FFI_HIDDEN
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_SUBST(TARGET)
|
|
||||||
AC_SUBST(TARGETDIR)
|
|
||||||
|
|
||||||
AC_SUBST(SHELL)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(debug,
|
|
||||||
[ --enable-debug debugging mode],
|
|
||||||
if test "$enable_debug" = "yes"; then
|
|
||||||
AC_DEFINE(FFI_DEBUG, 1, [Define this if you want extra debugging.])
|
|
||||||
fi)
|
|
||||||
AM_CONDITIONAL(FFI_DEBUG, test "$enable_debug" = "yes")
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(structs,
|
|
||||||
[ --disable-structs omit code for struct support],
|
|
||||||
if test "$enable_structs" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_STRUCTS, 1, [Define this is you do not want support for aggregate types.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(raw-api,
|
|
||||||
[ --disable-raw-api make the raw api unavailable],
|
|
||||||
if test "$enable_raw_api" = "no"; then
|
|
||||||
AC_DEFINE(FFI_NO_RAW_API, 1, [Define this is you do not want support for the raw API.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(purify-safety,
|
|
||||||
[ --enable-purify-safety purify-safe mode],
|
|
||||||
if test "$enable_purify_safety" = "yes"; then
|
|
||||||
AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.])
|
|
||||||
fi)
|
|
||||||
|
|
||||||
# These variables are only ever used when we cross-build to X86_WIN32.
|
|
||||||
# And we only support this with GCC, so...
|
|
||||||
if test x"$GCC" != x"no"; then
|
|
||||||
if test -n "$with_cross_host" &&
|
|
||||||
test x"$with_cross_host" != x"no"; then
|
|
||||||
toolexecdir='$(exec_prefix)/$(target_alias)'
|
|
||||||
toolexeclibdir='$(toolexecdir)/lib'
|
|
||||||
else
|
|
||||||
toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
|
|
||||||
toolexeclibdir='$(libdir)'
|
|
||||||
fi
|
|
||||||
multi_os_directory=`$CC -print-multi-os-directory`
|
|
||||||
case $multi_os_directory in
|
|
||||||
.) ;; # Avoid trailing /.
|
|
||||||
*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
|
|
||||||
esac
|
|
||||||
AC_SUBST(toolexecdir)
|
|
||||||
AC_SUBST(toolexeclibdir)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "${multilib}" = "yes"; then
|
|
||||||
multilib_arg="--enable-multilib"
|
|
||||||
else
|
|
||||||
multilib_arg=
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_CONFIG_COMMANDS(include, [test -d include || mkdir include])
|
|
||||||
AC_CONFIG_COMMANDS(src, [
|
|
||||||
test -d src || mkdir src
|
|
||||||
test -d src/$TARGETDIR || mkdir src/$TARGETDIR
|
|
||||||
], [TARGETDIR="$TARGETDIR"])
|
|
||||||
|
|
||||||
AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h)
|
|
||||||
|
|
||||||
AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc)
|
|
||||||
|
|
||||||
AC_OUTPUT
|
|
||||||
@@ -1,615 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
|
|
||||||
Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
|
|
||||||
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
|
|
||||||
|
|
||||||
Code to allocate and deallocate memory for closures.
|
|
||||||
|
|
||||||
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 __linux__ && !defined _GNU_SOURCE
|
|
||||||
#define _GNU_SOURCE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ffi.h>
|
|
||||||
#include <ffi_common.h>
|
|
||||||
|
|
||||||
#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
|
|
||||||
# if __gnu_linux__
|
|
||||||
/* This macro indicates it may be forbidden to map anonymous memory
|
|
||||||
with both write and execute permission. Code compiled when this
|
|
||||||
option is defined will attempt to map such pages once, but if it
|
|
||||||
fails, it falls back to creating a temporary file in a writable and
|
|
||||||
executable filesystem and mapping pages from it into separate
|
|
||||||
locations in the virtual memory space, one location writable and
|
|
||||||
another executable. */
|
|
||||||
# define FFI_MMAP_EXEC_WRIT 1
|
|
||||||
# define HAVE_MNTENT 1
|
|
||||||
# endif
|
|
||||||
# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
|
|
||||||
/* Windows systems may have Data Execution Protection (DEP) enabled,
|
|
||||||
which requires the use of VirtualMalloc/VirtualFree to alloc/free
|
|
||||||
executable memory. */
|
|
||||||
# define FFI_MMAP_EXEC_WRIT 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
|
|
||||||
# ifdef __linux__
|
|
||||||
/* When defined to 1 check for SELinux and if SELinux is active,
|
|
||||||
don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
|
|
||||||
might cause audit messages. */
|
|
||||||
# define FFI_MMAP_EXEC_SELINUX 1
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if FFI_CLOSURES
|
|
||||||
|
|
||||||
# if FFI_EXEC_TRAMPOLINE_TABLE
|
|
||||||
|
|
||||||
// Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations.
|
|
||||||
|
|
||||||
# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */
|
|
||||||
|
|
||||||
#define USE_LOCKS 1
|
|
||||||
#define USE_DL_PREFIX 1
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#ifndef USE_BUILTIN_FFS
|
|
||||||
#define USE_BUILTIN_FFS 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We need to use mmap, not sbrk. */
|
|
||||||
#define HAVE_MORECORE 0
|
|
||||||
|
|
||||||
/* We could, in theory, support mremap, but it wouldn't buy us anything. */
|
|
||||||
#define HAVE_MREMAP 0
|
|
||||||
|
|
||||||
/* We have no use for this, so save some code and data. */
|
|
||||||
#define NO_MALLINFO 1
|
|
||||||
|
|
||||||
/* We need all allocations to be in regular segments, otherwise we
|
|
||||||
lose track of the corresponding code address. */
|
|
||||||
#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
|
|
||||||
|
|
||||||
/* Don't allocate more than a page unless needed. */
|
|
||||||
#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
|
|
||||||
|
|
||||||
#if FFI_CLOSURE_TEST
|
|
||||||
/* Don't release single pages, to avoid a worst-case scenario of
|
|
||||||
continuously allocating and releasing single pages, but release
|
|
||||||
pairs of pages, which should do just as well given that allocations
|
|
||||||
are likely to be small. */
|
|
||||||
#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#ifndef _MSC_VER
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#if !defined(X86_WIN32) && !defined(X86_WIN64)
|
|
||||||
#ifdef HAVE_MNTENT
|
|
||||||
#include <mntent.h>
|
|
||||||
#endif /* HAVE_MNTENT */
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
/* We don't want sys/mman.h to be included after we redefine mmap and
|
|
||||||
dlmunmap. */
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#define LACKS_SYS_MMAN_H 1
|
|
||||||
|
|
||||||
#if FFI_MMAP_EXEC_SELINUX
|
|
||||||
#include <sys/statfs.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static int selinux_enabled = -1;
|
|
||||||
|
|
||||||
static int
|
|
||||||
selinux_enabled_check (void)
|
|
||||||
{
|
|
||||||
struct statfs sfs;
|
|
||||||
FILE *f;
|
|
||||||
char *buf = NULL;
|
|
||||||
size_t len = 0;
|
|
||||||
|
|
||||||
if (statfs ("/selinux", &sfs) >= 0
|
|
||||||
&& (unsigned int) sfs.f_type == 0xf97cff8cU)
|
|
||||||
return 1;
|
|
||||||
f = fopen ("/proc/mounts", "r");
|
|
||||||
if (f == NULL)
|
|
||||||
return 0;
|
|
||||||
while (getline (&buf, &len, f) >= 0)
|
|
||||||
{
|
|
||||||
char *p = strchr (buf, ' ');
|
|
||||||
if (p == NULL)
|
|
||||||
break;
|
|
||||||
p = strchr (p + 1, ' ');
|
|
||||||
if (p == NULL)
|
|
||||||
break;
|
|
||||||
if (strncmp (p + 1, "selinuxfs ", 10) == 0)
|
|
||||||
{
|
|
||||||
free (buf);
|
|
||||||
fclose (f);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free (buf);
|
|
||||||
fclose (f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
|
|
||||||
: (selinux_enabled = selinux_enabled_check ()))
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define is_selinux_enabled() 0
|
|
||||||
|
|
||||||
#endif /* !FFI_MMAP_EXEC_SELINUX */
|
|
||||||
|
|
||||||
#elif defined (__CYGWIN__) || defined(__INTERIX)
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
/* Cygwin is Linux-like, but not quite that Linux-like. */
|
|
||||||
#define is_selinux_enabled() 0
|
|
||||||
|
|
||||||
#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
|
|
||||||
|
|
||||||
/* Declare all functions defined in dlmalloc.c as static. */
|
|
||||||
static void *dlmalloc(size_t);
|
|
||||||
static void dlfree(void*);
|
|
||||||
static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
|
|
||||||
static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
|
|
||||||
static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
|
|
||||||
static void *dlvalloc(size_t) MAYBE_UNUSED;
|
|
||||||
static int dlmallopt(int, int) MAYBE_UNUSED;
|
|
||||||
static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
|
|
||||||
static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
|
|
||||||
static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
|
|
||||||
static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
|
|
||||||
static void *dlpvalloc(size_t) MAYBE_UNUSED;
|
|
||||||
static int dlmalloc_trim(size_t) MAYBE_UNUSED;
|
|
||||||
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
|
|
||||||
static void dlmalloc_stats(void) MAYBE_UNUSED;
|
|
||||||
|
|
||||||
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
|
|
||||||
/* Use these for mmap and munmap within dlmalloc.c. */
|
|
||||||
static void *dlmmap(void *, size_t, int, int, int, off_t);
|
|
||||||
static int dlmunmap(void *, size_t);
|
|
||||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
|
|
||||||
|
|
||||||
#define mmap dlmmap
|
|
||||||
#define munmap dlmunmap
|
|
||||||
|
|
||||||
#include "dlmalloc.c"
|
|
||||||
|
|
||||||
#undef mmap
|
|
||||||
#undef munmap
|
|
||||||
|
|
||||||
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX)
|
|
||||||
|
|
||||||
/* A mutex used to synchronize access to *exec* variables in this file. */
|
|
||||||
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
/* A file descriptor of a temporary file from which we'll map
|
|
||||||
executable pages. */
|
|
||||||
static int execfd = -1;
|
|
||||||
|
|
||||||
/* The amount of space already allocated from the temporary file. */
|
|
||||||
static size_t execsize = 0;
|
|
||||||
|
|
||||||
/* Open a temporary file name, and immediately unlink it. */
|
|
||||||
static int
|
|
||||||
open_temp_exec_file_name (char *name)
|
|
||||||
{
|
|
||||||
int fd = mkstemp (name);
|
|
||||||
|
|
||||||
if (fd != -1)
|
|
||||||
unlink (name);
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open a temporary file in the named directory. */
|
|
||||||
static int
|
|
||||||
open_temp_exec_file_dir (const char *dir)
|
|
||||||
{
|
|
||||||
static const char suffix[] = "/ffiXXXXXX";
|
|
||||||
int lendir = strlen (dir);
|
|
||||||
char *tempname = __builtin_alloca (lendir + sizeof (suffix));
|
|
||||||
|
|
||||||
if (!tempname)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memcpy (tempname, dir, lendir);
|
|
||||||
memcpy (tempname + lendir, suffix, sizeof (suffix));
|
|
||||||
|
|
||||||
return open_temp_exec_file_name (tempname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open a temporary file in the directory in the named environment
|
|
||||||
variable. */
|
|
||||||
static int
|
|
||||||
open_temp_exec_file_env (const char *envvar)
|
|
||||||
{
|
|
||||||
const char *value = getenv (envvar);
|
|
||||||
|
|
||||||
if (!value)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return open_temp_exec_file_dir (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_MNTENT
|
|
||||||
/* Open a temporary file in an executable and writable mount point
|
|
||||||
listed in the mounts file. Subsequent calls with the same mounts
|
|
||||||
keep searching for mount points in the same file. Providing NULL
|
|
||||||
as the mounts file closes the file. */
|
|
||||||
static int
|
|
||||||
open_temp_exec_file_mnt (const char *mounts)
|
|
||||||
{
|
|
||||||
static const char *last_mounts;
|
|
||||||
static FILE *last_mntent;
|
|
||||||
|
|
||||||
if (mounts != last_mounts)
|
|
||||||
{
|
|
||||||
if (last_mntent)
|
|
||||||
endmntent (last_mntent);
|
|
||||||
|
|
||||||
last_mounts = mounts;
|
|
||||||
|
|
||||||
if (mounts)
|
|
||||||
last_mntent = setmntent (mounts, "r");
|
|
||||||
else
|
|
||||||
last_mntent = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!last_mntent)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct mntent mnt;
|
|
||||||
char buf[MAXPATHLEN * 3];
|
|
||||||
|
|
||||||
if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (hasmntopt (&mnt, "ro")
|
|
||||||
|| hasmntopt (&mnt, "noexec")
|
|
||||||
|| access (mnt.mnt_dir, W_OK))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fd = open_temp_exec_file_dir (mnt.mnt_dir);
|
|
||||||
|
|
||||||
if (fd != -1)
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* HAVE_MNTENT */
|
|
||||||
|
|
||||||
/* Instructions to look for a location to hold a temporary file that
|
|
||||||
can be mapped in for execution. */
|
|
||||||
static struct
|
|
||||||
{
|
|
||||||
int (*func)(const char *);
|
|
||||||
const char *arg;
|
|
||||||
int repeat;
|
|
||||||
} open_temp_exec_file_opts[] = {
|
|
||||||
{ open_temp_exec_file_env, "TMPDIR", 0 },
|
|
||||||
{ open_temp_exec_file_dir, "/tmp", 0 },
|
|
||||||
{ open_temp_exec_file_dir, "/var/tmp", 0 },
|
|
||||||
{ open_temp_exec_file_dir, "/dev/shm", 0 },
|
|
||||||
{ open_temp_exec_file_env, "HOME", 0 },
|
|
||||||
#ifdef HAVE_MNTENT
|
|
||||||
{ open_temp_exec_file_mnt, "/etc/mtab", 1 },
|
|
||||||
{ open_temp_exec_file_mnt, "/proc/mounts", 1 },
|
|
||||||
#endif /* HAVE_MNTENT */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Current index into open_temp_exec_file_opts. */
|
|
||||||
static int open_temp_exec_file_opts_idx = 0;
|
|
||||||
|
|
||||||
/* Reset a current multi-call func, then advances to the next entry.
|
|
||||||
If we're at the last, go back to the first and return nonzero,
|
|
||||||
otherwise return zero. */
|
|
||||||
static int
|
|
||||||
open_temp_exec_file_opts_next (void)
|
|
||||||
{
|
|
||||||
if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
|
||||||
open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
|
|
||||||
|
|
||||||
open_temp_exec_file_opts_idx++;
|
|
||||||
if (open_temp_exec_file_opts_idx
|
|
||||||
== (sizeof (open_temp_exec_file_opts)
|
|
||||||
/ sizeof (*open_temp_exec_file_opts)))
|
|
||||||
{
|
|
||||||
open_temp_exec_file_opts_idx = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return a file descriptor of a temporary zero-sized file in a
|
|
||||||
writable and exexutable filesystem. */
|
|
||||||
static int
|
|
||||||
open_temp_exec_file (void)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
|
|
||||||
(open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
|
|
||||||
|
|
||||||
if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
|
|
||||||
|| fd == -1)
|
|
||||||
{
|
|
||||||
if (open_temp_exec_file_opts_next ())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (fd == -1);
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map in a chunk of memory from the temporary exec file into separate
|
|
||||||
locations in the virtual memory address space, one writable and one
|
|
||||||
executable. Returns the address of the writable portion, after
|
|
||||||
storing an offset to the corresponding executable portion at the
|
|
||||||
last word of the requested chunk. */
|
|
||||||
static void *
|
|
||||||
dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if (execfd == -1)
|
|
||||||
{
|
|
||||||
open_temp_exec_file_opts_idx = 0;
|
|
||||||
retry_open:
|
|
||||||
execfd = open_temp_exec_file ();
|
|
||||||
if (execfd == -1)
|
|
||||||
return MFAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = execsize;
|
|
||||||
|
|
||||||
if (ftruncate (execfd, offset + length))
|
|
||||||
return MFAIL;
|
|
||||||
|
|
||||||
flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
|
|
||||||
flags |= MAP_SHARED;
|
|
||||||
|
|
||||||
ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
|
|
||||||
flags, execfd, offset);
|
|
||||||
if (ptr == MFAIL)
|
|
||||||
{
|
|
||||||
if (!offset)
|
|
||||||
{
|
|
||||||
close (execfd);
|
|
||||||
goto retry_open;
|
|
||||||
}
|
|
||||||
ftruncate (execfd, offset);
|
|
||||||
return MFAIL;
|
|
||||||
}
|
|
||||||
else if (!offset
|
|
||||||
&& open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
|
|
||||||
open_temp_exec_file_opts_next ();
|
|
||||||
|
|
||||||
start = mmap (start, length, prot, flags, execfd, offset);
|
|
||||||
|
|
||||||
if (start == MFAIL)
|
|
||||||
{
|
|
||||||
munmap (ptr, length);
|
|
||||||
ftruncate (execfd, offset);
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
|
|
||||||
|
|
||||||
execsize += length;
|
|
||||||
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map in a writable and executable chunk of memory if possible.
|
|
||||||
Failing that, fall back to dlmmap_locked. */
|
|
||||||
static void *
|
|
||||||
dlmmap (void *start, size_t length, int prot,
|
|
||||||
int flags, int fd, off_t offset)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
assert (start == NULL && length % malloc_getpagesize == 0
|
|
||||||
&& prot == (PROT_READ | PROT_WRITE)
|
|
||||||
&& flags == (MAP_PRIVATE | MAP_ANONYMOUS)
|
|
||||||
&& fd == -1 && offset == 0);
|
|
||||||
|
|
||||||
#if FFI_CLOSURE_TEST
|
|
||||||
printf ("mapping in %zi\n", length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (execfd == -1 && !is_selinux_enabled ())
|
|
||||||
{
|
|
||||||
ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
|
|
||||||
|
|
||||||
if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
|
|
||||||
/* Cool, no need to mess with separate segments. */
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
/* If MREMAP_DUP is ever introduced and implemented, try mmap
|
|
||||||
with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
|
|
||||||
MREMAP_DUP and prot at this point. */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (execsize == 0 || execfd == -1)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock (&open_temp_exec_file_mutex);
|
|
||||||
ptr = dlmmap_locked (start, length, prot, flags, offset);
|
|
||||||
pthread_mutex_unlock (&open_temp_exec_file_mutex);
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dlmmap_locked (start, length, prot, flags, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release memory at the given address, as well as the corresponding
|
|
||||||
executable page if it's separate. */
|
|
||||||
static int
|
|
||||||
dlmunmap (void *start, size_t length)
|
|
||||||
{
|
|
||||||
/* We don't bother decreasing execsize or truncating the file, since
|
|
||||||
we can't quite tell whether we're unmapping the end of the file.
|
|
||||||
We don't expect frequent deallocation anyway. If we did, we
|
|
||||||
could locate pages in the file by writing to the pages being
|
|
||||||
deallocated and checking that the file contents change.
|
|
||||||
Yuck. */
|
|
||||||
msegmentptr seg = segment_holding (gm, start);
|
|
||||||
void *code;
|
|
||||||
|
|
||||||
#if FFI_CLOSURE_TEST
|
|
||||||
printf ("unmapping %zi\n", length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (seg && (code = add_segment_exec_offset (start, seg)) != start)
|
|
||||||
{
|
|
||||||
int ret = munmap (code, length);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return munmap (start, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FFI_CLOSURE_FREE_CODE
|
|
||||||
/* Return segment holding given code address. */
|
|
||||||
static msegmentptr
|
|
||||||
segment_holding_code (mstate m, char* addr)
|
|
||||||
{
|
|
||||||
msegmentptr sp = &m->seg;
|
|
||||||
for (;;) {
|
|
||||||
if (addr >= add_segment_exec_offset (sp->base, sp)
|
|
||||||
&& addr < add_segment_exec_offset (sp->base, sp) + sp->size)
|
|
||||||
return sp;
|
|
||||||
if ((sp = sp->next) == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
|
|
||||||
|
|
||||||
/* Allocate a chunk of memory with the given size. Returns a pointer
|
|
||||||
to the writable address, and sets *CODE to the executable
|
|
||||||
corresponding virtual address. */
|
|
||||||
void *
|
|
||||||
ffi_closure_alloc (size_t size, void **code)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if (!code)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ptr = dlmalloc (size);
|
|
||||||
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
msegmentptr seg = segment_holding (gm, ptr);
|
|
||||||
|
|
||||||
*code = add_segment_exec_offset (ptr, seg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Release a chunk of memory allocated with ffi_closure_alloc. If
|
|
||||||
FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
|
|
||||||
writable or the executable address given. Otherwise, only the
|
|
||||||
writable address can be provided here. */
|
|
||||||
void
|
|
||||||
ffi_closure_free (void *ptr)
|
|
||||||
{
|
|
||||||
#if FFI_CLOSURE_FREE_CODE
|
|
||||||
msegmentptr seg = segment_holding_code (gm, ptr);
|
|
||||||
|
|
||||||
if (seg)
|
|
||||||
ptr = sub_segment_exec_offset (ptr, seg);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dlfree (ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if FFI_CLOSURE_TEST
|
|
||||||
/* Do some internal sanity testing to make sure allocation and
|
|
||||||
deallocation of pages are working as intended. */
|
|
||||||
int main ()
|
|
||||||
{
|
|
||||||
void *p[3];
|
|
||||||
#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
|
|
||||||
#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
|
|
||||||
GET (0, malloc_getpagesize / 2);
|
|
||||||
GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
|
|
||||||
PUT (1);
|
|
||||||
GET (1, 2 * malloc_getpagesize);
|
|
||||||
GET (2, malloc_getpagesize / 2);
|
|
||||||
PUT (1);
|
|
||||||
PUT (0);
|
|
||||||
PUT (2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* FFI_CLOSURE_TEST */
|
|
||||||
# else /* ! FFI_MMAP_EXEC_WRIT */
|
|
||||||
|
|
||||||
/* On many systems, memory returned by malloc is writable and
|
|
||||||
executable, so just use it. */
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void *
|
|
||||||
ffi_closure_alloc (size_t size, void **code)
|
|
||||||
{
|
|
||||||
if (!code)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return *code = malloc (size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ffi_closure_free (void *ptr)
|
|
||||||
{
|
|
||||||
free (ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
# endif /* ! FFI_MMAP_EXEC_WRIT */
|
|
||||||
#endif /* FFI_CLOSURES */
|
|
||||||
5059
.pc/icc128/ChangeLog
5059
.pc/icc128/ChangeLog
File diff suppressed because it is too large
Load Diff
@@ -1,637 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
ffi64.c - Copyright (c) 20011 Anthony Green
|
|
||||||
Copyright (c) 2008, 2010 Red Hat, Inc.
|
|
||||||
Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
|
|
||||||
|
|
||||||
x86-64 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.
|
|
||||||
----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#include <ffi.h>
|
|
||||||
#include <ffi_common.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
|
|
||||||
#define MAX_GPR_REGS 6
|
|
||||||
#define MAX_SSE_REGS 8
|
|
||||||
|
|
||||||
struct register_args
|
|
||||||
{
|
|
||||||
/* Registers for argument passing. */
|
|
||||||
UINT64 gpr[MAX_GPR_REGS];
|
|
||||||
__int128_t sse[MAX_SSE_REGS];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags,
|
|
||||||
void *raddr, void (*fnaddr)(void), unsigned ssecount);
|
|
||||||
|
|
||||||
/* All reference to register classes here is identical to the code in
|
|
||||||
gcc/config/i386/i386.c. Do *not* change one without the other. */
|
|
||||||
|
|
||||||
/* Register class used for passing given 64bit part of the argument.
|
|
||||||
These represent classes as documented by the PS ABI, with the
|
|
||||||
exception of SSESF, SSEDF classes, that are basically SSE class,
|
|
||||||
just gcc will use SF or DFmode move instead of DImode to avoid
|
|
||||||
reformatting penalties.
|
|
||||||
|
|
||||||
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
|
||||||
whenever possible (upper half does contain padding). */
|
|
||||||
enum x86_64_reg_class
|
|
||||||
{
|
|
||||||
X86_64_NO_CLASS,
|
|
||||||
X86_64_INTEGER_CLASS,
|
|
||||||
X86_64_INTEGERSI_CLASS,
|
|
||||||
X86_64_SSE_CLASS,
|
|
||||||
X86_64_SSESF_CLASS,
|
|
||||||
X86_64_SSEDF_CLASS,
|
|
||||||
X86_64_SSEUP_CLASS,
|
|
||||||
X86_64_X87_CLASS,
|
|
||||||
X86_64_X87UP_CLASS,
|
|
||||||
X86_64_COMPLEX_X87_CLASS,
|
|
||||||
X86_64_MEMORY_CLASS
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_CLASSES 4
|
|
||||||
|
|
||||||
#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS)
|
|
||||||
|
|
||||||
/* x86-64 register passing implementation. See x86-64 ABI for details. Goal
|
|
||||||
of this code is to classify each 8bytes of incoming argument by the register
|
|
||||||
class and assign registers accordingly. */
|
|
||||||
|
|
||||||
/* Return the union class of CLASS1 and CLASS2.
|
|
||||||
See the x86-64 PS ABI for details. */
|
|
||||||
|
|
||||||
static enum x86_64_reg_class
|
|
||||||
merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
|
|
||||||
{
|
|
||||||
/* Rule #1: If both classes are equal, this is the resulting class. */
|
|
||||||
if (class1 == class2)
|
|
||||||
return class1;
|
|
||||||
|
|
||||||
/* Rule #2: If one of the classes is NO_CLASS, the resulting class is
|
|
||||||
the other class. */
|
|
||||||
if (class1 == X86_64_NO_CLASS)
|
|
||||||
return class2;
|
|
||||||
if (class2 == X86_64_NO_CLASS)
|
|
||||||
return class1;
|
|
||||||
|
|
||||||
/* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */
|
|
||||||
if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
|
|
||||||
return X86_64_MEMORY_CLASS;
|
|
||||||
|
|
||||||
/* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */
|
|
||||||
if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
|
|
||||||
|| (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
|
|
||||||
return X86_64_INTEGERSI_CLASS;
|
|
||||||
if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
|
|
||||||
|| class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
|
|
||||||
return X86_64_INTEGER_CLASS;
|
|
||||||
|
|
||||||
/* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
|
|
||||||
MEMORY is used. */
|
|
||||||
if (class1 == X86_64_X87_CLASS
|
|
||||||
|| class1 == X86_64_X87UP_CLASS
|
|
||||||
|| class1 == X86_64_COMPLEX_X87_CLASS
|
|
||||||
|| class2 == X86_64_X87_CLASS
|
|
||||||
|| class2 == X86_64_X87UP_CLASS
|
|
||||||
|| class2 == X86_64_COMPLEX_X87_CLASS)
|
|
||||||
return X86_64_MEMORY_CLASS;
|
|
||||||
|
|
||||||
/* Rule #6: Otherwise class SSE is used. */
|
|
||||||
return X86_64_SSE_CLASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Classify the argument of type TYPE and mode MODE.
|
|
||||||
CLASSES will be filled by the register class used to pass each word
|
|
||||||
of the operand. The number of words is returned. In case the parameter
|
|
||||||
should be passed in memory, 0 is returned. As a special case for zero
|
|
||||||
sized containers, classes[0] will be NO_CLASS and 1 is returned.
|
|
||||||
|
|
||||||
See the x86-64 PS ABI for details.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
|
|
||||||
size_t byte_offset)
|
|
||||||
{
|
|
||||||
switch (type->type)
|
|
||||||
{
|
|
||||||
case FFI_TYPE_UINT8:
|
|
||||||
case FFI_TYPE_SINT8:
|
|
||||||
case FFI_TYPE_UINT16:
|
|
||||||
case FFI_TYPE_SINT16:
|
|
||||||
case FFI_TYPE_UINT32:
|
|
||||||
case FFI_TYPE_SINT32:
|
|
||||||
case FFI_TYPE_UINT64:
|
|
||||||
case FFI_TYPE_SINT64:
|
|
||||||
case FFI_TYPE_POINTER:
|
|
||||||
{
|
|
||||||
int size = byte_offset + type->size;
|
|
||||||
|
|
||||||
if (size <= 4)
|
|
||||||
{
|
|
||||||
classes[0] = X86_64_INTEGERSI_CLASS;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (size <= 8)
|
|
||||||
{
|
|
||||||
classes[0] = X86_64_INTEGER_CLASS;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else if (size <= 12)
|
|
||||||
{
|
|
||||||
classes[0] = X86_64_INTEGER_CLASS;
|
|
||||||
classes[1] = X86_64_INTEGERSI_CLASS;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
else if (size <= 16)
|
|
||||||
{
|
|
||||||
classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
FFI_ASSERT (0);
|
|
||||||
}
|
|
||||||
case FFI_TYPE_FLOAT:
|
|
||||||
if (!(byte_offset % 8))
|
|
||||||
classes[0] = X86_64_SSESF_CLASS;
|
|
||||||
else
|
|
||||||
classes[0] = X86_64_SSE_CLASS;
|
|
||||||
return 1;
|
|
||||||
case FFI_TYPE_DOUBLE:
|
|
||||||
classes[0] = X86_64_SSEDF_CLASS;
|
|
||||||
return 1;
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
|
||||||
classes[0] = X86_64_X87_CLASS;
|
|
||||||
classes[1] = X86_64_X87UP_CLASS;
|
|
||||||
return 2;
|
|
||||||
case FFI_TYPE_STRUCT:
|
|
||||||
{
|
|
||||||
const int UNITS_PER_WORD = 8;
|
|
||||||
int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
|
||||||
ffi_type **ptr;
|
|
||||||
int i;
|
|
||||||
enum x86_64_reg_class subclasses[MAX_CLASSES];
|
|
||||||
|
|
||||||
/* If the struct is larger than 32 bytes, pass it on the stack. */
|
|
||||||
if (type->size > 32)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < words; i++)
|
|
||||||
classes[i] = X86_64_NO_CLASS;
|
|
||||||
|
|
||||||
/* Zero sized arrays or structures are NO_CLASS. We return 0 to
|
|
||||||
signalize memory class, so handle it as special case. */
|
|
||||||
if (!words)
|
|
||||||
{
|
|
||||||
classes[0] = X86_64_NO_CLASS;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Merge the fields of structure. */
|
|
||||||
for (ptr = type->elements; *ptr != NULL; ptr++)
|
|
||||||
{
|
|
||||||
int num;
|
|
||||||
|
|
||||||
byte_offset = ALIGN (byte_offset, (*ptr)->alignment);
|
|
||||||
|
|
||||||
num = classify_argument (*ptr, subclasses, byte_offset % 8);
|
|
||||||
if (num == 0)
|
|
||||||
return 0;
|
|
||||||
for (i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
int pos = byte_offset / 8;
|
|
||||||
classes[i + pos] =
|
|
||||||
merge_classes (subclasses[i], classes[i + pos]);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_offset += (*ptr)->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (words > 2)
|
|
||||||
{
|
|
||||||
/* When size > 16 bytes, if the first one isn't
|
|
||||||
X86_64_SSE_CLASS or any other ones aren't
|
|
||||||
X86_64_SSEUP_CLASS, everything should be passed in
|
|
||||||
memory. */
|
|
||||||
if (classes[0] != X86_64_SSE_CLASS)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 1; i < words; i++)
|
|
||||||
if (classes[i] != X86_64_SSEUP_CLASS)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Final merger cleanup. */
|
|
||||||
for (i = 0; i < words; i++)
|
|
||||||
{
|
|
||||||
/* If one class is MEMORY, everything should be passed in
|
|
||||||
memory. */
|
|
||||||
if (classes[i] == X86_64_MEMORY_CLASS)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* The X86_64_SSEUP_CLASS should be always preceded by
|
|
||||||
X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
|
|
||||||
if (classes[i] == X86_64_SSEUP_CLASS
|
|
||||||
&& classes[i - 1] != X86_64_SSE_CLASS
|
|
||||||
&& classes[i - 1] != X86_64_SSEUP_CLASS)
|
|
||||||
{
|
|
||||||
/* The first one should never be X86_64_SSEUP_CLASS. */
|
|
||||||
FFI_ASSERT (i != 0);
|
|
||||||
classes[i] = X86_64_SSE_CLASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
|
|
||||||
everything should be passed in memory. */
|
|
||||||
if (classes[i] == X86_64_X87UP_CLASS
|
|
||||||
&& (classes[i - 1] != X86_64_X87_CLASS))
|
|
||||||
{
|
|
||||||
/* The first one should never be X86_64_X87UP_CLASS. */
|
|
||||||
FFI_ASSERT (i != 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return words;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
FFI_ASSERT(0);
|
|
||||||
}
|
|
||||||
return 0; /* Never reached. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Examine the argument and return set number of register required in each
|
|
||||||
class. Return zero iff parameter should be passed in memory, otherwise
|
|
||||||
the number of registers. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES],
|
|
||||||
_Bool in_return, int *pngpr, int *pnsse)
|
|
||||||
{
|
|
||||||
int i, n, ngpr, nsse;
|
|
||||||
|
|
||||||
n = classify_argument (type, classes, 0);
|
|
||||||
if (n == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ngpr = nsse = 0;
|
|
||||||
for (i = 0; i < n; ++i)
|
|
||||||
switch (classes[i])
|
|
||||||
{
|
|
||||||
case X86_64_INTEGER_CLASS:
|
|
||||||
case X86_64_INTEGERSI_CLASS:
|
|
||||||
ngpr++;
|
|
||||||
break;
|
|
||||||
case X86_64_SSE_CLASS:
|
|
||||||
case X86_64_SSESF_CLASS:
|
|
||||||
case X86_64_SSEDF_CLASS:
|
|
||||||
nsse++;
|
|
||||||
break;
|
|
||||||
case X86_64_NO_CLASS:
|
|
||||||
case X86_64_SSEUP_CLASS:
|
|
||||||
break;
|
|
||||||
case X86_64_X87_CLASS:
|
|
||||||
case X86_64_X87UP_CLASS:
|
|
||||||
case X86_64_COMPLEX_X87_CLASS:
|
|
||||||
return in_return != 0;
|
|
||||||
default:
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
*pngpr = ngpr;
|
|
||||||
*pnsse = nsse;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform machine dependent cif processing. */
|
|
||||||
|
|
||||||
ffi_status
|
|
||||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
|
||||||
{
|
|
||||||
int gprcount, ssecount, i, avn, n, ngpr, nsse, flags;
|
|
||||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
|
||||||
size_t bytes;
|
|
||||||
|
|
||||||
gprcount = ssecount = 0;
|
|
||||||
|
|
||||||
flags = cif->rtype->type;
|
|
||||||
if (flags != FFI_TYPE_VOID)
|
|
||||||
{
|
|
||||||
n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
|
|
||||||
if (n == 0)
|
|
||||||
{
|
|
||||||
/* The return value is passed in memory. A pointer to that
|
|
||||||
memory is the first argument. Allocate a register for it. */
|
|
||||||
gprcount++;
|
|
||||||
/* We don't have to do anything in asm for the return. */
|
|
||||||
flags = FFI_TYPE_VOID;
|
|
||||||
}
|
|
||||||
else if (flags == FFI_TYPE_STRUCT)
|
|
||||||
{
|
|
||||||
/* Mark which registers the result appears in. */
|
|
||||||
_Bool sse0 = SSE_CLASS_P (classes[0]);
|
|
||||||
_Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]);
|
|
||||||
if (sse0 && !sse1)
|
|
||||||
flags |= 1 << 8;
|
|
||||||
else if (!sse0 && sse1)
|
|
||||||
flags |= 1 << 9;
|
|
||||||
else if (sse0 && sse1)
|
|
||||||
flags |= 1 << 10;
|
|
||||||
/* Mark the true size of the structure. */
|
|
||||||
flags |= cif->rtype->size << 12;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Go over all arguments and determine the way they should be passed.
|
|
||||||
If it's in a register and there is space for it, let that be so. If
|
|
||||||
not, add it's size to the stack byte count. */
|
|
||||||
for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++)
|
|
||||||
{
|
|
||||||
if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0
|
|
||||||
|| gprcount + ngpr > MAX_GPR_REGS
|
|
||||||
|| ssecount + nsse > MAX_SSE_REGS)
|
|
||||||
{
|
|
||||||
long align = cif->arg_types[i]->alignment;
|
|
||||||
|
|
||||||
if (align < 8)
|
|
||||||
align = 8;
|
|
||||||
|
|
||||||
bytes = ALIGN (bytes, align);
|
|
||||||
bytes += cif->arg_types[i]->size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gprcount += ngpr;
|
|
||||||
ssecount += nsse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ssecount)
|
|
||||||
flags |= 1 << 11;
|
|
||||||
cif->flags = flags;
|
|
||||||
cif->bytes = ALIGN (bytes, 8);
|
|
||||||
|
|
||||||
return FFI_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|
||||||
{
|
|
||||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
|
||||||
char *stack, *argp;
|
|
||||||
ffi_type **arg_types;
|
|
||||||
int gprcount, ssecount, ngpr, nsse, i, avn;
|
|
||||||
_Bool ret_in_memory;
|
|
||||||
struct register_args *reg_args;
|
|
||||||
|
|
||||||
/* Can't call 32-bit mode from 64-bit mode. */
|
|
||||||
FFI_ASSERT (cif->abi == FFI_UNIX64);
|
|
||||||
|
|
||||||
/* If the return value is a struct and we don't have a return value
|
|
||||||
address then we need to make one. Note the setting of flags to
|
|
||||||
VOID above in ffi_prep_cif_machdep. */
|
|
||||||
ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT
|
|
||||||
&& (cif->flags & 0xff) == FFI_TYPE_VOID);
|
|
||||||
if (rvalue == NULL && ret_in_memory)
|
|
||||||
rvalue = alloca (cif->rtype->size);
|
|
||||||
|
|
||||||
/* Allocate the space for the arguments, plus 4 words of temp space. */
|
|
||||||
stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8);
|
|
||||||
reg_args = (struct register_args *) stack;
|
|
||||||
argp = stack + sizeof (struct register_args);
|
|
||||||
|
|
||||||
gprcount = ssecount = 0;
|
|
||||||
|
|
||||||
/* If the return value is passed in memory, add the pointer as the
|
|
||||||
first integer argument. */
|
|
||||||
if (ret_in_memory)
|
|
||||||
reg_args->gpr[gprcount++] = (unsigned long) rvalue;
|
|
||||||
|
|
||||||
avn = cif->nargs;
|
|
||||||
arg_types = cif->arg_types;
|
|
||||||
|
|
||||||
for (i = 0; i < avn; ++i)
|
|
||||||
{
|
|
||||||
size_t size = arg_types[i]->size;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
|
|
||||||
if (n == 0
|
|
||||||
|| gprcount + ngpr > MAX_GPR_REGS
|
|
||||||
|| ssecount + nsse > MAX_SSE_REGS)
|
|
||||||
{
|
|
||||||
long align = arg_types[i]->alignment;
|
|
||||||
|
|
||||||
/* Stack arguments are *always* at least 8 byte aligned. */
|
|
||||||
if (align < 8)
|
|
||||||
align = 8;
|
|
||||||
|
|
||||||
/* Pass this argument in memory. */
|
|
||||||
argp = (void *) ALIGN (argp, align);
|
|
||||||
memcpy (argp, avalue[i], size);
|
|
||||||
argp += size;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The argument is passed entirely in registers. */
|
|
||||||
char *a = (char *) avalue[i];
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0; j < n; j++, a += 8, size -= 8)
|
|
||||||
{
|
|
||||||
switch (classes[j])
|
|
||||||
{
|
|
||||||
case X86_64_INTEGER_CLASS:
|
|
||||||
case X86_64_INTEGERSI_CLASS:
|
|
||||||
reg_args->gpr[gprcount] = 0;
|
|
||||||
memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
|
|
||||||
gprcount++;
|
|
||||||
break;
|
|
||||||
case X86_64_SSE_CLASS:
|
|
||||||
case X86_64_SSEDF_CLASS:
|
|
||||||
reg_args->sse[ssecount++] = *(UINT64 *) a;
|
|
||||||
break;
|
|
||||||
case X86_64_SSESF_CLASS:
|
|
||||||
reg_args->sse[ssecount++] = *(UINT32 *) a;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args),
|
|
||||||
cif->flags, rvalue, fn, ssecount);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void ffi_closure_unix64(void);
|
|
||||||
|
|
||||||
ffi_status
|
|
||||||
ffi_prep_closure_loc (ffi_closure* closure,
|
|
||||||
ffi_cif* cif,
|
|
||||||
void (*fun)(ffi_cif*, void*, void**, void*),
|
|
||||||
void *user_data,
|
|
||||||
void *codeloc)
|
|
||||||
{
|
|
||||||
volatile unsigned short *tramp;
|
|
||||||
|
|
||||||
/* Sanity check on the cif ABI. */
|
|
||||||
{
|
|
||||||
int abi = cif->abi;
|
|
||||||
if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)))
|
|
||||||
return FFI_BAD_ABI;
|
|
||||||
}
|
|
||||||
|
|
||||||
tramp = (volatile unsigned short *) &closure->tramp[0];
|
|
||||||
|
|
||||||
tramp[0] = 0xbb49; /* mov <code>, %r11 */
|
|
||||||
*((unsigned long long * volatile) &tramp[1])
|
|
||||||
= (unsigned long) ffi_closure_unix64;
|
|
||||||
tramp[5] = 0xba49; /* mov <data>, %r10 */
|
|
||||||
*((unsigned long long * volatile) &tramp[6])
|
|
||||||
= (unsigned long) codeloc;
|
|
||||||
|
|
||||||
/* Set the carry bit iff the function uses any sse registers.
|
|
||||||
This is clc or stc, together with the first byte of the jmp. */
|
|
||||||
tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8;
|
|
||||||
|
|
||||||
tramp[11] = 0xe3ff; /* jmp *%r11 */
|
|
||||||
|
|
||||||
closure->cif = cif;
|
|
||||||
closure->fun = fun;
|
|
||||||
closure->user_data = user_data;
|
|
||||||
|
|
||||||
return FFI_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
|
|
||||||
struct register_args *reg_args, char *argp)
|
|
||||||
{
|
|
||||||
ffi_cif *cif;
|
|
||||||
void **avalue;
|
|
||||||
ffi_type **arg_types;
|
|
||||||
long i, avn;
|
|
||||||
int gprcount, ssecount, ngpr, nsse;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
avalue = alloca(cif->nargs * sizeof(void *));
|
|
||||||
gprcount = ssecount = 0;
|
|
||||||
|
|
||||||
ret = cif->rtype->type;
|
|
||||||
if (ret != FFI_TYPE_VOID)
|
|
||||||
{
|
|
||||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
|
||||||
int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse);
|
|
||||||
if (n == 0)
|
|
||||||
{
|
|
||||||
/* The return value goes in memory. Arrange for the closure
|
|
||||||
return value to go directly back to the original caller. */
|
|
||||||
rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
|
|
||||||
/* We don't have to do anything in asm for the return. */
|
|
||||||
ret = FFI_TYPE_VOID;
|
|
||||||
}
|
|
||||||
else if (ret == FFI_TYPE_STRUCT && n == 2)
|
|
||||||
{
|
|
||||||
/* Mark which register the second word of the structure goes in. */
|
|
||||||
_Bool sse0 = SSE_CLASS_P (classes[0]);
|
|
||||||
_Bool sse1 = SSE_CLASS_P (classes[1]);
|
|
||||||
if (!sse0 && sse1)
|
|
||||||
ret |= 1 << 8;
|
|
||||||
else if (sse0 && !sse1)
|
|
||||||
ret |= 1 << 9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avn = cif->nargs;
|
|
||||||
arg_types = cif->arg_types;
|
|
||||||
|
|
||||||
for (i = 0; i < avn; ++i)
|
|
||||||
{
|
|
||||||
enum x86_64_reg_class classes[MAX_CLASSES];
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse);
|
|
||||||
if (n == 0
|
|
||||||
|| gprcount + ngpr > MAX_GPR_REGS
|
|
||||||
|| ssecount + nsse > MAX_SSE_REGS)
|
|
||||||
{
|
|
||||||
long align = arg_types[i]->alignment;
|
|
||||||
|
|
||||||
/* Stack arguments are *always* at least 8 byte aligned. */
|
|
||||||
if (align < 8)
|
|
||||||
align = 8;
|
|
||||||
|
|
||||||
/* Pass this argument in memory. */
|
|
||||||
argp = (void *) ALIGN (argp, align);
|
|
||||||
avalue[i] = argp;
|
|
||||||
argp += arg_types[i]->size;
|
|
||||||
}
|
|
||||||
/* If the argument is in a single register, or two consecutive
|
|
||||||
integer registers, then we can use that address directly. */
|
|
||||||
else if (n == 1
|
|
||||||
|| (n == 2 && !(SSE_CLASS_P (classes[0])
|
|
||||||
|| SSE_CLASS_P (classes[1]))))
|
|
||||||
{
|
|
||||||
/* The argument is in a single register. */
|
|
||||||
if (SSE_CLASS_P (classes[0]))
|
|
||||||
{
|
|
||||||
avalue[i] = ®_args->sse[ssecount];
|
|
||||||
ssecount += n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
avalue[i] = ®_args->gpr[gprcount];
|
|
||||||
gprcount += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Otherwise, allocate space to make them consecutive. */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *a = alloca (16);
|
|
||||||
int j;
|
|
||||||
|
|
||||||
avalue[i] = a;
|
|
||||||
for (j = 0; j < n; j++, a += 8)
|
|
||||||
{
|
|
||||||
if (SSE_CLASS_P (classes[j]))
|
|
||||||
memcpy (a, ®_args->sse[ssecount++], 8);
|
|
||||||
else
|
|
||||||
memcpy (a, ®_args->gpr[gprcount++], 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Invoke the closure. */
|
|
||||||
closure->fun (cif, rvalue, avalue, closure->user_data);
|
|
||||||
|
|
||||||
/* Tell assembly how to perform return type promotions. */
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __x86_64__ */
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,363 +0,0 @@
|
|||||||
Status
|
|
||||||
======
|
|
||||||
|
|
||||||
libffi-3.0.12 was released on XXXXXXX. Check the libffi web page for
|
|
||||||
updates: <URL:http://sourceware.org/libffi/>.
|
|
||||||
|
|
||||||
|
|
||||||
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 essentially 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Supported Platforms
|
|
||||||
===================
|
|
||||||
|
|
||||||
Libffi has been ported to many different platforms.
|
|
||||||
For specific configuration details and testing status, please
|
|
||||||
refer to the wiki page here:
|
|
||||||
|
|
||||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
|
|
||||||
|
|
||||||
At the time of release, the following basic configurations have been
|
|
||||||
tested:
|
|
||||||
|
|
||||||
|--------------+------------------|
|
|
||||||
| Architecture | Operating System |
|
|
||||||
|--------------+------------------|
|
|
||||||
| Alpha | Linux |
|
|
||||||
| Alpha | Tru64 |
|
|
||||||
| ARM | Linux |
|
|
||||||
| ARM | iOS |
|
|
||||||
| AVR32 | Linux |
|
|
||||||
| Blackfin | uClinux |
|
|
||||||
| HPPA | HPUX |
|
|
||||||
| IA-64 | Linux |
|
|
||||||
| M68K | FreeMiNT |
|
|
||||||
| M68K | RTEMS |
|
|
||||||
| MIPS | IRIX |
|
|
||||||
| MIPS | Linux |
|
|
||||||
| MIPS | RTEMS |
|
|
||||||
| MIPS64 | Linux |
|
|
||||||
| PowerPC | AMIGA |
|
|
||||||
| PowerPC | Linux |
|
|
||||||
| PowerPC | Mac OSX |
|
|
||||||
| PowerPC | FreeBSD |
|
|
||||||
| PowerPC64 | Linux |
|
|
||||||
| S390 | Linux |
|
|
||||||
| S390X | Linux |
|
|
||||||
| SPARC | Linux |
|
|
||||||
| SPARC | Solaris |
|
|
||||||
| SPARC64 | Linux |
|
|
||||||
| SPARC64 | FreeBSD |
|
|
||||||
| X86 | FreeBSD |
|
|
||||||
| X86 | Interix |
|
|
||||||
| X86 | kFreeBSD |
|
|
||||||
| X86 | Linux |
|
|
||||||
| X86 | Mac OSX |
|
|
||||||
| X86 | OpenBSD |
|
|
||||||
| X86 | OS/2 |
|
|
||||||
| X86 | Solaris |
|
|
||||||
| X86 | Windows/Cygwin |
|
|
||||||
| X86 | Windows/MingW |
|
|
||||||
| X86-64 | FreeBSD |
|
|
||||||
| X86-64 | Linux |
|
|
||||||
| X86-64 | Linux/x32 |
|
|
||||||
| X86-64 | OpenBSD |
|
|
||||||
| X86-64 | Windows/MingW |
|
|
||||||
|--------------+------------------|
|
|
||||||
|
|
||||||
Please send additional platform test results to
|
|
||||||
libffi-discuss@sourceware.org and feel free to update the wiki page
|
|
||||||
above.
|
|
||||||
|
|
||||||
Installing libffi
|
|
||||||
=================
|
|
||||||
|
|
||||||
First you must configure the distribution for your particular
|
|
||||||
system. Go to the directory you wish to build libffi in and run the
|
|
||||||
"configure" program found in the root directory of the libffi source
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
You may want to tell configure where to install the libffi library and
|
|
||||||
header files. To do that, use the --prefix configure switch. Libffi
|
|
||||||
will install under /usr/local by default.
|
|
||||||
|
|
||||||
If you want to enable extra run-time debugging checks use the the
|
|
||||||
--enable-debug configure switch. This is useful when your program dies
|
|
||||||
mysteriously while using libffi.
|
|
||||||
|
|
||||||
Another useful configure switch is --enable-purify-safety. Using this
|
|
||||||
will add some extra code which will suppress certain warnings when you
|
|
||||||
are using Purify with libffi. Only use this switch when using
|
|
||||||
Purify, as it will slow down the library.
|
|
||||||
|
|
||||||
It's also possible to build libffi on Windows platforms with
|
|
||||||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
|
||||||
wrapper script during configuration like so:
|
|
||||||
|
|
||||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
|
||||||
|
|
||||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
|
||||||
You may also need to specify --build appropriately. When building with MSVC
|
|
||||||
under a MingW environment, you may need to remove the line in configure
|
|
||||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
|
||||||
present in MingW, and is not required when using MingW-style paths.)
|
|
||||||
|
|
||||||
For iOS builds, run generate-ios-source-and-headers.py and then
|
|
||||||
libffi.xcodeproj should work.
|
|
||||||
|
|
||||||
Configure has many other options. Use "configure --help" to see them all.
|
|
||||||
|
|
||||||
Once configure has finished, type "make". Note that you must be using
|
|
||||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
|
||||||
|
|
||||||
To ensure that libffi is working as advertised, type "make check".
|
|
||||||
This will require that you have DejaGNU installed.
|
|
||||||
|
|
||||||
To install the library and header files, type "make install".
|
|
||||||
|
|
||||||
|
|
||||||
History
|
|
||||||
=======
|
|
||||||
|
|
||||||
See the ChangeLog files for details.
|
|
||||||
|
|
||||||
3.0.12 XXX-XX-XX
|
|
||||||
Add Blackfin support.
|
|
||||||
|
|
||||||
3.0.11 Apr-11-12
|
|
||||||
Lots of build fixes.
|
|
||||||
Add Amiga newer MacOS support.
|
|
||||||
Add support for variadic functions (ffi_prep_cif_var).
|
|
||||||
Add Linux/x32 support.
|
|
||||||
Add thiscall, fastcall and MSVC cdecl support on Windows.
|
|
||||||
Add Amiga and newer MacOS support.
|
|
||||||
Add m68k FreeMiNT support.
|
|
||||||
Integration with iOS' xcode build tools.
|
|
||||||
Fix Octeon and MC68881 support.
|
|
||||||
Fix code pessimizations.
|
|
||||||
Lots of build fixes.
|
|
||||||
|
|
||||||
3.0.10 Aug-23-11
|
|
||||||
Add support for Apple's iOS.
|
|
||||||
Add support for ARM VFP ABI.
|
|
||||||
Add RTEMS support for MIPS and M68K.
|
|
||||||
Fix instruction cache clearing problems on
|
|
||||||
ARM and SPARC.
|
|
||||||
Fix the N64 build on mips-sgi-irix6.5.
|
|
||||||
Enable builds with Microsoft's compiler.
|
|
||||||
Enable x86 builds with Oracle's Solaris compiler.
|
|
||||||
Fix support for calling code compiled with Oracle's Sparc
|
|
||||||
Solaris compiler.
|
|
||||||
Testsuite fixes for Tru64 Unix.
|
|
||||||
Additional platform support.
|
|
||||||
|
|
||||||
3.0.9 Dec-31-09
|
|
||||||
Add AVR32 and win64 ports. Add ARM softfp support.
|
|
||||||
Many fixes for AIX, Solaris, HP-UX, *BSD.
|
|
||||||
Several PowerPC and x86-64 bug fixes.
|
|
||||||
Build DLL for windows.
|
|
||||||
|
|
||||||
3.0.8 Dec-19-08
|
|
||||||
Add *BSD, BeOS, and PA-Linux support.
|
|
||||||
|
|
||||||
3.0.7 Nov-11-08
|
|
||||||
Fix for ppc FreeBSD.
|
|
||||||
(thanks to Andreas Tobler)
|
|
||||||
|
|
||||||
3.0.6 Jul-17-08
|
|
||||||
Fix for closures on sh.
|
|
||||||
Mark the sh/sh64 stack as non-executable.
|
|
||||||
(both thanks to Kaz Kojima)
|
|
||||||
|
|
||||||
3.0.5 Apr-3-08
|
|
||||||
Fix libffi.pc file.
|
|
||||||
Fix #define ARM for IcedTea users.
|
|
||||||
Fix x86 closure bug.
|
|
||||||
|
|
||||||
3.0.4 Feb-24-08
|
|
||||||
Fix x86 OpenBSD configury.
|
|
||||||
|
|
||||||
3.0.3 Feb-22-08
|
|
||||||
Enable x86 OpenBSD thanks to Thomas Heller, and
|
|
||||||
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
|
|
||||||
Clean up test instruction in README.
|
|
||||||
|
|
||||||
3.0.2 Feb-21-08
|
|
||||||
Improved x86 FreeBSD support.
|
|
||||||
Thanks to Björn König.
|
|
||||||
|
|
||||||
3.0.1 Feb-15-08
|
|
||||||
Fix instruction cache flushing bug on MIPS.
|
|
||||||
Thanks to David Daney.
|
|
||||||
|
|
||||||
3.0.0 Feb-15-08
|
|
||||||
Many changes, mostly thanks to the GCC project.
|
|
||||||
Cygnus Solutions is now Red Hat.
|
|
||||||
|
|
||||||
[10 years go by...]
|
|
||||||
|
|
||||||
1.20 Oct-5-98
|
|
||||||
Raffaele Sena produces ARM port.
|
|
||||||
|
|
||||||
1.19 Oct-5-98
|
|
||||||
Fixed x86 long double and long long return support.
|
|
||||||
m68k bug fixes from Andreas Schwab.
|
|
||||||
Patch for DU assembler compatibility for the Alpha from Richard
|
|
||||||
Henderson.
|
|
||||||
|
|
||||||
1.18 Apr-17-98
|
|
||||||
Bug fixes and MIPS configuration changes.
|
|
||||||
|
|
||||||
1.17 Feb-24-98
|
|
||||||
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
|
|
||||||
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
|
|
||||||
|
|
||||||
1.16 Feb-11-98
|
|
||||||
Richard Henderson produces Alpha port.
|
|
||||||
|
|
||||||
1.15 Dec-4-97
|
|
||||||
Fixed an n32 ABI bug. New libtool, auto* support.
|
|
||||||
|
|
||||||
1.14 May-13-97
|
|
||||||
libtool is now used to generate shared and static libraries.
|
|
||||||
Fixed a minor portability problem reported by Russ McManus
|
|
||||||
<mcmanr@eq.gs.com>.
|
|
||||||
|
|
||||||
1.13 Dec-2-96
|
|
||||||
Added --enable-purify-safety to keep Purify from complaining
|
|
||||||
about certain low level code.
|
|
||||||
Sparc fix for calling functions with < 6 args.
|
|
||||||
Linux x86 a.out fix.
|
|
||||||
|
|
||||||
1.12 Nov-22-96
|
|
||||||
Added missing ffi_type_void, needed for supporting void return
|
|
||||||
types. Fixed test case for non MIPS machines. Cygnus Support
|
|
||||||
is now Cygnus Solutions.
|
|
||||||
|
|
||||||
1.11 Oct-30-96
|
|
||||||
Added notes about GNU make.
|
|
||||||
|
|
||||||
1.10 Oct-29-96
|
|
||||||
Added configuration fix for non GNU compilers.
|
|
||||||
|
|
||||||
1.09 Oct-29-96
|
|
||||||
Added --enable-debug configure switch. Clean-ups based on LCLint
|
|
||||||
feedback. ffi_mips.h is always installed. Many configuration
|
|
||||||
fixes. Fixed ffitest.c for sparc builds.
|
|
||||||
|
|
||||||
1.08 Oct-15-96
|
|
||||||
Fixed n32 problem. Many clean-ups.
|
|
||||||
|
|
||||||
1.07 Oct-14-96
|
|
||||||
Gordon Irlam rewrites v8.S again. Bug fixes.
|
|
||||||
|
|
||||||
1.06 Oct-14-96
|
|
||||||
Gordon Irlam improved the sparc port.
|
|
||||||
|
|
||||||
1.05 Oct-14-96
|
|
||||||
Interface changes based on feedback.
|
|
||||||
|
|
||||||
1.04 Oct-11-96
|
|
||||||
Sparc port complete (modulo struct passing bug).
|
|
||||||
|
|
||||||
1.03 Oct-10-96
|
|
||||||
Passing struct args, and returning struct values works for
|
|
||||||
all architectures/calling conventions. Expanded tests.
|
|
||||||
|
|
||||||
1.02 Oct-9-96
|
|
||||||
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
|
|
||||||
Added "make test".
|
|
||||||
|
|
||||||
1.01 Oct-8-96
|
|
||||||
Fixed float passing bug in mips version. Restructured some
|
|
||||||
of the code. Builds cleanly with SGI tools.
|
|
||||||
|
|
||||||
1.00 Oct-7-96
|
|
||||||
First release. No public announcement.
|
|
||||||
|
|
||||||
|
|
||||||
Authors & Credits
|
|
||||||
=================
|
|
||||||
|
|
||||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
|
||||||
|
|
||||||
The developers of the GNU Compiler Collection project have made
|
|
||||||
innumerable valuable contributions. See the ChangeLog file for
|
|
||||||
details.
|
|
||||||
|
|
||||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
|
||||||
gencall library for Silicon Graphics machines.
|
|
||||||
|
|
||||||
The closure mechanism was designed and implemented by Kresten Krab
|
|
||||||
Thorup.
|
|
||||||
|
|
||||||
Major processor architecture ports were contributed by the following
|
|
||||||
developers:
|
|
||||||
|
|
||||||
alpha Richard Henderson
|
|
||||||
arm Raffaele Sena
|
|
||||||
cris Simon Posnjak, Hans-Peter Nilsson
|
|
||||||
frv Anthony Green
|
|
||||||
ia64 Hans Boehm
|
|
||||||
m32r Kazuhiro Inaoka
|
|
||||||
m68k Andreas Schwab
|
|
||||||
mips Anthony Green, Casey Marshall
|
|
||||||
mips64 David Daney
|
|
||||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
|
||||||
powerpc Geoffrey Keating, Andreas Tobler,
|
|
||||||
David Edelsohn, John Hornkvist
|
|
||||||
powerpc64 Jakub Jelinek
|
|
||||||
s390 Gerhard Tonn, Ulrich Weigand
|
|
||||||
sh Kaz Kojima
|
|
||||||
sh64 Kaz Kojima
|
|
||||||
sparc Anthony Green, Gordon Irlam
|
|
||||||
x86 Anthony Green, Jon Beniston
|
|
||||||
x86-64 Bo Thorsen
|
|
||||||
|
|
||||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
|
||||||
stepping through the code and tracking down bugs.
|
|
||||||
|
|
||||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
|
||||||
configuration help.
|
|
||||||
|
|
||||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
|
||||||
interface.
|
|
||||||
|
|
||||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
|
||||||
|
|
||||||
Alex Oliva solved the executable page problem for SElinux.
|
|
||||||
|
|
||||||
The list above is almost certainly incomplete and inaccurate. I'm
|
|
||||||
happy to make corrections or additions upon request.
|
|
||||||
|
|
||||||
If you have a problem, or have found a bug, please send a note to the
|
|
||||||
author at green@moxielogic.com, or the project mailing list at
|
|
||||||
libffi-discuss@sourceware.org.
|
|
||||||
@@ -1,595 +0,0 @@
|
|||||||
// !$*UTF8*$!
|
|
||||||
{
|
|
||||||
archiveVersion = 1;
|
|
||||||
classes = {
|
|
||||||
};
|
|
||||||
objectVersion = 46;
|
|
||||||
objects = {
|
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
|
||||||
6C43CBDC1534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBD1534F76F00162364 /* ffi.c */; };
|
|
||||||
6C43CBDD1534F76F00162364 /* sysv.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBBF1534F76F00162364 /* sysv.S */; };
|
|
||||||
6C43CBDE1534F76F00162364 /* trampoline.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC01534F76F00162364 /* trampoline.S */; };
|
|
||||||
6C43CBE61534F76F00162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBC91534F76F00162364 /* darwin.S */; };
|
|
||||||
6C43CBE81534F76F00162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBCB1534F76F00162364 /* ffi.c */; };
|
|
||||||
6C43CBE91534F76F00162364 /* ffi64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CBCC1534F76F00162364 /* ffi64.c */; };
|
|
||||||
6C43CC1F1534F77800162364 /* darwin.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC051534F77800162364 /* darwin.S */; };
|
|
||||||
6C43CC201534F77800162364 /* darwin64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC061534F77800162364 /* darwin64.S */; };
|
|
||||||
6C43CC211534F77800162364 /* ffi.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC071534F77800162364 /* ffi.c */; };
|
|
||||||
6C43CC221534F77800162364 /* ffi64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC081534F77800162364 /* ffi64.c */; };
|
|
||||||
6C43CC2F1534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
|
|
||||||
6C43CC301534F7BE00162364 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC281534F7BE00162364 /* closures.c */; };
|
|
||||||
6C43CC311534F7BE00162364 /* debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC291534F7BE00162364 /* debug.c */; };
|
|
||||||
6C43CC321534F7BE00162364 /* debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC291534F7BE00162364 /* debug.c */; };
|
|
||||||
6C43CC331534F7BE00162364 /* dlmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2A1534F7BE00162364 /* dlmalloc.c */; };
|
|
||||||
6C43CC341534F7BE00162364 /* dlmalloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2A1534F7BE00162364 /* dlmalloc.c */; };
|
|
||||||
6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
|
|
||||||
6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2B1534F7BE00162364 /* java_raw_api.c */; };
|
|
||||||
6C43CC371534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
|
|
||||||
6C43CC381534F7BE00162364 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2C1534F7BE00162364 /* prep_cif.c */; };
|
|
||||||
6C43CC391534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
|
|
||||||
6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2D1534F7BE00162364 /* raw_api.c */; };
|
|
||||||
6C43CC3B1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
|
|
||||||
6C43CC3C1534F7BE00162364 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C43CC2E1534F7BE00162364 /* types.c */; };
|
|
||||||
6C43CC971535032600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8D1535032600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CC981535032600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8E1535032600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CC991535032600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC8F1535032600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC901535032600162364 /* ffi_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CC9B1535032600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC911535032600162364 /* fficonfig.h */; };
|
|
||||||
6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC921535032600162364 /* fficonfig_i386.h */; };
|
|
||||||
6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC931535032600162364 /* fficonfig_x86_64.h */; };
|
|
||||||
6C43CC9E1535032600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC941535032600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC951535032600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CC961535032600162364 /* ffitarget_x86_64.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCAD1535039600162364 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA21535039600162364 /* ffi.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA31535039600162364 /* ffi_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCAF1535039600162364 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA41535039600162364 /* ffi_common.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCB01535039600162364 /* ffi_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA51535039600162364 /* ffi_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCB11535039600162364 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA61535039600162364 /* fficonfig.h */; };
|
|
||||||
6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA71535039600162364 /* fficonfig_armv7.h */; };
|
|
||||||
6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA81535039600162364 /* fficonfig_i386.h */; };
|
|
||||||
6C43CCB41535039600162364 /* ffitarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCA91535039600162364 /* ffitarget.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAA1535039600162364 /* ffitarget_arm.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAB1535039600162364 /* ffitarget_armv7.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C43CCAC1535039600162364 /* ffitarget_i386.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
||||||
/* End PBXBuildFile section */
|
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
|
||||||
6C43CB3D1534E9D100162364 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
6C43CBBD1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
|
|
||||||
6C43CBBF1534F76F00162364 /* sysv.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv.S; sourceTree = "<group>"; };
|
|
||||||
6C43CBC01534F76F00162364 /* trampoline.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline.S; sourceTree = "<group>"; };
|
|
||||||
6C43CBC91534F76F00162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
|
|
||||||
6C43CBCB1534F76F00162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
|
|
||||||
6C43CBCC1534F76F00162364 /* ffi64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64.c; sourceTree = "<group>"; };
|
|
||||||
6C43CC051534F77800162364 /* darwin.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin.S; sourceTree = "<group>"; };
|
|
||||||
6C43CC061534F77800162364 /* darwin64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64.S; sourceTree = "<group>"; };
|
|
||||||
6C43CC071534F77800162364 /* ffi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi.c; sourceTree = "<group>"; };
|
|
||||||
6C43CC081534F77800162364 /* ffi64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64.c; sourceTree = "<group>"; };
|
|
||||||
6C43CC281534F7BE00162364 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = closures.c; path = src/closures.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC291534F7BE00162364 /* debug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = debug.c; path = src/debug.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC2A1534F7BE00162364 /* dlmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = dlmalloc.c; path = src/dlmalloc.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC2B1534F7BE00162364 /* java_raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = java_raw_api.c; path = src/java_raw_api.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC2C1534F7BE00162364 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prep_cif.c; path = src/prep_cif.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC2D1534F7BE00162364 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = raw_api.c; path = src/raw_api.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC2E1534F7BE00162364 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = types.c; path = src/types.c; sourceTree = SOURCE_ROOT; };
|
|
||||||
6C43CC8D1535032600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC8E1535032600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC8F1535032600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC901535032600162364 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC911535032600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC921535032600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC931535032600162364 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC941535032600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC951535032600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
|
|
||||||
6C43CC961535032600162364 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA21535039600162364 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA31535039600162364 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA41535039600162364 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA51535039600162364 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA61535039600162364 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA71535039600162364 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA81535039600162364 /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCA91535039600162364 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCAA1535039600162364 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCAB1535039600162364 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = "<group>"; };
|
|
||||||
6C43CCAC1535039600162364 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = "<group>"; };
|
|
||||||
F6F980BA147386130008F121 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
/* End PBXFileReference section */
|
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
|
||||||
6C43CB3A1534E9D100162364 /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
F6F980B7147386130008F121 /* Frameworks */ = {
|
|
||||||
isa = PBXFrameworksBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXFrameworksBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
|
||||||
6C43CBAF1534F76F00162364 /* iOS */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CCA11535039600162364 /* include */,
|
|
||||||
6C43CBBB1534F76F00162364 /* src */,
|
|
||||||
);
|
|
||||||
name = iOS;
|
|
||||||
path = ios;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CBBB1534F76F00162364 /* src */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CBC81534F76F00162364 /* x86 */,
|
|
||||||
6C43CBBC1534F76F00162364 /* arm */,
|
|
||||||
);
|
|
||||||
path = src;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CBBC1534F76F00162364 /* arm */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CBBD1534F76F00162364 /* ffi.c */,
|
|
||||||
6C43CBBF1534F76F00162364 /* sysv.S */,
|
|
||||||
6C43CBC01534F76F00162364 /* trampoline.S */,
|
|
||||||
);
|
|
||||||
path = arm;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CBC81534F76F00162364 /* x86 */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CBC91534F76F00162364 /* darwin.S */,
|
|
||||||
6C43CBCB1534F76F00162364 /* ffi.c */,
|
|
||||||
6C43CBCC1534F76F00162364 /* ffi64.c */,
|
|
||||||
);
|
|
||||||
path = x86;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CBF01534F77800162364 /* OS X */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CC8C1535032600162364 /* include */,
|
|
||||||
6C43CBFC1534F77800162364 /* src */,
|
|
||||||
);
|
|
||||||
name = "OS X";
|
|
||||||
path = osx;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CBFC1534F77800162364 /* src */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CC041534F77800162364 /* x86 */,
|
|
||||||
);
|
|
||||||
path = src;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CC041534F77800162364 /* x86 */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CC051534F77800162364 /* darwin.S */,
|
|
||||||
6C43CC061534F77800162364 /* darwin64.S */,
|
|
||||||
6C43CC071534F77800162364 /* ffi.c */,
|
|
||||||
6C43CC081534F77800162364 /* ffi64.c */,
|
|
||||||
);
|
|
||||||
path = x86;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CC3D1534F7C400162364 /* src */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CC281534F7BE00162364 /* closures.c */,
|
|
||||||
6C43CC291534F7BE00162364 /* debug.c */,
|
|
||||||
6C43CC2A1534F7BE00162364 /* dlmalloc.c */,
|
|
||||||
6C43CC2B1534F7BE00162364 /* java_raw_api.c */,
|
|
||||||
6C43CC2C1534F7BE00162364 /* prep_cif.c */,
|
|
||||||
6C43CC2D1534F7BE00162364 /* raw_api.c */,
|
|
||||||
6C43CC2E1534F7BE00162364 /* types.c */,
|
|
||||||
);
|
|
||||||
name = src;
|
|
||||||
path = ios;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CC8C1535032600162364 /* include */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CC8D1535032600162364 /* ffi.h */,
|
|
||||||
6C43CC8E1535032600162364 /* ffi_common.h */,
|
|
||||||
6C43CC8F1535032600162364 /* ffi_i386.h */,
|
|
||||||
6C43CC901535032600162364 /* ffi_x86_64.h */,
|
|
||||||
6C43CC911535032600162364 /* fficonfig.h */,
|
|
||||||
6C43CC921535032600162364 /* fficonfig_i386.h */,
|
|
||||||
6C43CC931535032600162364 /* fficonfig_x86_64.h */,
|
|
||||||
6C43CC941535032600162364 /* ffitarget.h */,
|
|
||||||
6C43CC951535032600162364 /* ffitarget_i386.h */,
|
|
||||||
6C43CC961535032600162364 /* ffitarget_x86_64.h */,
|
|
||||||
);
|
|
||||||
path = include;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
6C43CCA11535039600162364 /* include */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CCA21535039600162364 /* ffi.h */,
|
|
||||||
6C43CCA31535039600162364 /* ffi_armv7.h */,
|
|
||||||
6C43CCA41535039600162364 /* ffi_common.h */,
|
|
||||||
6C43CCA51535039600162364 /* ffi_i386.h */,
|
|
||||||
6C43CCA61535039600162364 /* fficonfig.h */,
|
|
||||||
6C43CCA71535039600162364 /* fficonfig_armv7.h */,
|
|
||||||
6C43CCA81535039600162364 /* fficonfig_i386.h */,
|
|
||||||
6C43CCA91535039600162364 /* ffitarget.h */,
|
|
||||||
6C43CCAA1535039600162364 /* ffitarget_arm.h */,
|
|
||||||
6C43CCAB1535039600162364 /* ffitarget_armv7.h */,
|
|
||||||
6C43CCAC1535039600162364 /* ffitarget_i386.h */,
|
|
||||||
);
|
|
||||||
path = include;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
F6B0839514721EE50031D8A1 = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
6C43CC3D1534F7C400162364 /* src */,
|
|
||||||
6C43CBAF1534F76F00162364 /* iOS */,
|
|
||||||
6C43CBF01534F77800162364 /* OS X */,
|
|
||||||
F6F980C6147386260008F121 /* Products */,
|
|
||||||
);
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
F6F980C6147386260008F121 /* Products */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
F6F980BA147386130008F121 /* libffi.a */,
|
|
||||||
6C43CB3D1534E9D100162364 /* libffi.a */,
|
|
||||||
);
|
|
||||||
name = Products;
|
|
||||||
path = ../..;
|
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
|
||||||
|
|
||||||
/* Begin PBXHeadersBuildPhase section */
|
|
||||||
6C43CB3B1534E9D100162364 /* Headers */ = {
|
|
||||||
isa = PBXHeadersBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
6C43CC971535032600162364 /* ffi.h in Headers */,
|
|
||||||
6C43CC981535032600162364 /* ffi_common.h in Headers */,
|
|
||||||
6C43CC991535032600162364 /* ffi_i386.h in Headers */,
|
|
||||||
6C43CC9A1535032600162364 /* ffi_x86_64.h in Headers */,
|
|
||||||
6C43CC9E1535032600162364 /* ffitarget.h in Headers */,
|
|
||||||
6C43CC9F1535032600162364 /* ffitarget_i386.h in Headers */,
|
|
||||||
6C43CCA01535032600162364 /* ffitarget_x86_64.h in Headers */,
|
|
||||||
6C43CC9B1535032600162364 /* fficonfig.h in Headers */,
|
|
||||||
6C43CC9C1535032600162364 /* fficonfig_i386.h in Headers */,
|
|
||||||
6C43CC9D1535032600162364 /* fficonfig_x86_64.h in Headers */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
F6F980B8147386130008F121 /* Headers */ = {
|
|
||||||
isa = PBXHeadersBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
6C43CCAD1535039600162364 /* ffi.h in Headers */,
|
|
||||||
6C43CCAE1535039600162364 /* ffi_armv7.h in Headers */,
|
|
||||||
6C43CCAF1535039600162364 /* ffi_common.h in Headers */,
|
|
||||||
6C43CCB01535039600162364 /* ffi_i386.h in Headers */,
|
|
||||||
6C43CCB41535039600162364 /* ffitarget.h in Headers */,
|
|
||||||
6C43CCB51535039600162364 /* ffitarget_arm.h in Headers */,
|
|
||||||
6C43CCB61535039600162364 /* ffitarget_armv7.h in Headers */,
|
|
||||||
6C43CCB71535039600162364 /* ffitarget_i386.h in Headers */,
|
|
||||||
6C43CCB11535039600162364 /* fficonfig.h in Headers */,
|
|
||||||
6C43CCB21535039600162364 /* fficonfig_armv7.h in Headers */,
|
|
||||||
6C43CCB31535039600162364 /* fficonfig_i386.h in Headers */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXHeadersBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
|
||||||
6C43CB3C1534E9D100162364 /* libffi OS X */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = 6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */;
|
|
||||||
buildPhases = (
|
|
||||||
6C43CC401534FF3B00162364 /* Generate Source and Headers */,
|
|
||||||
6C43CB391534E9D100162364 /* Sources */,
|
|
||||||
6C43CB3A1534E9D100162364 /* Frameworks */,
|
|
||||||
6C43CB3B1534E9D100162364 /* Headers */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = "libffi OS X";
|
|
||||||
productName = "ffi OS X";
|
|
||||||
productReference = 6C43CB3D1534E9D100162364 /* libffi.a */;
|
|
||||||
productType = "com.apple.product-type.library.static";
|
|
||||||
};
|
|
||||||
F6F980B9147386130008F121 /* libffi iOS */ = {
|
|
||||||
isa = PBXNativeTarget;
|
|
||||||
buildConfigurationList = F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */;
|
|
||||||
buildPhases = (
|
|
||||||
6C43CC3E1534F8E200162364 /* Generate Trampoline */,
|
|
||||||
6C43CC3F1534FF1B00162364 /* Generate Source and Headers */,
|
|
||||||
F6F980B6147386130008F121 /* Sources */,
|
|
||||||
F6F980B7147386130008F121 /* Frameworks */,
|
|
||||||
F6F980B8147386130008F121 /* Headers */,
|
|
||||||
);
|
|
||||||
buildRules = (
|
|
||||||
);
|
|
||||||
dependencies = (
|
|
||||||
);
|
|
||||||
name = "libffi iOS";
|
|
||||||
productName = ffi;
|
|
||||||
productReference = F6F980BA147386130008F121 /* libffi.a */;
|
|
||||||
productType = "com.apple.product-type.library.static";
|
|
||||||
};
|
|
||||||
/* End PBXNativeTarget section */
|
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
|
||||||
F6B0839714721EE50031D8A1 /* Project object */ = {
|
|
||||||
isa = PBXProject;
|
|
||||||
attributes = {
|
|
||||||
LastUpgradeCheck = 0430;
|
|
||||||
};
|
|
||||||
buildConfigurationList = F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */;
|
|
||||||
compatibilityVersion = "Xcode 3.2";
|
|
||||||
developmentRegion = English;
|
|
||||||
hasScannedForEncodings = 0;
|
|
||||||
knownRegions = (
|
|
||||||
en,
|
|
||||||
);
|
|
||||||
mainGroup = F6B0839514721EE50031D8A1;
|
|
||||||
productRefGroup = F6B0839514721EE50031D8A1;
|
|
||||||
projectDirPath = "";
|
|
||||||
projectRoot = "";
|
|
||||||
targets = (
|
|
||||||
F6F980B9147386130008F121 /* libffi iOS */,
|
|
||||||
6C43CB3C1534E9D100162364 /* libffi OS X */,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
/* End PBXProject section */
|
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
|
||||||
6C43CC3E1534F8E200162364 /* Generate Trampoline */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Generate Trampoline";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /usr/bin/python;
|
|
||||||
shellScript = "import subprocess\nimport re\nimport os\nimport errno\nimport sys\n\ndef main():\n with open('src/arm/trampoline.S', 'w') as tramp_out:\n p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out)\n p.wait()\n\nif __name__ == '__main__':\n main()";
|
|
||||||
};
|
|
||||||
6C43CC3F1534FF1B00162364 /* Generate Source and Headers */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Generate Source and Headers";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/usr/bin/python generate-ios-source-and-headers.py";
|
|
||||||
};
|
|
||||||
6C43CC401534FF3B00162364 /* Generate Source and Headers */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "Generate Source and Headers";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "/usr/bin/python generate-osx-source-and-headers.py";
|
|
||||||
};
|
|
||||||
/* End PBXShellScriptBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
|
||||||
6C43CB391534E9D100162364 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
6C43CC1F1534F77800162364 /* darwin.S in Sources */,
|
|
||||||
6C43CC201534F77800162364 /* darwin64.S in Sources */,
|
|
||||||
6C43CC211534F77800162364 /* ffi.c in Sources */,
|
|
||||||
6C43CC221534F77800162364 /* ffi64.c in Sources */,
|
|
||||||
6C43CC301534F7BE00162364 /* closures.c in Sources */,
|
|
||||||
6C43CC321534F7BE00162364 /* debug.c in Sources */,
|
|
||||||
6C43CC341534F7BE00162364 /* dlmalloc.c in Sources */,
|
|
||||||
6C43CC361534F7BE00162364 /* java_raw_api.c in Sources */,
|
|
||||||
6C43CC381534F7BE00162364 /* prep_cif.c in Sources */,
|
|
||||||
6C43CC3A1534F7BE00162364 /* raw_api.c in Sources */,
|
|
||||||
6C43CC3C1534F7BE00162364 /* types.c in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
F6F980B6147386130008F121 /* Sources */ = {
|
|
||||||
isa = PBXSourcesBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
6C43CBDC1534F76F00162364 /* ffi.c in Sources */,
|
|
||||||
6C43CBDD1534F76F00162364 /* sysv.S in Sources */,
|
|
||||||
6C43CBDE1534F76F00162364 /* trampoline.S in Sources */,
|
|
||||||
6C43CBE61534F76F00162364 /* darwin.S in Sources */,
|
|
||||||
6C43CBE81534F76F00162364 /* ffi.c in Sources */,
|
|
||||||
6C43CBE91534F76F00162364 /* ffi64.c in Sources */,
|
|
||||||
6C43CC2F1534F7BE00162364 /* closures.c in Sources */,
|
|
||||||
6C43CC311534F7BE00162364 /* debug.c in Sources */,
|
|
||||||
6C43CC331534F7BE00162364 /* dlmalloc.c in Sources */,
|
|
||||||
6C43CC351534F7BE00162364 /* java_raw_api.c in Sources */,
|
|
||||||
6C43CC371534F7BE00162364 /* prep_cif.c in Sources */,
|
|
||||||
6C43CC391534F7BE00162364 /* raw_api.c in Sources */,
|
|
||||||
6C43CC3B1534F7BE00162364 /* types.c in Sources */,
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
};
|
|
||||||
/* End PBXSourcesBuildPhase section */
|
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
|
||||||
6C43CB4B1534E9D100162364 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
|
||||||
DSTROOT = /tmp/ffi.dst;
|
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
|
|
||||||
);
|
|
||||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
|
||||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
|
||||||
PRODUCT_NAME = ffi;
|
|
||||||
SDKROOT = macosx;
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
6C43CB4C1534E9D100162364 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
|
||||||
DSTROOT = /tmp/ffi.dst;
|
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
|
||||||
"$(inherited)",
|
|
||||||
"\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Library/Frameworks\"",
|
|
||||||
);
|
|
||||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
|
||||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
|
||||||
PRODUCT_NAME = ffi;
|
|
||||||
SDKROOT = macosx;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
F6B083AB14721EE50031D8A1 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
|
||||||
COPY_PHASE_STRIP = NO;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
|
||||||
"DEBUG=1",
|
|
||||||
"$(inherited)",
|
|
||||||
);
|
|
||||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
|
||||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
|
||||||
GCC_WARN_UNUSED_VALUE = NO;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
HEADER_SEARCH_PATHS = ios/include;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
F6B083AC14721EE50031D8A1 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
|
||||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
|
||||||
COPY_PHASE_STRIP = YES;
|
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = "";
|
|
||||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
|
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
|
||||||
GCC_WARN_UNUSED_VALUE = NO;
|
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
|
||||||
HEADER_SEARCH_PATHS = ios/include;
|
|
||||||
SDKROOT = iphoneos;
|
|
||||||
VALIDATE_PRODUCT = YES;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
F6F980C2147386130008F121 /* Debug */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ARCHS = (
|
|
||||||
armv6,
|
|
||||||
armv7,
|
|
||||||
);
|
|
||||||
DSTROOT = /tmp/ffi.dst;
|
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
|
||||||
GCC_THUMB_SUPPORT = NO;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
|
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
|
||||||
PRODUCT_NAME = ffi;
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
};
|
|
||||||
name = Debug;
|
|
||||||
};
|
|
||||||
F6F980C3147386130008F121 /* Release */ = {
|
|
||||||
isa = XCBuildConfiguration;
|
|
||||||
buildSettings = {
|
|
||||||
ARCHS = (
|
|
||||||
armv6,
|
|
||||||
armv7,
|
|
||||||
);
|
|
||||||
DSTROOT = /tmp/ffi.dst;
|
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
|
||||||
GCC_THUMB_SUPPORT = NO;
|
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 4.0;
|
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
|
||||||
PRODUCT_NAME = ffi;
|
|
||||||
SKIP_INSTALL = YES;
|
|
||||||
};
|
|
||||||
name = Release;
|
|
||||||
};
|
|
||||||
/* End XCBuildConfiguration section */
|
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
|
||||||
6C43CB4A1534E9D100162364 /* Build configuration list for PBXNativeTarget "libffi OS X" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
6C43CB4B1534E9D100162364 /* Debug */,
|
|
||||||
6C43CB4C1534E9D100162364 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
F6B0839A14721EE50031D8A1 /* Build configuration list for PBXProject "libffi" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
F6B083AB14721EE50031D8A1 /* Debug */,
|
|
||||||
F6B083AC14721EE50031D8A1 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
F6F980C4147386130008F121 /* Build configuration list for PBXNativeTarget "libffi iOS" */ = {
|
|
||||||
isa = XCConfigurationList;
|
|
||||||
buildConfigurations = (
|
|
||||||
F6F980C2147386130008F121 /* Debug */,
|
|
||||||
F6F980C3147386130008F121 /* Release */,
|
|
||||||
);
|
|
||||||
defaultConfigurationIsVisible = 0;
|
|
||||||
defaultConfigurationName = Release;
|
|
||||||
};
|
|
||||||
/* End XCConfigurationList section */
|
|
||||||
};
|
|
||||||
rootObject = F6B0839714721EE50031D8A1 /* Project object */;
|
|
||||||
}
|
|
||||||
4864
.pc/mint/ChangeLog
4864
.pc/mint/ChangeLog
File diff suppressed because it is too large
Load Diff
355
.pc/mint/README
355
.pc/mint/README
@@ -1,355 +0,0 @@
|
|||||||
Status
|
|
||||||
======
|
|
||||||
|
|
||||||
libffi-3.0.12 was released on *****************. Check the libffi web
|
|
||||||
page for updates: <URL:http://sourceware.org/libffi/>.
|
|
||||||
|
|
||||||
|
|
||||||
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 essentially 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.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Supported Platforms
|
|
||||||
===================
|
|
||||||
|
|
||||||
Libffi has been ported to many different platforms.
|
|
||||||
For specific configuration details and testing status, please
|
|
||||||
refer to the wiki page here:
|
|
||||||
|
|
||||||
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
|
|
||||||
|
|
||||||
At the time of release, the following basic configurations have been
|
|
||||||
tested:
|
|
||||||
|
|
||||||
|--------------+------------------|
|
|
||||||
| Architecture | Operating System |
|
|
||||||
|--------------+------------------|
|
|
||||||
| Alpha | Linux |
|
|
||||||
| Alpha | Tru64 |
|
|
||||||
| ARM | Linux |
|
|
||||||
| ARM | iOS |
|
|
||||||
| AVR32 | Linux |
|
|
||||||
| HPPA | HPUX |
|
|
||||||
| IA-64 | Linux |
|
|
||||||
| M68K | RTEMS |
|
|
||||||
| MIPS | IRIX |
|
|
||||||
| MIPS | Linux |
|
|
||||||
| MIPS | RTEMS |
|
|
||||||
| MIPS64 | Linux |
|
|
||||||
| PowerPC | AMIGA |
|
|
||||||
| PowerPC | Linux |
|
|
||||||
| PowerPC | Mac OSX |
|
|
||||||
| PowerPC | FreeBSD |
|
|
||||||
| PowerPC64 | Linux |
|
|
||||||
| S390 | Linux |
|
|
||||||
| S390X | Linux |
|
|
||||||
| SPARC | Linux |
|
|
||||||
| SPARC | Solaris |
|
|
||||||
| SPARC64 | Linux |
|
|
||||||
| SPARC64 | FreeBSD |
|
|
||||||
| X86 | FreeBSD |
|
|
||||||
| X86 | Interix |
|
|
||||||
| X86 | kFreeBSD |
|
|
||||||
| X86 | Linux |
|
|
||||||
| X86 | Linux/x32 |
|
|
||||||
| X86 | Mac OSX |
|
|
||||||
| X86 | OpenBSD |
|
|
||||||
| X86 | OS/2 |
|
|
||||||
| X86 | Solaris |
|
|
||||||
| X86 | Windows/Cygwin |
|
|
||||||
| X86 | Windows/MingW |
|
|
||||||
| X86-64 | FreeBSD |
|
|
||||||
| X86-64 | Linux |
|
|
||||||
| X86-64 | OpenBSD |
|
|
||||||
| X86-64 | Windows/MingW |
|
|
||||||
|--------------+------------------|
|
|
||||||
|
|
||||||
Please send additional platform test results to
|
|
||||||
libffi-discuss@sourceware.org and feel free to update the wiki page
|
|
||||||
above.
|
|
||||||
|
|
||||||
Installing libffi
|
|
||||||
=================
|
|
||||||
|
|
||||||
First you must configure the distribution for your particular
|
|
||||||
system. Go to the directory you wish to build libffi in and run the
|
|
||||||
"configure" program found in the root directory of the libffi source
|
|
||||||
distribution.
|
|
||||||
|
|
||||||
You may want to tell configure where to install the libffi library and
|
|
||||||
header files. To do that, use the --prefix configure switch. Libffi
|
|
||||||
will install under /usr/local by default.
|
|
||||||
|
|
||||||
If you want to enable extra run-time debugging checks use the the
|
|
||||||
--enable-debug configure switch. This is useful when your program dies
|
|
||||||
mysteriously while using libffi.
|
|
||||||
|
|
||||||
Another useful configure switch is --enable-purify-safety. Using this
|
|
||||||
will add some extra code which will suppress certain warnings when you
|
|
||||||
are using Purify with libffi. Only use this switch when using
|
|
||||||
Purify, as it will slow down the library.
|
|
||||||
|
|
||||||
It's also possible to build libffi on Windows platforms with
|
|
||||||
Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
|
|
||||||
wrapper script during configuration like so:
|
|
||||||
|
|
||||||
path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
|
|
||||||
|
|
||||||
For 64-bit Windows builds, use CC="path/to/msvcc.sh -m64".
|
|
||||||
You may also need to specify --build appropriately. When building with MSVC
|
|
||||||
under a MingW environment, you may need to remove the line in configure
|
|
||||||
that sets 'fix_srcfile_path' to a 'cygpath' command. ('cygpath' is not
|
|
||||||
present in MingW, and is not required when using MingW-style paths.)
|
|
||||||
|
|
||||||
For iOS builds, refer to the build-ios.sh script for guidance.
|
|
||||||
|
|
||||||
Configure has many other options. Use "configure --help" to see them all.
|
|
||||||
|
|
||||||
Once configure has finished, type "make". Note that you must be using
|
|
||||||
GNU make. You can ftp GNU make from prep.ai.mit.edu:/pub/gnu.
|
|
||||||
|
|
||||||
To ensure that libffi is working as advertised, type "make check".
|
|
||||||
This will require that you have DejaGNU installed.
|
|
||||||
|
|
||||||
To install the library and header files, type "make install".
|
|
||||||
|
|
||||||
|
|
||||||
History
|
|
||||||
=======
|
|
||||||
|
|
||||||
See the ChangeLog files for details.
|
|
||||||
|
|
||||||
3.0.11 MMM-DD-YY
|
|
||||||
Lots of build fixes.
|
|
||||||
Add Amiga newer MacOS support.
|
|
||||||
Add support for variadic functions (ffi_prep_cif_var).
|
|
||||||
Add Linux/x32 support.
|
|
||||||
Add thiscall, fastcall and MSVC cdecl support on Windows.
|
|
||||||
Add Amiga and newer MacOS support.
|
|
||||||
Fix Octeon and MC68881 support.
|
|
||||||
Fix code pessimizations.
|
|
||||||
Lots of build fixes.
|
|
||||||
|
|
||||||
3.0.10 Aug-23-11
|
|
||||||
Add support for Apple's iOS.
|
|
||||||
Add support for ARM VFP ABI.
|
|
||||||
Add RTEMS support for MIPS and M68K.
|
|
||||||
Fix instruction cache clearing problems on
|
|
||||||
ARM and SPARC.
|
|
||||||
Fix the N64 build on mips-sgi-irix6.5.
|
|
||||||
Enable builds with Microsoft's compiler.
|
|
||||||
Enable x86 builds with Oracle's Solaris compiler.
|
|
||||||
Fix support for calling code compiled with Oracle's Sparc
|
|
||||||
Solaris compiler.
|
|
||||||
Testsuite fixes for Tru64 Unix.
|
|
||||||
Additional platform support.
|
|
||||||
|
|
||||||
3.0.9 Dec-31-09
|
|
||||||
Add AVR32 and win64 ports. Add ARM softfp support.
|
|
||||||
Many fixes for AIX, Solaris, HP-UX, *BSD.
|
|
||||||
Several PowerPC and x86-64 bug fixes.
|
|
||||||
Build DLL for windows.
|
|
||||||
|
|
||||||
3.0.8 Dec-19-08
|
|
||||||
Add *BSD, BeOS, and PA-Linux support.
|
|
||||||
|
|
||||||
3.0.7 Nov-11-08
|
|
||||||
Fix for ppc FreeBSD.
|
|
||||||
(thanks to Andreas Tobler)
|
|
||||||
|
|
||||||
3.0.6 Jul-17-08
|
|
||||||
Fix for closures on sh.
|
|
||||||
Mark the sh/sh64 stack as non-executable.
|
|
||||||
(both thanks to Kaz Kojima)
|
|
||||||
|
|
||||||
3.0.5 Apr-3-08
|
|
||||||
Fix libffi.pc file.
|
|
||||||
Fix #define ARM for IcedTea users.
|
|
||||||
Fix x86 closure bug.
|
|
||||||
|
|
||||||
3.0.4 Feb-24-08
|
|
||||||
Fix x86 OpenBSD configury.
|
|
||||||
|
|
||||||
3.0.3 Feb-22-08
|
|
||||||
Enable x86 OpenBSD thanks to Thomas Heller, and
|
|
||||||
x86-64 FreeBSD thanks to Björn König and Andreas Tobler.
|
|
||||||
Clean up test instruction in README.
|
|
||||||
|
|
||||||
3.0.2 Feb-21-08
|
|
||||||
Improved x86 FreeBSD support.
|
|
||||||
Thanks to Björn König.
|
|
||||||
|
|
||||||
3.0.1 Feb-15-08
|
|
||||||
Fix instruction cache flushing bug on MIPS.
|
|
||||||
Thanks to David Daney.
|
|
||||||
|
|
||||||
3.0.0 Feb-15-08
|
|
||||||
Many changes, mostly thanks to the GCC project.
|
|
||||||
Cygnus Solutions is now Red Hat.
|
|
||||||
|
|
||||||
[10 years go by...]
|
|
||||||
|
|
||||||
1.20 Oct-5-98
|
|
||||||
Raffaele Sena produces ARM port.
|
|
||||||
|
|
||||||
1.19 Oct-5-98
|
|
||||||
Fixed x86 long double and long long return support.
|
|
||||||
m68k bug fixes from Andreas Schwab.
|
|
||||||
Patch for DU assembler compatibility for the Alpha from Richard
|
|
||||||
Henderson.
|
|
||||||
|
|
||||||
1.18 Apr-17-98
|
|
||||||
Bug fixes and MIPS configuration changes.
|
|
||||||
|
|
||||||
1.17 Feb-24-98
|
|
||||||
Bug fixes and m68k port from Andreas Schwab. PowerPC port from
|
|
||||||
Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes.
|
|
||||||
|
|
||||||
1.16 Feb-11-98
|
|
||||||
Richard Henderson produces Alpha port.
|
|
||||||
|
|
||||||
1.15 Dec-4-97
|
|
||||||
Fixed an n32 ABI bug. New libtool, auto* support.
|
|
||||||
|
|
||||||
1.14 May-13-97
|
|
||||||
libtool is now used to generate shared and static libraries.
|
|
||||||
Fixed a minor portability problem reported by Russ McManus
|
|
||||||
<mcmanr@eq.gs.com>.
|
|
||||||
|
|
||||||
1.13 Dec-2-96
|
|
||||||
Added --enable-purify-safety to keep Purify from complaining
|
|
||||||
about certain low level code.
|
|
||||||
Sparc fix for calling functions with < 6 args.
|
|
||||||
Linux x86 a.out fix.
|
|
||||||
|
|
||||||
1.12 Nov-22-96
|
|
||||||
Added missing ffi_type_void, needed for supporting void return
|
|
||||||
types. Fixed test case for non MIPS machines. Cygnus Support
|
|
||||||
is now Cygnus Solutions.
|
|
||||||
|
|
||||||
1.11 Oct-30-96
|
|
||||||
Added notes about GNU make.
|
|
||||||
|
|
||||||
1.10 Oct-29-96
|
|
||||||
Added configuration fix for non GNU compilers.
|
|
||||||
|
|
||||||
1.09 Oct-29-96
|
|
||||||
Added --enable-debug configure switch. Clean-ups based on LCLint
|
|
||||||
feedback. ffi_mips.h is always installed. Many configuration
|
|
||||||
fixes. Fixed ffitest.c for sparc builds.
|
|
||||||
|
|
||||||
1.08 Oct-15-96
|
|
||||||
Fixed n32 problem. Many clean-ups.
|
|
||||||
|
|
||||||
1.07 Oct-14-96
|
|
||||||
Gordon Irlam rewrites v8.S again. Bug fixes.
|
|
||||||
|
|
||||||
1.06 Oct-14-96
|
|
||||||
Gordon Irlam improved the sparc port.
|
|
||||||
|
|
||||||
1.05 Oct-14-96
|
|
||||||
Interface changes based on feedback.
|
|
||||||
|
|
||||||
1.04 Oct-11-96
|
|
||||||
Sparc port complete (modulo struct passing bug).
|
|
||||||
|
|
||||||
1.03 Oct-10-96
|
|
||||||
Passing struct args, and returning struct values works for
|
|
||||||
all architectures/calling conventions. Expanded tests.
|
|
||||||
|
|
||||||
1.02 Oct-9-96
|
|
||||||
Added SGI n32 support. Fixed bugs in both o32 and Linux support.
|
|
||||||
Added "make test".
|
|
||||||
|
|
||||||
1.01 Oct-8-96
|
|
||||||
Fixed float passing bug in mips version. Restructured some
|
|
||||||
of the code. Builds cleanly with SGI tools.
|
|
||||||
|
|
||||||
1.00 Oct-7-96
|
|
||||||
First release. No public announcement.
|
|
||||||
|
|
||||||
|
|
||||||
Authors & Credits
|
|
||||||
=================
|
|
||||||
|
|
||||||
libffi was originally written by Anthony Green <green@redhat.com>.
|
|
||||||
|
|
||||||
The developers of the GNU Compiler Collection project have made
|
|
||||||
innumerable valuable contributions. See the ChangeLog file for
|
|
||||||
details.
|
|
||||||
|
|
||||||
Some of the ideas behind libffi were inspired by Gianni Mariani's free
|
|
||||||
gencall library for Silicon Graphics machines.
|
|
||||||
|
|
||||||
The closure mechanism was designed and implemented by Kresten Krab
|
|
||||||
Thorup.
|
|
||||||
|
|
||||||
Major processor architecture ports were contributed by the following
|
|
||||||
developers:
|
|
||||||
|
|
||||||
alpha Richard Henderson
|
|
||||||
arm Raffaele Sena
|
|
||||||
cris Simon Posnjak, Hans-Peter Nilsson
|
|
||||||
frv Anthony Green
|
|
||||||
ia64 Hans Boehm
|
|
||||||
m32r Kazuhiro Inaoka
|
|
||||||
m68k Andreas Schwab
|
|
||||||
mips Anthony Green, Casey Marshall
|
|
||||||
mips64 David Daney
|
|
||||||
pa Randolph Chung, Dave Anglin, Andreas Tobler
|
|
||||||
powerpc Geoffrey Keating, Andreas Tobler,
|
|
||||||
David Edelsohn, John Hornkvist
|
|
||||||
powerpc64 Jakub Jelinek
|
|
||||||
s390 Gerhard Tonn, Ulrich Weigand
|
|
||||||
sh Kaz Kojima
|
|
||||||
sh64 Kaz Kojima
|
|
||||||
sparc Anthony Green, Gordon Irlam
|
|
||||||
x86 Anthony Green, Jon Beniston
|
|
||||||
x86-64 Bo Thorsen
|
|
||||||
|
|
||||||
Jesper Skov and Andrew Haley both did more than their fair share of
|
|
||||||
stepping through the code and tracking down bugs.
|
|
||||||
|
|
||||||
Thanks also to Tom Tromey for bug fixes, documentation and
|
|
||||||
configuration help.
|
|
||||||
|
|
||||||
Thanks to Jim Blandy, who provided some useful feedback on the libffi
|
|
||||||
interface.
|
|
||||||
|
|
||||||
Andreas Tobler has done a tremendous amount of work on the testsuite.
|
|
||||||
|
|
||||||
Alex Oliva solved the executable page problem for SElinux.
|
|
||||||
|
|
||||||
The list above is almost certainly incomplete and inaccurate. I'm
|
|
||||||
happy to make corrections or additions upon request.
|
|
||||||
|
|
||||||
If you have a problem, or have found a bug, please send a note to the
|
|
||||||
author at green@moxielogic.com, or the project mailing list at
|
|
||||||
libffi-discuss@sourceware.org.
|
|
||||||
@@ -1,289 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
ffi.c
|
|
||||||
|
|
||||||
m68k Foreign Function Interface
|
|
||||||
----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#include <ffi.h>
|
|
||||||
#include <ffi_common.h>
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#ifdef __rtems__
|
|
||||||
void rtems_cache_flush_multiple_data_lines( const void *, size_t );
|
|
||||||
#else
|
|
||||||
#include <sys/syscall.h>
|
|
||||||
#include <asm/cachectl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ffi_call_SYSV (extended_cif *,
|
|
||||||
unsigned, unsigned,
|
|
||||||
void *, void (*fn) ());
|
|
||||||
void *ffi_prep_args (void *stack, extended_cif *ecif);
|
|
||||||
void ffi_closure_SYSV (ffi_closure *);
|
|
||||||
void ffi_closure_struct_SYSV (ffi_closure *);
|
|
||||||
unsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
|
|
||||||
void *resp, void *args);
|
|
||||||
|
|
||||||
/* ffi_prep_args is called by the assembly routine once stack space has
|
|
||||||
been allocated for the function's arguments. */
|
|
||||||
|
|
||||||
void *
|
|
||||||
ffi_prep_args (void *stack, extended_cif *ecif)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
void **p_argv;
|
|
||||||
char *argp;
|
|
||||||
ffi_type **p_arg;
|
|
||||||
void *struct_value_ptr;
|
|
||||||
|
|
||||||
argp = stack;
|
|
||||||
|
|
||||||
if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
|
|
||||||
&& !ecif->cif->flags)
|
|
||||||
struct_value_ptr = ecif->rvalue;
|
|
||||||
else
|
|
||||||
struct_value_ptr = NULL;
|
|
||||||
|
|
||||||
p_argv = ecif->avalue;
|
|
||||||
|
|
||||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
|
||||||
i != 0;
|
|
||||||
i--, p_arg++)
|
|
||||||
{
|
|
||||||
size_t z;
|
|
||||||
|
|
||||||
z = (*p_arg)->size;
|
|
||||||
if (z < sizeof (int))
|
|
||||||
{
|
|
||||||
switch ((*p_arg)->type)
|
|
||||||
{
|
|
||||||
case FFI_TYPE_SINT8:
|
|
||||||
*(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_UINT8:
|
|
||||||
*(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_SINT16:
|
|
||||||
*(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_UINT16:
|
|
||||||
*(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
|
||||||
memcpy (argp + sizeof (int) - z, *p_argv, z);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
FFI_ASSERT (0);
|
|
||||||
}
|
|
||||||
z = sizeof (int);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memcpy (argp, *p_argv, z);
|
|
||||||
|
|
||||||
/* Align if necessary. */
|
|
||||||
if ((sizeof(int) - 1) & z)
|
|
||||||
z = ALIGN(z, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
p_argv++;
|
|
||||||
argp += z;
|
|
||||||
}
|
|
||||||
|
|
||||||
return struct_value_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CIF_FLAGS_INT 1
|
|
||||||
#define CIF_FLAGS_DINT 2
|
|
||||||
#define CIF_FLAGS_FLOAT 4
|
|
||||||
#define CIF_FLAGS_DOUBLE 8
|
|
||||||
#define CIF_FLAGS_LDOUBLE 16
|
|
||||||
#define CIF_FLAGS_POINTER 32
|
|
||||||
#define CIF_FLAGS_STRUCT1 64
|
|
||||||
#define CIF_FLAGS_STRUCT2 128
|
|
||||||
|
|
||||||
/* Perform machine dependent cif processing */
|
|
||||||
ffi_status
|
|
||||||
ffi_prep_cif_machdep (ffi_cif *cif)
|
|
||||||
{
|
|
||||||
/* Set the return type flag */
|
|
||||||
switch (cif->rtype->type)
|
|
||||||
{
|
|
||||||
case FFI_TYPE_VOID:
|
|
||||||
cif->flags = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_STRUCT:
|
|
||||||
switch (cif->rtype->size)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
cif->flags = CIF_FLAGS_STRUCT1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
cif->flags = CIF_FLAGS_STRUCT2;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
cif->flags = CIF_FLAGS_INT;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
cif->flags = CIF_FLAGS_DINT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cif->flags = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_FLOAT:
|
|
||||||
cif->flags = CIF_FLAGS_FLOAT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_DOUBLE:
|
|
||||||
cif->flags = CIF_FLAGS_DOUBLE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if (FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE)
|
|
||||||
case FFI_TYPE_LONGDOUBLE:
|
|
||||||
cif->flags = CIF_FLAGS_LDOUBLE;
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case FFI_TYPE_POINTER:
|
|
||||||
cif->flags = CIF_FLAGS_POINTER;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FFI_TYPE_SINT64:
|
|
||||||
case FFI_TYPE_UINT64:
|
|
||||||
cif->flags = CIF_FLAGS_DINT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
cif->flags = CIF_FLAGS_INT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FFI_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ffi_call (ffi_cif *cif, void (*fn) (), 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. */
|
|
||||||
|
|
||||||
if (rvalue == NULL
|
|
||||||
&& cif->rtype->type == FFI_TYPE_STRUCT
|
|
||||||
&& cif->rtype->size > 8)
|
|
||||||
ecif.rvalue = alloca (cif->rtype->size);
|
|
||||||
else
|
|
||||||
ecif.rvalue = rvalue;
|
|
||||||
|
|
||||||
switch (cif->abi)
|
|
||||||
{
|
|
||||||
case FFI_SYSV:
|
|
||||||
ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
|
|
||||||
ecif.rvalue, fn);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
FFI_ASSERT (0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
void **p_argv;
|
|
||||||
char *argp;
|
|
||||||
ffi_type **p_arg;
|
|
||||||
|
|
||||||
argp = stack;
|
|
||||||
p_argv = avalue;
|
|
||||||
|
|
||||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
|
||||||
{
|
|
||||||
size_t z;
|
|
||||||
|
|
||||||
z = (*p_arg)->size;
|
|
||||||
if (z <= 4)
|
|
||||||
{
|
|
||||||
*p_argv = (void *) (argp + 4 - z);
|
|
||||||
|
|
||||||
z = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*p_argv = (void *) argp;
|
|
||||||
|
|
||||||
/* Align if necessary */
|
|
||||||
if ((sizeof(int) - 1) & z)
|
|
||||||
z = ALIGN(z, sizeof(int));
|
|
||||||
}
|
|
||||||
|
|
||||||
p_argv++;
|
|
||||||
argp += z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
ffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
|
|
||||||
{
|
|
||||||
ffi_cif *cif;
|
|
||||||
void **arg_area;
|
|
||||||
|
|
||||||
cif = closure->cif;
|
|
||||||
arg_area = (void**) alloca (cif->nargs * sizeof (void *));
|
|
||||||
|
|
||||||
ffi_prep_incoming_args_SYSV(args, arg_area, cif);
|
|
||||||
|
|
||||||
(closure->fun) (cif, resp, arg_area, closure->user_data);
|
|
||||||
|
|
||||||
return cif->flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
ffi_status
|
|
||||||
ffi_prep_closure_loc (ffi_closure* closure,
|
|
||||||
ffi_cif* cif,
|
|
||||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
|
||||||
void *user_data,
|
|
||||||
void *codeloc)
|
|
||||||
{
|
|
||||||
if (cif->abi != FFI_SYSV)
|
|
||||||
return FFI_BAD_ABI;
|
|
||||||
|
|
||||||
*(unsigned short *)closure->tramp = 0x207c;
|
|
||||||
*(void **)(closure->tramp + 2) = codeloc;
|
|
||||||
*(unsigned short *)(closure->tramp + 6) = 0x4ef9;
|
|
||||||
if (cif->rtype->type == FFI_TYPE_STRUCT
|
|
||||||
&& !cif->flags)
|
|
||||||
*(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
|
|
||||||
else
|
|
||||||
*(void **)(closure->tramp + 8) = ffi_closure_SYSV;
|
|
||||||
|
|
||||||
#ifdef __rtems__
|
|
||||||
rtems_cache_flush_multiple_data_lines( codeloc, FFI_TRAMPOLINE_SIZE );
|
|
||||||
#else
|
|
||||||
syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
|
|
||||||
FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
closure->cif = cif;
|
|
||||||
closure->user_data = user_data;
|
|
||||||
closure->fun = fun;
|
|
||||||
|
|
||||||
return FFI_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,270 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
sysv.S - Copyright (c) 1998, 2012 Andreas Schwab
|
|
||||||
Copyright (c) 2008 Red Hat, Inc.
|
|
||||||
|
|
||||||
m68k 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.
|
|
||||||
----------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#define LIBFFI_ASM
|
|
||||||
#include <fficonfig.h>
|
|
||||||
#include <ffi.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_AS_CFI_PSEUDO_OP
|
|
||||||
#define CFI_STARTPROC() .cfi_startproc
|
|
||||||
#define CFI_OFFSET(reg,off) .cfi_offset reg,off
|
|
||||||
#define CFI_DEF_CFA(reg,off) .cfi_def_cfa reg,off
|
|
||||||
#define CFI_ENDPROC() .cfi_endproc
|
|
||||||
#else
|
|
||||||
#define CFI_STARTPROC()
|
|
||||||
#define CFI_OFFSET(reg,off)
|
|
||||||
#define CFI_DEF_CFA(reg,off)
|
|
||||||
#define CFI_ENDPROC()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.text
|
|
||||||
|
|
||||||
.globl ffi_call_SYSV
|
|
||||||
.type ffi_call_SYSV,@function
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
ffi_call_SYSV:
|
|
||||||
CFI_STARTPROC()
|
|
||||||
link %fp,#0
|
|
||||||
CFI_OFFSET(14,-8)
|
|
||||||
CFI_DEF_CFA(14,8)
|
|
||||||
move.l %d2,-(%sp)
|
|
||||||
CFI_OFFSET(2,-12)
|
|
||||||
|
|
||||||
| Make room for all of the new args.
|
|
||||||
sub.l 12(%fp),%sp
|
|
||||||
|
|
||||||
| Call ffi_prep_args
|
|
||||||
move.l 8(%fp),-(%sp)
|
|
||||||
pea 4(%sp)
|
|
||||||
#if !defined __PIC__
|
|
||||||
jsr ffi_prep_args
|
|
||||||
#else
|
|
||||||
bsr.l ffi_prep_args@PLTPC
|
|
||||||
#endif
|
|
||||||
addq.l #8,%sp
|
|
||||||
|
|
||||||
| Pass pointer to struct value, if any
|
|
||||||
move.l %a0,%a1
|
|
||||||
|
|
||||||
| Call the function
|
|
||||||
move.l 24(%fp),%a0
|
|
||||||
jsr (%a0)
|
|
||||||
|
|
||||||
| Remove the space we pushed for the args
|
|
||||||
add.l 12(%fp),%sp
|
|
||||||
|
|
||||||
| Load the pointer to storage for the return value
|
|
||||||
move.l 20(%fp),%a1
|
|
||||||
|
|
||||||
| Load the return type code
|
|
||||||
move.l 16(%fp),%d2
|
|
||||||
|
|
||||||
| If the return value pointer is NULL, assume no return value.
|
|
||||||
| NOTE: On the mc68000, tst on an address register is not supported.
|
|
||||||
#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
|
|
||||||
cmp.w #0, %a1
|
|
||||||
#else
|
|
||||||
tst.l %a1
|
|
||||||
#endif
|
|
||||||
jbeq noretval
|
|
||||||
|
|
||||||
btst #0,%d2
|
|
||||||
jbeq retlongint
|
|
||||||
move.l %d0,(%a1)
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retlongint:
|
|
||||||
btst #1,%d2
|
|
||||||
jbeq retfloat
|
|
||||||
move.l %d0,(%a1)
|
|
||||||
move.l %d1,4(%a1)
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retfloat:
|
|
||||||
btst #2,%d2
|
|
||||||
jbeq retdouble
|
|
||||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
|
||||||
fmove.s %fp0,(%a1)
|
|
||||||
#else
|
|
||||||
move.l %d0,(%a1)
|
|
||||||
#endif
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retdouble:
|
|
||||||
btst #3,%d2
|
|
||||||
jbeq retlongdouble
|
|
||||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
|
||||||
fmove.d %fp0,(%a1)
|
|
||||||
#else
|
|
||||||
move.l %d0,(%a1)+
|
|
||||||
move.l %d1,(%a1)
|
|
||||||
#endif
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retlongdouble:
|
|
||||||
btst #4,%d2
|
|
||||||
jbeq retpointer
|
|
||||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
|
||||||
fmove.x %fp0,(%a1)
|
|
||||||
#else
|
|
||||||
move.l %d0,(%a1)+
|
|
||||||
move.l %d1,(%a1)+
|
|
||||||
move.l %d2,(%a1)
|
|
||||||
#endif
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retpointer:
|
|
||||||
btst #5,%d2
|
|
||||||
jbeq retstruct1
|
|
||||||
move.l %a0,(%a1)
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retstruct1:
|
|
||||||
btst #6,%d2
|
|
||||||
jbeq retstruct2
|
|
||||||
move.b %d0,(%a1)
|
|
||||||
jbra epilogue
|
|
||||||
|
|
||||||
retstruct2:
|
|
||||||
btst #7,%d2
|
|
||||||
jbeq noretval
|
|
||||||
move.w %d0,(%a1)
|
|
||||||
|
|
||||||
noretval:
|
|
||||||
epilogue:
|
|
||||||
move.l (%sp)+,%d2
|
|
||||||
unlk %fp
|
|
||||||
rts
|
|
||||||
CFI_ENDPROC()
|
|
||||||
.size ffi_call_SYSV,.-ffi_call_SYSV
|
|
||||||
|
|
||||||
.globl ffi_closure_SYSV
|
|
||||||
.type ffi_closure_SYSV, @function
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
ffi_closure_SYSV:
|
|
||||||
CFI_STARTPROC()
|
|
||||||
link %fp,#-12
|
|
||||||
CFI_OFFSET(14,-8)
|
|
||||||
CFI_DEF_CFA(14,8)
|
|
||||||
move.l %sp,-12(%fp)
|
|
||||||
pea 8(%fp)
|
|
||||||
pea -12(%fp)
|
|
||||||
move.l %a0,-(%sp)
|
|
||||||
#if !defined __PIC__
|
|
||||||
jsr ffi_closure_SYSV_inner
|
|
||||||
#else
|
|
||||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lsr.l #1,%d0
|
|
||||||
jne 1f
|
|
||||||
jcc .Lcls_epilogue
|
|
||||||
move.l -12(%fp),%d0
|
|
||||||
.Lcls_epilogue:
|
|
||||||
unlk %fp
|
|
||||||
rts
|
|
||||||
1:
|
|
||||||
lea -12(%fp),%a0
|
|
||||||
lsr.l #2,%d0
|
|
||||||
jne 1f
|
|
||||||
jcs .Lcls_ret_float
|
|
||||||
move.l (%a0)+,%d0
|
|
||||||
move.l (%a0),%d1
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
.Lcls_ret_float:
|
|
||||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
|
||||||
fmove.s (%a0),%fp0
|
|
||||||
#else
|
|
||||||
move.l (%a0),%d0
|
|
||||||
#endif
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
1:
|
|
||||||
lsr.l #2,%d0
|
|
||||||
jne 1f
|
|
||||||
jcs .Lcls_ret_ldouble
|
|
||||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
|
||||||
fmove.d (%a0),%fp0
|
|
||||||
#else
|
|
||||||
move.l (%a0)+,%d0
|
|
||||||
move.l (%a0),%d1
|
|
||||||
#endif
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
.Lcls_ret_ldouble:
|
|
||||||
#if defined(__MC68881__) || defined(__HAVE_68881__)
|
|
||||||
fmove.x (%a0),%fp0
|
|
||||||
#else
|
|
||||||
move.l (%a0)+,%d0
|
|
||||||
move.l (%a0)+,%d1
|
|
||||||
move.l (%a0),%d2
|
|
||||||
#endif
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
1:
|
|
||||||
lsr.l #2,%d0
|
|
||||||
jne .Lcls_ret_struct2
|
|
||||||
jcs .Lcls_ret_struct1
|
|
||||||
move.l (%a0),%a0
|
|
||||||
move.l %a0,%d0
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
.Lcls_ret_struct1:
|
|
||||||
move.b (%a0),%d0
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
.Lcls_ret_struct2:
|
|
||||||
move.w (%a0),%d0
|
|
||||||
jra .Lcls_epilogue
|
|
||||||
CFI_ENDPROC()
|
|
||||||
|
|
||||||
.size ffi_closure_SYSV,.-ffi_closure_SYSV
|
|
||||||
|
|
||||||
.globl ffi_closure_struct_SYSV
|
|
||||||
.type ffi_closure_struct_SYSV, @function
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
ffi_closure_struct_SYSV:
|
|
||||||
CFI_STARTPROC()
|
|
||||||
link %fp,#0
|
|
||||||
CFI_OFFSET(14,-8)
|
|
||||||
CFI_DEF_CFA(14,8)
|
|
||||||
move.l %sp,-12(%fp)
|
|
||||||
pea 8(%fp)
|
|
||||||
move.l %a1,-(%sp)
|
|
||||||
move.l %a0,-(%sp)
|
|
||||||
#if !defined __PIC__
|
|
||||||
jsr ffi_closure_SYSV_inner
|
|
||||||
#else
|
|
||||||
bsr.l ffi_closure_SYSV_inner@PLTPC
|
|
||||||
#endif
|
|
||||||
unlk %fp
|
|
||||||
rts
|
|
||||||
CFI_ENDPROC()
|
|
||||||
.size ffi_closure_struct_SYSV,.-ffi_closure_struct_SYSV
|
|
||||||
|
|
||||||
#if defined __ELF__ && defined __linux__
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
||||||
#endif
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,203 +0,0 @@
|
|||||||
## 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:
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,443 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------*-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
|
|
||||||
@@ -1,826 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------------
|
|
||||||
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 */
|
|
||||||
|
|
||||||
@@ -1,135 +0,0 @@
|
|||||||
/* -----------------------------------------------------------------*-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 __ILP32__
|
|
||||||
#define FFI_SIZEOF_ARG 8
|
|
||||||
#define FFI_SIZEOF_JAVA_RAW 4
|
|
||||||
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
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,64 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
/* 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);
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user