Merge upstream libffi

From-SVN: r184897
This commit is contained in:
Anthony Green 2012-03-04 21:11:09 +00:00
parent 8b59af5c6a
commit 34fa7690ac
63 changed files with 6319 additions and 636 deletions

View File

@ -1,37 +1,36 @@
2012-02-27 Mikael Pettersson <mikpe@it.uu.se>
2012-03-03 H.J. Lu <hongjiu.lu@intel.com>
PR libffi/52223
* Makefile.am (FLAGS_TO_PASS): Define.
* Makefile.in: Regenerate.
* src/x86/ffi64.c (ffi_call): Cast the return value to unsigned
long.
(ffi_prep_closure_loc): Cast to 64bit address in trampoline.
(ffi_closure_unix64_inner): Cast return pointer to unsigned long
first.
2012-02-23 Kai Tietz <ktietz@redhat.com>
* src/x86/ffitarget.h (FFI_SIZEOF_ARG): Defined to 8 for x32.
(ffi_arg): Set to unsigned long long for x32.
(ffi_sarg): Set to long long for x32.
PR libffi/52221
* src/x86/ffi.c (ffi_closure_raw_THISCALL): New
prototype.
(ffi_prep_raw_closure_loc): Use ffi_closure_raw_THISCALL for
thiscall-convention.
(ffi_raw_call): Use ffi_prep_args_raw.
* src/x86/win32.S (ffi_closure_raw_THISCALL): Add
implementation for stub.
2012-03-03 H.J. Lu <hongjiu.lu@intel.com>
2012-02-13 Kai Tietz <ktietz@redhat.com>
* src/prep_cif.c (ffi_prep_cif_core): Properly check bad ABI.
PR libffi/52221
* src/x86/ffi.c (ffi_prep_raw_closure_loc): Add thiscall
support for X86_WIN32.
(FFI_INIT_TRAMPOLINE_THISCALL): Fix displacement.
2012-03-03 Andoni Morales Alastruey <ylatuya@gmail.com>
2012-02-11 Eric Botcazou <ebotcazou@adacore.com>
* configure.ac: Add -no-undefined for both 32- and 64-bit x86
windows-like hosts.
* configure: Rebuilt.
* src/sparc/v9.S (STACKFRAME): Bump to 176.
2012-02-23 Anthony Green <green@moxielogic.com>
* src/*/ffitarget.h: Ensure that users never include ffitarget.h
directly.
2012-02-10 Kai Tietz <ktietz@redhat.com>
* configure.ac (AM_LTLDFLAGS): Add -no-undefine for x64
windows target.
* configure: Regenerated.
2012-02-08 Kai Tietz <ktietz@redhat.com>
* src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32
@ -63,6 +62,20 @@
* testsuite/libffi.call/struct1_win32.c: New test.
* testsuite/libffi.call/struct2_win32.c: New test.
2012-01-23 Uros Bizjak <ubizjak@gmail.com>
* src/alpha/ffi.c (ffi_prep_closure_loc): Check for bad ABI.
2012-01-23 Anthony Green <green@moxielogic.com>
Chris Young <cdyoung@ntlworld.com>
* configure.ac: Add Amiga support.
* configure: Rebuilt.
2012-01-23 Dmitry Nadezhin <dmitry.nadezhin@gmail.com>
* include/ffi_common.h (LIKELY, UNLIKELY): Fix definitions.
2012-01-23 Andreas Schwab <schwab@linux-m68k.org>
* src/m68k/sysv.S (ffi_call_SYSV): Properly test for plain
@ -87,6 +100,67 @@
* configure: Regenerate.
2011-11-12 David Gilbert <david.gilbert@linaro.org>
* doc/libffi.texi, include/ffi.h.in, include/ffi_common.h,
man/Makefile.am, man/ffi.3, man/ffi_prep_cif.3,
man/ffi_prep_cif_var.3, src/arm/ffi.c, src/arm/ffitarget.h,
src/cris/ffi.c, src/prep_cif.c,
testsuite/libffi.call/cls_double_va.c,
testsuite/libffi.call/cls_longdouble_va.c,
testsuite/libffi.call/float_va.c: Many changes to support variadic
function calls.
2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com>
* src/powerpc/ffi.c, src/powerpc/ffitarget.h,
src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for
softfloat powerpc variants.
2011-11-12 Petr Salinger <Petr.Salinger@seznam.cz>
* configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support.
* configure: Rebuilt.
2011-11-12 Timothy Wall <twall@users.sf.net>
* src/arm/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): Max
alignment of 4 for wince on ARM.
2011-11-12 Kyle Moffett <Kyle.D.Moffett@boeing.com>
Anthony Green <green@moxielogic.com>
* src/ppc/sysv.S, src/ppc/ffi.c: Remove use of ppc string
instructions (not available on some cores, like the PPC440).
2011-11-12 Kimura Wataru <kimuraw@i.nifty.jp>
* m4/ax_enable_builddir: Change from string comparison to numeric
comparison for wc output.
* configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS
X 10.7.
* configure: Rebuilt.
2011-11-12 Anthony Green <green@moxielogic.com>
* Makefile.am (AM_CCASFLAGS): Add -g option to build assembly
files with debug info.
* Makefile.in: Rebuilt.
2011-11-12 Jasper Lievisse Adriaanse <jasper@openbsd.org>
* README: Update list of supported OpenBSD systems.
2011-11-12 Anthony Green <green@moxielogic.com>
* libtool-version: Update.
* Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if
FFI_DEBUG.
(libffi_la_SOURCES): Remove src/debug.c
(EXTRA_DIST): Add src/debug.c
* Makefile.in: Rebuilt.
* README: Update for 3.0.11.
2011-11-10 Richard Henderson <rth@redhat.com>
* configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check.
@ -135,10 +209,127 @@
Use them to handle ELF vs. ECOFF differences.
[__osf__] (_GLOBAL__F_ffi_call_osf): Define.
2011-03-30 Timothy Wall <twall@users.sf.net>
* src/powerpc/darwin.S: Fix unknown FDE encoding.
* src/powerpc/darwin_closure.S: ditto.
2011-02-25 Anthony Green <green@moxielogic.com>
* src/powerpc/ffi.c (ffi_prep_closure_loc): Allow for more
32-bit ABIs.
2011-02-15 Anthony Green <green@moxielogic.com>
* m4/ax_cc_maxopt.m4: Don't -malign-double or use -ffast-math.
* configure: Rebuilt.
2011-02-13 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure: Regenerate.
2011-02-13 Anthony Green <green@moxielogic.com>
* include/ffi_common.h (UNLIKELY, LIKELY): Define.
* src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition.
* src/prep_cif.c (UNLIKELY, LIKELY): Remove definition.
* src/prep_cif.c (initialize_aggregate): Convert assertion into
FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0.
* src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
just return FFI_BAD_ABI when things are wrong.
* src/arm/ffi.c (ffi_prep_closure_loc): Ditto.
* src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto.
* src/mips/ffi.c (ffi_prep_closure_loc): Ditto.
* src/ia64/ffi.c (ffi_prep_closure_loc): Ditto.
* src/avr32/ffi.c (ffi_prep_closure_loc): Ditto.
2011-02-11 Anthony Green <green@moxielogic.com>
* src/sparc/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test,
just return FFI_BAD_ABI when things are wrong.
2011-02-09 Stuart Shelton <srcshelton@gmail.com>
http://bugs.gentoo.org/show_bug.cgi?id=286911
* src/mips/ffitarget.h: Clean up error messages.
* src/java_raw_api.c (ffi_java_translate_args): Cast raw arg to
ffi_raw*.
* include/ffi.h.in: Add pragma for SGI compiler.
2011-02-09 Anthony Green <green@moxielogic.com>
* configure.ac: Add powerpc64-*-darwin* support.
2011-02-09 Anthony Green <green@moxielogic.com>
* README: Mention Interix.
2011-02-09 Jonathan Callen <abcd@gentoo.org>
* configure.ac: Add Interix to win32/cygwin/mingw case.
* configure: Ditto.
* src/closures.c: Treat Interix like Cygwin, instead of as a
generic win32.
2011-02-09 Anthony Green <green@moxielogic.com>
* testsuite/libffi.call/err_bad_typedef.c: Remove xfail.
* testsuite/libffi.call/err_bad_abi.c: Remove xfail.
* src/x86/ffi64.c (UNLIKELY, LIKELY): Define.
(ffi_prep_closure_loc): Check for bad ABI.
* src/prep_cif.c (UNLIKELY, LIKELY): Define.
(initialize_aggregate): Check for bad types.
2011-02-09 Landon Fuller <landonf@plausible.coop>
* Makefile.am (EXTRA_DIST): Add build-ios.sh, src/arm/gentramp.sh,
src/arm/trampoline.S.
(nodist_libffi_la_SOURCES): Add src/arc/trampoline.S.
* configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Define.
* src/arm/ffi.c (ffi_trampoline_table)
(ffi_closure_trampoline_table_page, ffi_trampoline_table_entry)
(FFI_TRAMPOLINE_CODELOC_CONFIG, FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET)
(FFI_TRAMPOLINE_COUNT, ffi_trampoline_lock, ffi_trampoline_tables)
(ffi_trampoline_table_alloc, ffi_closure_alloc, ffi_closure_free):
Define for FFI_EXEC_TRAMPOLINE_TABLE case (iOS).
(ffi_prep_closure_loc): Handl FFI_EXEC_TRAMPOLINE_TABLE case
separately.
* src/arm/sysv.S: Handle Apple iOS host.
* src/closures.c: Handle FFI_EXEC_TRAMPOLINE_TABLE case.
* build-ios.sh: New file.
* fficonfig.h.in, configure, Makefile.in: Rebuilt.
* README: Mention ARM iOS.
2011-02-08 Oren Held <orenhe@il.ibm.com>
* src/dlmalloc.c (_STRUCT_MALLINFO): Define in order to avoid
redefinition of mallinfo on HP-UX.
2011-02-08 Ginn Chen <ginn.chen@oracle.com>
* src/sparc/ffi.c (ffi_call): Make compatible with Solaris Studio
aggregate return ABI. Flush cache.
(ffi_prep_closure_loc): Flush cache.
2011-02-11 Anthony Green <green@moxielogic.com>
From Tom Honermann <tom.honermann@oracle.com>:
* src/powerpc/aix.S (ffi_call_AIX): Support for xlc toolchain on
AIX. Declare .ffi_prep_args. Insert nops after branch
instructions so that the AIX linker can insert TOC reload
instructions.
* src/powerpc/aix_closure.S: Declare .ffi_closure_helper_DARWIN.
2011-02-08 Ed <ed@kdtc.net>
* src/powerpc/asm.h: Fix grammar nit in comment.
2011-02-08 Uli Link <ul.mcamafia@linkitup.de>
* include/ffi.h.in (FFI_64_BIT_MAX): Define and use.
2011-02-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR libffi/46661
@ -146,6 +337,11 @@
uintptr_t first.
* testsuite/libffi.call/cls_pointer_stack.c (main): Likewise.
2011-02-08 Rafael Avila de Espindola <respindola@mozilla.com>
* configure.ac: Fix x86 test for pc related relocs.
* configure: Rebuilt.
2011-02-07 Joel Sherrill <joel.sherrill@oarcorp.com>
* libffi/src/m68k/ffi.c: Add RTEMS support for cache flushing.
@ -204,6 +400,13 @@
(.eh_frame): Use FDE_ENCODING.
(.LASFDE1, .LASFDE2, LASFDE3): Simplify with FDE_ENCODE.
2010-11-22 Jacek Caban <jacek@codeweavers.com>
* configure.ac: Check for symbol underscores on mingw-w64.
* configure: Rebuilt.
* src/x86/win64.S: Correctly access extern symbols in respect to
underscores.
2010-11-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* testsuite/lib/libffi-dg.exp: Rename ...
@ -271,6 +474,31 @@
* testsuite/libffi.call/cls_longdouble.c: Likewise.
* testsuite/libffi.call/huge_struct.c: Likewise.
2010-08-05 Dan Witte <dwitte@mozilla.com>
* Makefile.am: Pass FFI_DEBUG define to msvcc.sh for linking to the
debug CRT when --enable-debug is given.
* configure.ac: Define it.
* msvcc.sh: Translate -g and -DFFI_DEBUG appropriately.
2010-08-04 Dan Witte <dwitte@mozilla.com>
* src/x86/ffitarget.h: Add X86_ANY define for all x86/x86_64
platforms.
* src/x86/ffi.c: Remove redundant ifdef checks.
* src/prep_cif.c: Push stack space computation into src/x86/ffi.c
for X86_ANY so return value space doesn't get added twice.
2010-08-03 Neil Rashbrooke <neil@parkwaycc.co.uk>
* msvcc.sh: Don't pass -safeseh to ml64 because behavior is buggy.
2010-07-22 Dan Witte <dwitte@mozilla.com>
* src/*/ffitarget.h: Make FFI_LAST_ABI one past the last valid ABI.
* src/prep_cif.c: Fix ABI assertion.
* src/cris/ffi.c: Ditto.
2010-07-10 Evan Phoenix <evan@fallingsnow.net>
* src/closures.c (selinux_enabled_check): Fix strncmp usage bug.
@ -302,6 +530,14 @@
* fficonfig.h.in: Regenerate.
* src/x86/sysv.S (.eh_frame): Use .ascii, .string or error.
2010-05-11 Dan Witte <dwitte@mozilla.com>
* doc/libffi.tex: Document previous change.
2010-05-11 Makoto Kato <m_kato@ga2.so-net.ne.jp>
* src/x86/ffi.c (ffi_call): Don't copy structs passed by value.
2010-05-05 Michael Kohler <michaelkohler@live.com>
* src/dlmalloc.c (dlfree): Fix spelling.
@ -337,6 +573,11 @@
* man/Makefile.in: Regenerate.
* testsuite/Makefile.in: Regenerate.
2010-03-30 Dan Witte <dwitte@mozilla.com>
* msvcc.sh: Disable build warnings.
* README (tested): Clarify windows build procedure.
2010-03-15 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac (libffi_cv_as_x86_64_unwind_section_type): New test.
@ -711,6 +952,11 @@
* man/Makefile.in: Regenerate.
* testsuite/Makefile.in: Regenerate.
2011-08-22 Jasper Lievisse Adriaanse <jasper@openbsd.org>
* configure.ac: Add OpenBSD/hppa and OpenBSD/powerpc support.
* configure: Rebuilt.
2009-07-30 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure.ac (_AC_ARG_VAR_PRECIOUS): Use m4_rename_force.

View File

@ -1,4 +1,5 @@
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
libffi - Copyright (c) 1996-2012 Anthony Green, Red Hat, Inc and others.
See source files for details.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -8,13 +9,13 @@ 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 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
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 CYGNUS SOLUTIONS 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.
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.

View File

@ -1,10 +1,7 @@
This directory contains the libffi package, which is not part of GCC but
shipped with GCC as convenience.
Status
======
libffi-3.0.9 was released on December 31, 2009. Check the libffi web
libffi-3.0.11 was released on *****************. Check the libffi web
page for updates: <URL:http://sourceware.org/libffi/>.
@ -46,7 +43,7 @@ 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.9
http://www.moxielogic.org/wiki/index.php?title=Libffi_3.0.11
At the time of release, the following basic configurations have been
tested:
@ -55,13 +52,18 @@ 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 |
@ -73,8 +75,10 @@ tested:
| SPARC64 | Linux |
| SPARC64 | FreeBSD |
| X86 | FreeBSD |
| X86 | Interix |
| X86 | kFreeBSD |
| X86 | Linux |
| X86 | Linux/x32 |
| X86 | Mac OSX |
| X86 | OpenBSD |
| X86 | OS/2 |
@ -84,6 +88,7 @@ tested:
| X86-64 | FreeBSD |
| X86-64 | Linux |
| X86-64 | OpenBSD |
| X86-64 | Windows/MingW |
|--------------+------------------|
Please send additional platform test results to
@ -115,9 +120,15 @@ 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 --enable-shared --enable-static \
CC=path/to/msvcc.sh LD=link \
CPP=\"cl -nologo -EP\"
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.
@ -135,11 +146,27 @@ History
See the ChangeLog files for details.
3.0.10 ???-??-??
3.0.11 MMM-DD-YY
Lots of build fixes.
Add Amiga newer MacOS support.
Add Linux/x32 support.
Add thiscall and fastcall support on Windows.
Fix Octeon and MC68881 support.
Fix code pessimizations.
3.0.10 Aug-23-11
Add support for Apple's iOS.
Add support for ARM VFP ABI.
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.
Testsuite fixes for Tru64 Unix.
Enable builds with Microsoft's compiler.
Enable x86 builds with Sun'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.
@ -320,5 +347,6 @@ 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
green@redhat.com.
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.

67
libffi/build-ios.sh Executable file
View File

@ -0,0 +1,67 @@
#!/bin/sh
PLATFORM_IOS=/Developer/Platforms/iPhoneOS.platform/
PLATFORM_IOS_SIM=/Developer/Platforms/iPhoneSimulator.platform/
SDK_IOS_VERSION="4.2"
MIN_IOS_VERSION="3.0"
OUTPUT_DIR="universal-ios"
build_target () {
local platform=$1
local sdk=$2
local arch=$3
local triple=$4
local builddir=$5
mkdir -p "${builddir}"
pushd "${builddir}"
export CC="${platform}"/Developer/usr/bin/gcc-4.2
export CFLAGS="-arch ${arch} -isysroot ${sdk} -miphoneos-version-min=${MIN_IOS_VERSION}"
../configure --host=${triple} && make
popd
}
# Build all targets
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv6 arm-apple-darwin10 armv6-ios
build_target "${PLATFORM_IOS}" "${PLATFORM_IOS}/Developer/SDKs/iPhoneOS${SDK_IOS_VERSION}.sdk/" armv7 arm-apple-darwin10 armv7-ios
build_target "${PLATFORM_IOS_SIM}" "${PLATFORM_IOS_SIM}/Developer/SDKs/iPhoneSimulator${SDK_IOS_VERSION}.sdk/" i386 i386-apple-darwin10 i386-ios-sim
# Create universal output directories
mkdir -p "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}/include"
mkdir -p "${OUTPUT_DIR}/include/armv6"
mkdir -p "${OUTPUT_DIR}/include/armv7"
mkdir -p "${OUTPUT_DIR}/include/i386"
# Create the universal binary
lipo -create armv6-ios/.libs/libffi.a armv7-ios/.libs/libffi.a i386-ios-sim/.libs/libffi.a -output "${OUTPUT_DIR}/libffi.a"
# Copy in the headers
copy_headers () {
local src=$1
local dest=$2
# Fix non-relative header reference
sed 's/<ffitarget.h>/"ffitarget.h"/' < "${src}/include/ffi.h" > "${dest}/ffi.h"
cp "${src}/include/ffitarget.h" "${dest}"
}
copy_headers armv6-ios "${OUTPUT_DIR}/include/armv6"
copy_headers armv7-ios "${OUTPUT_DIR}/include/armv7"
copy_headers i386-ios-sim "${OUTPUT_DIR}/include/i386"
# Create top-level header
(
cat << EOF
#ifdef __arm__
#include <arm/arch.h>
#ifdef _ARM_ARCH_6
#include "include/armv6/ffi.h"
#elif _ARM_ARCH_7
#include "include/armv7/ffi.h"
#endif
#elif defined(__i386__)
#include "include/i386/ffi.h"
#endif
EOF
) > "${OUTPUT_DIR}/ffi.h"

View File

@ -19,7 +19,7 @@
This manual is for Libffi, a portable foreign-function interface
library.
Copyright @copyright{} 2008, 2010 Red Hat, Inc.
Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
@ -133,8 +133,6 @@ This initializes @var{cif} according to the given parameters.
you want. @ref{Multiple ABIs} for more information.
@var{nargs} is the number of arguments that this function accepts.
@samp{libffi} does not yet handle varargs functions; see @ref{Missing
Features} for more information.
@var{rtype} is a pointer to an @code{ffi_type} structure that
describes the return type of the function. @xref{Types}.
@ -150,6 +148,30 @@ objects is incorrect; or @code{FFI_BAD_ABI} if the @var{abi} parameter
is invalid.
@end defun
If the function being called is variadic (varargs) then
@code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}.
@findex ffi_prep_cif_var
@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes})
This initializes @var{cif} according to the given parameters for
a call to a variadic function. In general it's operation is the
same as for @code{ffi_prep_cif} except that:
@var{nfixedargs} is the number of fixed arguments, prior to any
variadic arguments. It must be greater than zero.
@var{ntotalargs} the total number of arguments, including variadic
and fixed arguments.
Note that, different cif's must be prepped for calls to the same
function when different numbers of arguments are passed.
Also note that a call to @code{ffi_prep_cif_var} with
@var{nfixedargs}=@var{nototalargs} is NOT equivalent to a call to
@code{ffi_prep_cif}.
@end defun
To call a function using an initialized @code{ffi_cif}, use the
@code{ffi_call} function:
@ -171,7 +193,9 @@ discarded.
@var{avalues} is a vector of @code{void *} pointers that point to the
memory locations holding the argument values for a call. If @var{cif}
declares that the function has no arguments (i.e., @var{nargs} was 0),
then @var{avalues} is ignored.
then @var{avalues} is ignored. Note that argument values may be
modified by the callee (for instance, structs passed by value); the
burden of copying pass-by-value arguments is placed on the caller.
@end defun
@ -570,9 +594,7 @@ support for these.
@itemize @bullet
@item
There is no support for calling varargs functions. This may work on
some platforms, depending on how the ABI is defined, but it is not
reliable.
Variadic closures.
@item
There is no support for bit fields in structures.
@ -589,6 +611,8 @@ The ``raw'' API is undocumented.
@c anything else?
@end itemize
Note that variadic support is very new and tested on a relatively
small number of platforms.
@node Index
@unnumbered Index

View File

@ -17,6 +17,9 @@
/* Define this if you want extra debugging. */
#undef FFI_DEBUG
/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */
#undef FFI_EXEC_TRAMPOLINE_TABLE
/* Cannot use malloc on this target, so, we revert to alternative means */
#undef FFI_MMAP_EXEC_WRIT

View File

@ -1,16 +1,17 @@
/* -----------------------------------------------------------------*-C-*-
libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
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:
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 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
@ -77,15 +78,31 @@ extern "C" {
/* 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
@ -132,17 +149,17 @@ typedef struct _ffi_type
#endif
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != 9223372036854775807
# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != 9223372036854775807
#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 == 9223372036854775807
#elif LONG_MAX == FFI_64_BIT_MAX
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
@ -190,12 +207,21 @@ typedef struct {
#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 == 9223372036854775807
# elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8
# endif
#endif
@ -265,6 +291,9 @@ typedef struct {
} ffi_closure __attribute__((aligned (8)));
#else
} ffi_closure;
# ifdef __sgi
# pragma pack 0
# endif
#endif
void *ffi_closure_alloc (size_t size, void **code);
@ -283,6 +312,9 @@ ffi_prep_closure_loc (ffi_closure*,
void *user_data,
void*codeloc);
#ifdef __sgi
# pragma pack 8
#endif
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
@ -361,6 +393,13 @@ ffi_status ffi_prep_cif(ffi_cif *cif,
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,

View File

@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Copyright (C) 2007 Free Software Foundation, Inc
ffi_common.h - Copyright (C) 2011, 2012 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc
Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
@ -74,6 +75,8 @@ void ffi_type_test(ffi_type *a, char *file, int line);
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs, unsigned int ntotalargs);
/* Extended cif, used in callback from assembly routine */
typedef struct
@ -112,11 +115,14 @@ typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
#ifndef __GNUC__
#define __builtin_expect(x, expected_value) (x)
#endif
#define LIKELY(x) __builtin_expect(!!(x),1)
#define UNLIKELY(x) __builtin_expect((x)!=0,0)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -16,6 +16,15 @@ libffi, -lffi
.Fa "ffi_type **atypes"
.Fc
.Ft void
.Fo ffi_prep_cif_var
.Fa "ffi_cif *cif"
.Fa "ffi_abi abi"
.Fa "unsigned int nfixedargs"
.Fa "unsigned int ntotalargs"
.Fa "ffi_type *rtype"
.Fa "ffi_type **atypes"
.Fc
.Ft void
.Fo ffi_call
.Fa "ffi_cif *cif"
.Fa "void (*fn)(void)"
@ -28,4 +37,5 @@ generate a call to another function at runtime without requiring knowledge of
the called function's interface at compile time.
.Sh SEE ALSO
.Xr ffi_prep_cif 3 ,
.Xr ffi_prep_cif_var 3 ,
.Xr ffi_call 3

View File

@ -37,7 +37,9 @@ structs that describe the data type, size and alignment of each argument.
points to an
.Nm ffi_type
that describes the data type, size and alignment of the
return value.
return value. Note that to call a variadic function
.Nm ffi_prep_cif_var
must be used instead.
.Sh RETURN VALUES
Upon successful completion,
.Nm ffi_prep_cif
@ -63,4 +65,6 @@ defined in
.
.Sh SEE ALSO
.Xr ffi 3 ,
.Xr ffi_call 3
.Xr ffi_call 3 ,
.Xr ffi_prep_cif_var 3

View File

@ -0,0 +1,73 @@
.Dd January 25, 2011
.Dt ffi_prep_cif_var 3
.Sh NAME
.Nm ffi_prep_cif_var
.Nd Prepare a
.Nm ffi_cif
structure for use with
.Nm ffi_call
for variadic functions.
.Sh SYNOPSIS
.In ffi.h
.Ft ffi_status
.Fo ffi_prep_cif_var
.Fa "ffi_cif *cif"
.Fa "ffi_abi abi"
.Fa "unsigned int nfixedargs"
.Fa "unsigned int ntotalargs"
.Fa "ffi_type *rtype"
.Fa "ffi_type **atypes"
.Fc
.Sh DESCRIPTION
The
.Nm ffi_prep_cif_var
function prepares a
.Nm ffi_cif
structure for use with
.Nm ffi_call
for variadic functions.
.Fa abi
specifies a set of calling conventions to use.
.Fa atypes
is an array of
.Fa ntotalargs
pointers to
.Nm ffi_type
structs that describe the data type, size and alignment of each argument.
.Fa rtype
points to an
.Nm ffi_type
that describes the data type, size and alignment of the
return value.
.Fa nfixedargs
must contain the number of fixed (non-variadic) arguments.
Note that to call a non-variadic function
.Nm ffi_prep_cif
must be used.
.Sh RETURN VALUES
Upon successful completion,
.Nm ffi_prep_cif_var
returns
.Nm FFI_OK .
It will return
.Nm FFI_BAD_TYPEDEF
if
.Fa cif
is
.Nm NULL
or
.Fa atypes
or
.Fa rtype
is malformed. If
.Fa abi
does not refer to a valid ABI,
.Nm FFI_BAD_ABI
will be returned. Available ABIs are
defined in
.Nm <ffitarget.h>
.
.Sh SEE ALSO
.Xr ffi 3 ,
.Xr ffi_call 3 ,
.Xr ffi_prep_cif 3

View File

@ -42,10 +42,11 @@
# format and translated into something sensible for cl or ml.
#
args="-nologo"
args="-nologo -W3"
md=-MD
cl="cl"
ml="ml"
safeseh="-safeseh"
output=
while [ $# -gt 0 ]
@ -63,15 +64,28 @@ do
-m64)
cl="cl" # "$MSVC/x86_amd64/cl"
ml="ml64" # "$MSVC/x86_amd64/ml64"
safeseh=
shift 1
;;
-O0)
args="$args -Od"
shift 1
;;
-O*)
args="$args $1"
# If we're optimizing, make sure we explicitly turn on some optimizations
# that are implicitly disabled by debug symbols (-Zi).
args="$args $1 -OPT:REF -OPT:ICF -INCREMENTAL:NO"
shift 1
;;
-g)
# Can't specify -RTC1 or -Zi in opt. -Gy is ok. Use -OPT:REF?
args="$args -D_DEBUG -RTC1 -Zi"
# Enable debug symbol generation.
args="$args -Zi -DEBUG"
shift 1
;;
-DFFI_DEBUG)
# Link against debug CRT and enable runtime error checks.
args="$args -RTC1"
defines="$defines $1"
md=-MDd
shift 1
;;
@ -108,8 +122,8 @@ do
shift 1
;;
-Wall)
# -Wall on MSVC is overzealous. Use -W3 instead.
args="$args -W3"
# -Wall on MSVC is overzealous, and we already build with -W3. Nothing
# to do here.
shift 1
;;
-Werror)
@ -164,7 +178,7 @@ if [ -n "$assembly" ]; then
echo "$cl -nologo -EP $includes $defines $src > $ppsrc"
"$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $?
output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')"
args="-nologo -safeseh $single $output $ppsrc"
args="-nologo $safeseh $single $output $ppsrc"
echo "$ml $args"
eval "\"$ml\" $args"

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
ffi.c - Copyright (c) 2012 Anthony Green
Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc.
Alpha Foreign Function Interface
@ -178,6 +179,9 @@ ffi_prep_closure_loc (ffi_closure* closure,
{
unsigned int *tramp;
if (cif->abi != FFI_OSF)
return FFI_BAD_ABI;
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x47fb0401; /* mov $27,$1 */
tramp[1] = 0xa77b0010; /* ldq $27,16($27) */

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for Alpha.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;

View File

@ -1,6 +1,10 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc.
ffi.c - Copyright (c) 2011 Timothy Wall
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
Copyright (c) 2011 Anthony Green
Copyright (c) 2011 Free Software Foundation
Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
ARM Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
@ -61,6 +65,7 @@ int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
i--, p_arg++)
{
size_t z;
size_t alignment;
/* Allocated in VFP registers. */
if (ecif->cif->abi == FFI_VFP
@ -78,8 +83,13 @@ int ffi_prep_args(char *stack, extended_cif *ecif, float *vfp_space)
}
/* Align if necessary */
if (((*p_arg)->alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, (*p_arg)->alignment);
alignment = (*p_arg)->alignment;
#ifdef _WIN32_WCE
if (alignment > 4)
alignment = 4;
#endif
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, alignment);
}
if ((*p_arg)->type == FFI_TYPE_STRUCT)
@ -186,6 +196,18 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
/* Perform machine dependent cif processing for variadic calls */
ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
unsigned int nfixedargs,
unsigned int ntotalargs)
{
/* VFP variadic calls actually use the SYSV ABI */
if (cif->abi == FFI_VFP)
cif->abi = FFI_SYSV;
return ffi_prep_cif_machdep(cif);
}
/* Prototypes for assembly functions, in sysv.S */
extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
@ -317,6 +339,11 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
alignment = (*p_arg)->alignment;
if (alignment < 4)
alignment = 4;
#ifdef _WIN32_WCE
else
if (alignment > 4)
alignment = 4;
#endif
/* Align if necessary */
if ((alignment - 1) & (unsigned) argp) {
argp = (char *) ALIGN(argp, alignment);
@ -339,6 +366,220 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
extern unsigned int ffi_arm_trampoline[3];
#if FFI_EXEC_TRAMPOLINE_TABLE
#include <mach/mach.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
extern void *ffi_closure_trampoline_table_page;
typedef struct ffi_trampoline_table ffi_trampoline_table;
typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
struct ffi_trampoline_table {
/* contigious writable and executable pages */
vm_address_t config_page;
vm_address_t trampoline_page;
/* free list tracking */
uint16_t free_count;
ffi_trampoline_table_entry *free_list;
ffi_trampoline_table_entry *free_list_pool;
ffi_trampoline_table *prev;
ffi_trampoline_table *next;
};
struct ffi_trampoline_table_entry {
void *(*trampoline)();
ffi_trampoline_table_entry *next;
};
/* Override the standard architecture trampoline size */
// XXX TODO - Fix
#undef FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE 12
/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
/* Total number of trampolines that fit in one trampoline table */
#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
static ffi_trampoline_table *ffi_trampoline_tables = NULL;
static ffi_trampoline_table *
ffi_trampoline_table_alloc ()
{
ffi_trampoline_table *table = NULL;
/* Loop until we can allocate two contigious pages */
while (table == NULL) {
vm_address_t config_page = 0x0;
kern_return_t kt;
/* Try to allocate two pages */
kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
if (kt != KERN_SUCCESS) {
fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
break;
}
/* Now drop the second half of the allocation to make room for the trampoline table */
vm_address_t trampoline_page = config_page+PAGE_SIZE;
kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
if (kt != KERN_SUCCESS) {
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
break;
}
/* Remap the trampoline table to directly follow the config page */
vm_prot_t cur_prot;
vm_prot_t max_prot;
kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
/* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
if (kt != KERN_SUCCESS) {
/* Log unexpected failures */
if (kt != KERN_NO_SPACE) {
fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
}
vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
continue;
}
/* We have valid trampoline and config pages */
table = calloc (1, sizeof(ffi_trampoline_table));
table->free_count = FFI_TRAMPOLINE_COUNT;
table->config_page = config_page;
table->trampoline_page = trampoline_page;
/* Create and initialize the free list */
table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
uint16_t i;
for (i = 0; i < table->free_count; i++) {
ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
if (i < table->free_count - 1)
entry->next = &table->free_list_pool[i+1];
}
table->free_list = table->free_list_pool;
}
return table;
}
void *
ffi_closure_alloc (size_t size, void **code)
{
/* Create the closure */
ffi_closure *closure = malloc(size);
if (closure == NULL)
return NULL;
pthread_mutex_lock(&ffi_trampoline_lock);
/* Check for an active trampoline table with available entries. */
ffi_trampoline_table *table = ffi_trampoline_tables;
if (table == NULL || table->free_list == NULL) {
table = ffi_trampoline_table_alloc ();
if (table == NULL) {
free(closure);
return NULL;
}
/* Insert the new table at the top of the list */
table->next = ffi_trampoline_tables;
if (table->next != NULL)
table->next->prev = table;
ffi_trampoline_tables = table;
}
/* Claim the free entry */
ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
ffi_trampoline_tables->free_list = entry->next;
ffi_trampoline_tables->free_count--;
entry->next = NULL;
pthread_mutex_unlock(&ffi_trampoline_lock);
/* Initialize the return values */
*code = entry->trampoline;
closure->trampoline_table = table;
closure->trampoline_table_entry = entry;
return closure;
}
void
ffi_closure_free (void *ptr)
{
ffi_closure *closure = ptr;
pthread_mutex_lock(&ffi_trampoline_lock);
/* Fetch the table and entry references */
ffi_trampoline_table *table = closure->trampoline_table;
ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
/* Return the entry to the free list */
entry->next = table->free_list;
table->free_list = entry;
table->free_count++;
/* If all trampolines within this table are free, and at least one other table exists, deallocate
* the table */
if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
/* Remove from the list */
if (table->prev != NULL)
table->prev->next = table->next;
if (table->next != NULL)
table->next->prev = table->prev;
/* Deallocate pages */
kern_return_t kt;
kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
if (kt != KERN_SUCCESS)
fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
/* Deallocate free list */
free (table->free_list_pool);
free (table);
} else if (ffi_trampoline_tables != table) {
/* Otherwise, bump this table to the top of the list */
table->prev = NULL;
table->next = ffi_trampoline_tables;
if (ffi_trampoline_tables != NULL)
ffi_trampoline_tables->prev = table;
ffi_trampoline_tables = table;
}
pthread_mutex_unlock (&ffi_trampoline_lock);
/* Free the closure */
free (closure);
}
#else
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \
@ -353,6 +594,7 @@ extern unsigned int ffi_arm_trampoline[3];
mapping. */ \
})
#endif
/* the cif must already be prep'ed */
@ -370,12 +612,18 @@ ffi_prep_closure_loc (ffi_closure* closure,
else if (cif->abi == FFI_VFP)
closure_func = &ffi_closure_VFP;
else
FFI_ASSERT (0);
return FFI_BAD_ABI;
#if FFI_EXEC_TRAMPOLINE_TABLE
void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
config[0] = closure;
config[1] = closure_func;
#else
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
closure_func, \
codeloc);
#endif
closure->cif = cif;
closure->user_data = user_data;
closure->fun = fun;

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
Copyright (c) 2010 CodeSourcery
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2010 CodeSourcery
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for ARM.
@ -29,6 +30,10 @@
#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
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
@ -55,6 +60,8 @@ typedef enum ffi_abi {
#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
#define FFI_TARGET_SPECIFIC_VARIADIC
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
@ -62,4 +69,3 @@ typedef enum ffi_abi {
#define FFI_NATIVE_RAW_API 0
#endif

118
libffi/src/arm/gentramp.sh Executable file
View File

@ -0,0 +1,118 @@
#!/bin/sh
# -----------------------------------------------------------------------
# gentramp.sh - Copyright (c) 2010, Plausible Labs Cooperative, Inc.
#
# ARM Trampoline Page Generator
#
# 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.
# -----------------------------------------------------------------------
PROGNAME=$0
# Each trampoline is exactly 3 instructions, or 12 bytes. If any of these values change,
# the entire arm trampoline implementation must be updated to match, too.
# Size of an individual trampoline, in bytes
TRAMPOLINE_SIZE=12
# Page size, in bytes
PAGE_SIZE=4096
# Compute the size of the reachable config page; The first 16 bytes of the config page
# are unreachable due to our maximum pc-relative ldr offset.
PAGE_AVAIL=`expr $PAGE_SIZE - 16`
# Compute the number of of available trampolines.
TRAMPOLINE_COUNT=`expr $PAGE_AVAIL / $TRAMPOLINE_SIZE`
header () {
echo "# GENERATED CODE - DO NOT EDIT"
echo "# This file was generated by $PROGNAME"
echo ""
# Write out the license header
cat << EOF
# Copyright (c) 2010, Plausible Labs Cooperative, 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.
# -----------------------------------------------------------------------
EOF
# Write out the trampoline table, aligned to the page boundary
echo ".text"
echo ".align 12"
echo ".globl _ffi_closure_trampoline_table_page"
echo "_ffi_closure_trampoline_table_page:"
}
# WARNING - Don't modify the trampoline code size without also updating the relevent libffi code
trampoline () {
cat << END
// trampoline
// Save to stack
stmfd sp!, {r0-r3}
// Load the context argument from the config page.
// This places the first usable config value at _ffi_closure_trampoline_table-4080
// This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc.
ldr r0, [pc, #-4092]
// Load the jump address from the config page.
ldr pc, [pc, #-4092]
END
}
main () {
# Write out the header
header
# Write out the trampolines
local i=0
while [ $i -lt ${TRAMPOLINE_COUNT} ]; do
trampoline
local i=`expr $i + 1`
done
}
main

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc.
Copyright (c) 2011 Plausible Labs Cooperative, Inc.
ARM Foreign Function Interface
@ -39,7 +40,11 @@
#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__
@ -48,6 +53,12 @@
#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.
@ -105,21 +116,33 @@
.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. */
_L__\name:
#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
@ -141,8 +164,7 @@ _L__\name:
#endif
.endm
@ r0: fn
@ r0: ffi_prep_args
@ r1: &ecif
@ r2: cif->bytes
@ r3: fig->flags
@ -222,11 +244,18 @@ ARM_FUNC_START ffi_call_SYSV
#endif
LSYM(Lepilogue):
RETLDM "r0-r3,fp"
#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
/*
@ -247,7 +276,7 @@ ARM_FUNC_START ffi_closure_SYSV
sub sp, sp, #16
str sp, [sp, #8]
add r1, sp, #8
bl ffi_closure_SYSV_inner
bl CNAME(ffi_closure_SYSV_inner)
cmp r0, #FFI_TYPE_INT
beq .Lretint
@ -299,7 +328,9 @@ ARM_FUNC_START ffi_closure_SYSV
.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.
@ -371,7 +402,7 @@ LSYM(Lbase_args):
@ assume no return value.
cmp r2, #0
beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_INT
streq r0, [r2]
beq LSYM(Lepilogue_vfp)

4450
libffi/src/arm/trampoline.S Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
AVR32 Foreign Function Interface
@ -394,7 +395,8 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
void *codeloc)
{
FFI_ASSERT(cif->abi == FFI_SYSV);
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
unsigned char *__tramp = (unsigned char*)(&closure->tramp[0]);
unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2009 Bradley Smith <brad@brad-smith.co.uk>
Target configuration macros for AVR32.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
@ -34,8 +39,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
closures.c - Copyright (c) 2007 Red Hat, Inc.
Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc
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.
@ -32,7 +33,7 @@
#include <ffi.h>
#include <ffi_common.h>
#ifndef FFI_MMAP_EXEC_WRIT
#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
@ -63,7 +64,11 @@
#if FFI_CLOSURES
# if FFI_MMAP_EXEC_WRIT
# 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
@ -167,7 +172,7 @@ selinux_enabled_check (void)
#endif /* !FFI_MMAP_EXEC_SELINUX */
#elif defined (__CYGWIN__)
#elif defined (__CYGWIN__) || defined(__INTERIX)
#include <sys/mman.h>
@ -193,11 +198,11 @@ 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__)
#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__) */
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#define mmap dlmmap
#define munmap dlmunmap
@ -207,7 +212,7 @@ static int dlmunmap(void *, size_t);
#undef mmap
#undef munmap
#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__)
#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;
@ -522,7 +527,7 @@ segment_holding_code (mstate m, char* addr)
}
#endif
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) */
#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

View File

@ -153,21 +153,24 @@ ffi_prep_args (char *stack, extended_cif * ecif)
return (struct_count);
}
ffi_status
ffi_prep_cif (ffi_cif * cif,
ffi_abi abi, unsigned int nargs,
ffi_type * rtype, ffi_type ** atypes)
ffi_status FFI_HIDDEN
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)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT (cif != NULL);
FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
FFI_ASSERT(nfixedargs <= ntotalargs);
FFI_ASSERT (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI);
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->nargs = ntotalargs;
cif->rtype = rtype;
cif->flags = 0;

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for CRIS.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
@ -34,8 +39,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif

View File

@ -622,6 +622,9 @@ DEFAULT_MMAP_THRESHOLD default: 256K
#include "/usr/include/malloc.h"
#else /* HAVE_USR_INCLUDE_MALLOC_H */
/* HP-UX's stdlib.h redefines mallinfo unless _STRUCT_MALLINFO is defined */
#define _STRUCT_MALLINFO
struct mallinfo {
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2004 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2004 Red Hat, Inc.
Target configuration macros for FR-V
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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 ----------------------------------- */
#ifndef LIBFFI_ASM
@ -35,13 +40,9 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
#ifdef FRV
FFI_EABI,
FFI_DEFAULT_ABI = FFI_EABI,
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_EABI
} ffi_abi;
#endif

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc.
Copyright (c) 2000 Hewlett Packard Company
Copyright (c) 2011 Anthony Green
IA64 Foreign Function Interface
@ -429,7 +430,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
struct ffi_ia64_trampoline_struct *tramp;
struct ia64_fd *fd;
FFI_ASSERT (cif->abi == FFI_UNIX);
if (cif->abi != FFI_UNIX)
return FFI_BAD_ABI;
tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
fd = (struct ia64_fd *)(void *)ffi_closure_unix;

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for IA-64.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#ifndef LIBFFI_ASM
typedef unsigned long long ffi_arg;
typedef signed long long ffi_sarg;
@ -34,8 +39,8 @@ typedef signed long long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_UNIX, /* Linux and all Unix variants use the same conventions */
FFI_DEFAULT_ABI = FFI_UNIX,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_UNIX
} ffi_abi;
#endif

View File

@ -311,7 +311,7 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue,
ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
ffi_java_ptrarray_to_raw (cif, avalue, raw);
(*cl->fun) (cif, rvalue, raw, cl->user_data);
(*cl->fun) (cif, rvalue, (ffi_raw*)raw, cl->user_data);
ffi_java_raw_to_rvalue (cif, rvalue);
}

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 2004 Renesas Technology.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2004 Renesas Technology.
Target configuration macros for M32R.
Permission is hereby granted, free of charge, to any person obtaining
@ -26,6 +27,10 @@
#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
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
@ -36,8 +41,8 @@ typedef enum ffi_abi
{
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif

View File

@ -261,7 +261,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
void *user_data,
void *codeloc)
{
FFI_ASSERT (cif->abi == FFI_SYSV);
if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
*(unsigned short *)closure->tramp = 0x207c;
*(void **)(closure->tramp + 2) = codeloc;

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for Motorola 68K.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#ifndef LIBFFI_ASM
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
@ -34,8 +39,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc.
Copyright (c) 2008 David Daney
ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 2008 David Daney
Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
MIPS Foreign Function Interface
@ -37,7 +38,11 @@
#endif
#ifndef USE__BUILTIN___CLEAR_CACHE
#include <sys/cachectl.h>
# if defined(__OpenBSD__)
# include <mips64/sysarch.h>
# else
# include <sys/cachectl.h>
# endif
#endif
#ifdef FFI_DEBUG
@ -662,10 +667,12 @@ ffi_prep_closure_loc (ffi_closure *closure,
char *clear_location = (char *) codeloc;
#if defined(FFI_MIPS_O32)
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT)
return FFI_BAD_ABI;
fn = ffi_closure_O32;
#else /* FFI_MIPS_N32 */
FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
if (cif->abi != FFI_N32 && cif->abi != FFI_N64)
return FFI_BAD_ABI;
fn = ffi_closure_N32;
#endif /* FFI_MIPS_O32 */

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for MIPS.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#ifdef linux
# include <asm/sgidefs.h>
#elif defined(__rtems__)
@ -36,7 +41,7 @@
#define _MIPS_SIM_ABI32 1
#define _MIPS_SIM_NABI32 2
#define _MIPS_SIM_ABI64 3
#else
#elif !defined(__OpenBSD__)
# include <sgidefs.h>
#endif
@ -51,7 +56,7 @@
# endif
#if !defined(_MIPS_SIM)
-- something is very wrong --
# error -- something is very wrong --
#else
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
# define FFI_MIPS_N32
@ -59,7 +64,7 @@
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
# define FFI_MIPS_O32
# else
-- this is an unsupported platform --
# error -- this is an unsupported platform --
# endif
# endif
#endif
@ -194,30 +199,29 @@ typedef enum ffi_abi {
FFI_O32_SOFT_FLOAT,
FFI_N32_SOFT_FLOAT,
FFI_N64_SOFT_FLOAT,
FFI_LAST_ABI,
#ifdef FFI_MIPS_O32
#ifdef __mips_soft_float
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT,
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT
#else
FFI_DEFAULT_ABI = FFI_O32,
FFI_DEFAULT_ABI = FFI_O32
#endif
#else
# if _MIPS_SIM==_ABI64
# ifdef __mips_soft_float
FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT,
FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT
# else
FFI_DEFAULT_ABI = FFI_N64,
FFI_DEFAULT_ABI = FFI_N64
# endif
# else
# ifdef __mips_soft_float
FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT,
FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT
# else
FFI_DEFAULT_ABI = FFI_N32,
FFI_DEFAULT_ABI = FFI_N32
# endif
# endif
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag

View File

@ -1,9 +1,11 @@
/* -----------------------------------------------------------------------
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
ffi.c - (c) 2011 Anthony Green
(c) 2008 Red Hat, Inc.
(c) 2006 Free Software Foundation, Inc.
(c) 2003-2004 Randolph Chung <tausq@debian.org>
HPPA Foreign Function Interface
HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
HP-UX PA ABI support
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -633,7 +635,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
UINT32 *tmp;
#endif
FFI_ASSERT (cif->abi == FFI_PA32);
if (cif->abi != FFI_PA32)
return FFI_BAD_ABI;
/* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for hppa.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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 ----------------------------------- */
#ifndef LIBFFI_ASM
@ -38,21 +43,22 @@ typedef enum ffi_abi {
#ifdef PA_LINUX
FFI_PA32,
FFI_DEFAULT_ABI = FFI_PA32,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_PA32
#endif
#ifdef PA_HPUX
FFI_PA32,
FFI_DEFAULT_ABI = FFI_PA32,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_PA32
#endif
#ifdef PA64_HPUX
#error "PA64_HPUX FFI is not yet implemented"
FFI_PA64,
FFI_DEFAULT_ABI = FFI_PA64,
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_PA64
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif

View File

@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------
aix.S - Copyright (c) 2002,2009 Free Software Foundation, Inc.
aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc.
based on darwin.S by John Hornkvist
PowerPC Assembly glue.
@ -79,6 +79,8 @@
.set f20,20
.set f21,21
.extern .ffi_prep_args
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
@ -125,6 +127,7 @@ ffi_call_AIX:
/* Call ffi_prep_args. */
mr r4, r1
bl .ffi_prep_args
nop
/* Now do the call. */
ld r0, 0(r29)
@ -226,6 +229,7 @@ L(float_return_value):
/* Call ffi_prep_args. */
mr r4, r1
bl .ffi_prep_args
nop
/* Now do the call. */
lwz r0, 0(r29)

View File

@ -79,6 +79,8 @@
.set f20,20
.set f21,21
.extern .ffi_closure_helper_DARWIN
#define LIBFFI_ASM
#define JUMPTARGET(name) name
#define L(x) x

View File

@ -42,7 +42,7 @@
/* If compiled for profiling, call `_mcount' at the start of each function. */
#ifdef PROF
/* The mcount code relies on a the return address being on the stack
/* The mcount code relies on the return address being on the stack
to locate our caller and so it can restore it; so store one just
for its benefit. */
#ifdef PIC

View File

@ -335,7 +335,7 @@ LSCIE1:
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x90 ; FDE Encoding (indirect pcrel)
.byte 0x10 ; FDE Encoding (indirect pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0

View File

@ -484,7 +484,7 @@ LSCIE1:
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size
.byte 0x90 ; FDE Encoding (indirect pcrel)
.byte 0x10 ; FDE Encoding (indirect pcrel)
.byte 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0

View File

@ -1,7 +1,9 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998 Geoffrey Keating
Copyright (C) 2007, 2008 Free Software Foundation, Inc
Copyright (C) 2008 Red Hat, Inc
ffi.c - Copyright (C) 2011 Anthony Green
Copyright (C) 2011 Kyle Moffett
Copyright (C) 2008 Red Hat, Inc
Copyright (C) 2007, 2008 Free Software Foundation, Inc
Copyright (c) 1998 Geoffrey Keating
PowerPC Foreign Function Interface
@ -39,32 +41,28 @@ enum {
/* The assembly depends on these exact flags. */
FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */
FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */
#ifndef __NO_FPRS__
FLAG_RETURNS_FP = 1 << (31-29),
#endif
FLAG_RETURNS_64BITS = 1 << (31-28),
FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */
FLAG_SYSV_SMST_R4 = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
structs. */
FLAG_SYSV_SMST_R3 = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
structs. */
/* Bits (31-24) through (31-19) store shift value for SMST */
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
#ifndef __NO_FPRS__
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
#endif
FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
FLAG_RETVAL_REFERENCE = 1 << (31- 4)
};
/* About the SYSV ABI. */
unsigned int NUM_GPR_ARG_REGISTERS = 8;
#define ASM_NEEDS_REGISTERS 4
#define NUM_GPR_ARG_REGISTERS 8
#ifndef __NO_FPRS__
unsigned int NUM_FPR_ARG_REGISTERS = 8;
#else
unsigned int NUM_FPR_ARG_REGISTERS = 0;
# define NUM_FPR_ARG_REGISTERS 8
#endif
enum { ASM_NEEDS_REGISTERS = 4 };
/* ffi_prep_args_SYSV is called by the assembly routine once stack space
has been allocated for the function's arguments.
@ -113,10 +111,12 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
valp gpr_base;
int intarg_count;
#ifndef __NO_FPRS__
/* 'fpr_base' points at the space for fpr1, and grows upwards as
we use FPR registers. */
valp fpr_base;
int fparg_count;
#endif
/* 'copy_space' grows down as we put structures in it. It should
stay 16-byte aligned. */
@ -125,9 +125,8 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
/* 'next_arg' grows up as we put parameters in it. */
valp next_arg;
int i, ii MAYBE_UNUSED;
int i;
ffi_type **ptr;
double double_tmp;
union {
void **v;
char **c;
@ -143,15 +142,16 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
size_t struct_copy_size;
unsigned gprvalue;
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
NUM_FPR_ARG_REGISTERS = 0;
stacktop.c = (char *) stack + bytes;
gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
intarg_count = 0;
#ifndef __NO_FPRS__
fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
fparg_count = 0;
copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
#else
copy_space.c = gpr_base.c;
#endif
next_arg.u = stack + 2;
/* Check that everything starts aligned properly. */
@ -174,12 +174,28 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
i > 0;
i--, ptr++, p_argv.v++)
{
switch ((*ptr)->type)
{
unsigned short typenum = (*ptr)->type;
/* We may need to handle some values depending on ABI */
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) {
if (typenum == FFI_TYPE_FLOAT)
typenum = FFI_TYPE_UINT32;
if (typenum == FFI_TYPE_DOUBLE)
typenum = FFI_TYPE_UINT64;
if (typenum == FFI_TYPE_LONGDOUBLE)
typenum = FFI_TYPE_UINT128;
} else if (ecif->cif->abi != FFI_LINUX) {
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
if (typenum == FFI_TYPE_LONGDOUBLE)
typenum = FFI_TYPE_STRUCT;
#endif
}
/* Now test the translated value */
switch (typenum) {
#ifndef __NO_FPRS__
case FFI_TYPE_FLOAT:
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
goto soft_float_prep;
double_tmp = **p_argv.f;
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
{
@ -218,43 +234,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if ((ecif->cif->abi != FFI_LINUX)
&& (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
goto do_struct;
/* The soft float ABI for long doubles works like this,
a long double is passed in four consecutive gprs if available.
A maximum of 2 long doubles can be passed in gprs.
If we do not have 4 gprs left, the long double is passed on the
stack, 4-byte aligned. */
if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
{
unsigned int int_tmp = (*p_argv.ui)[0];
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
{
if (intarg_count < NUM_GPR_ARG_REGISTERS)
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
*next_arg.u = int_tmp;
next_arg.u++;
for (ii = 1; ii < 4; ii++)
{
int_tmp = (*p_argv.ui)[ii];
*next_arg.u = int_tmp;
next_arg.u++;
}
}
else
{
*gpr_base.u++ = int_tmp;
for (ii = 1; ii < 4; ii++)
{
int_tmp = (*p_argv.ui)[ii];
*gpr_base.u++ = int_tmp;
}
}
intarg_count +=4;
}
else
{
double_tmp = (*p_argv.d)[0];
if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
@ -280,13 +259,40 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
fparg_count += 2;
FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
}
break;
#endif
#endif /* have FPRs */
/*
* The soft float ABI for long doubles works like this, a long double
* is passed in four consecutive GPRs if available. A maximum of 2
* long doubles can be passed in gprs. If we do not have 4 GPRs
* left, the long double is passed on the stack, 4-byte aligned.
*/
case FFI_TYPE_UINT128: {
unsigned int int_tmp = (*p_argv.ui)[0];
unsigned int ii;
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) {
if (intarg_count < NUM_GPR_ARG_REGISTERS)
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
*(next_arg.u++) = int_tmp;
for (ii = 1; ii < 4; ii++) {
int_tmp = (*p_argv.ui)[ii];
*(next_arg.u++) = int_tmp;
}
} else {
*(gpr_base.u++) = int_tmp;
for (ii = 1; ii < 4; ii++) {
int_tmp = (*p_argv.ui)[ii];
*(gpr_base.u++) = int_tmp;
}
}
intarg_count += 4;
break;
}
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
soft_double_prep:
if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
intarg_count++;
if (intarg_count >= NUM_GPR_ARG_REGISTERS)
@ -319,9 +325,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
break;
case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
do_struct:
#endif
struct_copy_size = ((*ptr)->size + 15) & ~0xF;
copy_space.c -= struct_copy_size;
memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
@ -349,7 +352,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
soft_float_prep:
gprvalue = **p_argv.ui;
@ -366,8 +368,10 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
/* Check that we didn't overrun the stack... */
FFI_ASSERT (copy_space.c >= next_arg.c);
FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
#ifndef __NO_FPRS__
FFI_ASSERT (fpr_base.u
<= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
#endif
FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
}
@ -604,9 +608,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
unsigned type = cif->rtype->type;
unsigned size = cif->rtype->size;
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
NUM_FPR_ARG_REGISTERS = 0;
if (cif->abi != FFI_LINUX64)
{
/* All the machine-independent calculation of cif->bytes will be wrong.
@ -646,62 +647,56 @@ ffi_prep_cif_machdep (ffi_cif *cif)
- Single/double FP values in fpr1, long double in fpr1,fpr2.
- soft-float float/doubles are treated as UINT32/UINT64 respectivley.
- soft-float long doubles are returned in gpr3-gpr6. */
/* First translate for softfloat/nonlinux */
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
if (type == FFI_TYPE_FLOAT)
type = FFI_TYPE_UINT32;
if (type == FFI_TYPE_DOUBLE)
type = FFI_TYPE_UINT64;
if (type == FFI_TYPE_LONGDOUBLE)
type = FFI_TYPE_UINT128;
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
if (type == FFI_TYPE_LONGDOUBLE)
type = FFI_TYPE_STRUCT;
#endif
}
switch (type)
{
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
#ifndef __NO_FPRS__
case FFI_TYPE_LONGDOUBLE:
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
&& cif->abi != FFI_LINUX_SOFT_FLOAT)
goto byref;
flags |= FLAG_RETURNS_128BITS;
/* Fall through. */
#endif
case FFI_TYPE_DOUBLE:
flags |= FLAG_RETURNS_64BITS;
/* Fall through. */
case FFI_TYPE_FLOAT:
/* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */
if (cif->abi != FFI_LINUX_SOFT_FLOAT)
flags |= FLAG_RETURNS_FP;
flags |= FLAG_RETURNS_FP;
break;
#endif
case FFI_TYPE_UINT128:
flags |= FLAG_RETURNS_128BITS;
/* Fall through. */
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
flags |= FLAG_RETURNS_64BITS;
break;
case FFI_TYPE_STRUCT:
if (cif->abi == FFI_SYSV)
{
/* The final SYSV ABI says that structures smaller or equal 8 bytes
are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
in memory. */
/* Treat structs with size <= 8 bytes. */
if (size <= 8)
{
flags |= FLAG_RETURNS_SMST;
/* These structs are returned in r3. We pack the type and the
precalculated shift value (needed in the sysv.S) into flags.
The same applies for the structs returned in r3/r4. */
if (size <= 4)
{
flags |= FLAG_SYSV_SMST_R3;
flags |= 8 * (4 - size) << 8;
break;
}
/* These structs are returned in r3 and r4. See above. */
if (size <= 8)
{
flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
flags |= 8 * (8 - size) << 8;
break;
}
}
}
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
byref:
#endif
/*
* The final SYSV ABI says that structures smaller or equal 8 bytes
* are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
* in memory.
*
* NOTE: The assembly code can safely assume that it just needs to
* store both r3 and r4 into a 8-byte word-aligned buffer, as
* we allocate a temporary buffer in ffi_call() if this flag is
* set.
*/
if (cif->abi == FFI_SYSV && size <= 8)
flags |= FLAG_RETURNS_SMST;
intarg_count++;
flags |= FLAG_RETVAL_REFERENCE;
/* Fall through. */
@ -722,39 +717,36 @@ ffi_prep_cif_machdep (ffi_cif *cif)
Stuff on the stack needs to keep proper alignment. */
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
switch ((*ptr)->type)
{
unsigned short typenum = (*ptr)->type;
/* We may need to handle some values depending on ABI */
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
if (typenum == FFI_TYPE_FLOAT)
typenum = FFI_TYPE_UINT32;
if (typenum == FFI_TYPE_DOUBLE)
typenum = FFI_TYPE_UINT64;
if (typenum == FFI_TYPE_LONGDOUBLE)
typenum = FFI_TYPE_UINT128;
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
if (typenum == FFI_TYPE_LONGDOUBLE)
typenum = FFI_TYPE_STRUCT;
#endif
}
switch (typenum) {
#ifndef __NO_FPRS__
case FFI_TYPE_FLOAT:
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
goto soft_float_cif;
fparg_count++;
/* floating singles are not 8-aligned on stack */
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
goto do_struct;
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
{
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
|| intarg_count < NUM_GPR_ARG_REGISTERS)
/* A long double in FFI_LINUX_SOFT_FLOAT can use only
a set of four consecutive gprs. If we have not enough,
we have to adjust the intarg_count value. */
intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
intarg_count += 4;
break;
}
else
fparg_count++;
fparg_count++;
/* Fall thru */
#endif
case FFI_TYPE_DOUBLE:
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
goto soft_double_cif;
fparg_count++;
/* If this FP arg is going on the stack, it must be
8-byte-aligned. */
@ -763,10 +755,21 @@ ffi_prep_cif_machdep (ffi_cif *cif)
&& intarg_count % 2 != 0)
intarg_count++;
break;
#endif
case FFI_TYPE_UINT128:
/*
* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
* of four consecutive gprs. If we do not have enough, we
* have to adjust the intarg_count value.
*/
if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
&& intarg_count < NUM_GPR_ARG_REGISTERS)
intarg_count = NUM_GPR_ARG_REGISTERS;
intarg_count += 4;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
soft_double_cif:
/* 'long long' arguments are passed as two words, but
either both words must fit in registers or both go
on the stack. If they go on the stack, they must
@ -783,9 +786,6 @@ ffi_prep_cif_machdep (ffi_cif *cif)
break;
case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
do_struct:
#endif
/* We must allocate space for a copy of these to enforce
pass-by-value. Pad the space up to a multiple of 16
bytes (the maximum alignment required for anything under
@ -793,12 +793,20 @@ ffi_prep_cif_machdep (ffi_cif *cif)
struct_copy_size += ((*ptr)->size + 15) & ~0xF;
/* Fall through (allocate space for the pointer). */
default:
soft_float_cif:
case FFI_TYPE_POINTER:
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
/* Everything else is passed as a 4-byte word in a GPR, either
the object itself or a pointer to it. */
intarg_count++;
break;
default:
FFI_ASSERT (0);
}
}
else
@ -827,16 +835,29 @@ ffi_prep_cif_machdep (ffi_cif *cif)
intarg_count += ((*ptr)->size + 7) / 8;
break;
default:
case FFI_TYPE_POINTER:
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT8:
case FFI_TYPE_SINT8:
/* Everything else is passed as a 8-byte word in a GPR, either
the object itself or a pointer to it. */
intarg_count++;
break;
default:
FFI_ASSERT (0);
}
}
#ifndef __NO_FPRS__
if (fparg_count != 0)
flags |= FLAG_FP_ARGUMENTS;
#endif
if (intarg_count > 4)
flags |= FLAG_4_GPR_ARGUMENTS;
if (struct_copy_size != 0)
@ -844,21 +865,27 @@ ffi_prep_cif_machdep (ffi_cif *cif)
if (cif->abi != FFI_LINUX64)
{
#ifndef __NO_FPRS__
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
#endif
/* Stack space. */
if (intarg_count > NUM_GPR_ARG_REGISTERS)
bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
#ifndef __NO_FPRS__
if (fparg_count > NUM_FPR_ARG_REGISTERS)
bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
#endif
}
else
{
#ifndef __NO_FPRS__
/* Space for the FPR registers, if needed. */
if (fparg_count != 0)
bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
#endif
/* Stack space. */
if (intarg_count > NUM_GPR_ARG_REGISTERS64)
@ -886,28 +913,41 @@ extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
void
ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
/*
* The final SYSV ABI says that structures smaller or equal 8 bytes
* are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
* in memory.
*
* Just to keep things simple for the assembly code, we will always
* bounce-buffer struct return values less than or equal to 8 bytes.
* This allows the ASM to handle SYSV small structures by directly
* writing r3 and r4 to memory without worrying about struct size.
*/
unsigned int smst_buffer[2];
extended_cif ecif;
unsigned int rsize;
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;
/* Ensure that we have a valid struct return value */
ecif.rvalue = rvalue;
if (cif->rtype->type == FFI_TYPE_STRUCT) {
rsize = cif->rtype->size;
if (rsize <= 8)
ecif.rvalue = smst_buffer;
else if (!rvalue)
ecif.rvalue = alloca(rsize);
}
switch (cif->abi)
{
#ifndef POWERPC64
# ifndef __NO_FPRS__
case FFI_SYSV:
case FFI_GCC_SYSV:
case FFI_LINUX:
# endif
case FFI_LINUX_SOFT_FLOAT:
ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
break;
@ -920,6 +960,10 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
FFI_ASSERT (0);
break;
}
/* Check for a bounce-buffered return value */
if (rvalue && ecif.rvalue == smst_buffer)
memcpy(rvalue, smst_buffer, rsize);
}
@ -949,14 +993,19 @@ ffi_prep_closure_loc (ffi_closure *closure,
#ifdef POWERPC64
void **tramp = (void **) &closure->tramp[0];
FFI_ASSERT (cif->abi == FFI_LINUX64);
if (cif->abi != FFI_LINUX64)
return FFI_BAD_ABI;
/* Copy function address and TOC from ffi_closure_LINUX64. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
tramp[2] = codeloc;
#else
unsigned int *tramp;
FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
if (! (cif->abi == FFI_GCC_SYSV
|| cif->abi == FFI_SYSV
|| cif->abi == FFI_LINUX
|| cif->abi == FFI_LINUX_SOFT_FLOAT))
return FFI_BAD_ABI;
tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x7c0802a6; /* mflr r0 */
@ -1011,32 +1060,38 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
void ** avalue;
ffi_type ** arg_types;
long i, avn;
long nf; /* number of floating registers already used */
long ng; /* number of general registers already used */
ffi_cif * cif;
double temp;
unsigned size;
#ifndef __NO_FPRS__
long nf = 0; /* number of floating registers already used */
#endif
long ng = 0; /* number of general registers already used */
ffi_cif *cif = closure->cif;
unsigned size = cif->rtype->size;
unsigned short rtypenum = cif->rtype->type;
cif = closure->cif;
avalue = alloca (cif->nargs * sizeof (void *));
size = cif->rtype->size;
nf = 0;
ng = 0;
/* First translate for softfloat/nonlinux */
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
if (rtypenum == FFI_TYPE_FLOAT)
rtypenum = FFI_TYPE_UINT32;
if (rtypenum == FFI_TYPE_DOUBLE)
rtypenum = FFI_TYPE_UINT64;
if (rtypenum == FFI_TYPE_LONGDOUBLE)
rtypenum = FFI_TYPE_UINT128;
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
if (rtypenum == FFI_TYPE_LONGDOUBLE)
rtypenum = FFI_TYPE_STRUCT;
#endif
}
/* Copy the caller's structure return value address so that the closure
returns the data directly to the caller.
For FFI_SYSV the result is passed in r3/r4 if the struct size is less
or equal 8 bytes. */
if ((cif->rtype->type == FFI_TYPE_STRUCT
&& !((cif->abi == FFI_SYSV) && (size <= 8)))
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| (cif->rtype->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
#endif
)
{
if (rtypenum == FFI_TYPE_STRUCT && ((cif->abi != FFI_SYSV) || (size > 8))) {
rvalue = (void *) *pgr;
ng++;
pgr++;
@ -1047,10 +1102,109 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
arg_types = cif->arg_types;
/* Grab the addresses of the arguments from the stack frame. */
while (i < avn)
{
switch (arg_types[i]->type)
{
while (i < avn) {
unsigned short typenum = arg_types[i]->type;
/* We may need to handle some values depending on ABI */
if (cif->abi == FFI_LINUX_SOFT_FLOAT) {
if (typenum == FFI_TYPE_FLOAT)
typenum = FFI_TYPE_UINT32;
if (typenum == FFI_TYPE_DOUBLE)
typenum = FFI_TYPE_UINT64;
if (typenum == FFI_TYPE_LONGDOUBLE)
typenum = FFI_TYPE_UINT128;
} else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) {
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
if (typenum == FFI_TYPE_LONGDOUBLE)
typenum = FFI_TYPE_STRUCT;
#endif
}
switch (typenum) {
#ifndef __NO_FPRS__
case FFI_TYPE_FLOAT:
/* unfortunately float values are stored as doubles
* in the ffi_closure_SYSV code (since we don't check
* the type in that routine).
*/
/* there are 8 64bit floating point registers */
if (nf < 8)
{
temp = pfr->d;
pfr->f = (float) temp;
avalue[i] = pfr;
nf++;
pfr++;
}
else
{
/* FIXME? here we are really changing the values
* stored in the original calling routines outgoing
* parameter stack. This is probably a really
* naughty thing to do but...
*/
avalue[i] = pst;
pst += 1;
}
break;
case FFI_TYPE_DOUBLE:
/* On the outgoing stack all values are aligned to 8 */
/* there are 8 64bit floating point registers */
if (nf < 8)
{
avalue[i] = pfr;
nf++;
pfr++;
}
else
{
if (((long) pst) & 4)
pst++;
avalue[i] = pst;
pst += 2;
}
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (nf < 7)
{
avalue[i] = pfr;
pfr += 2;
nf += 2;
}
else
{
if (((long) pst) & 4)
pst++;
avalue[i] = pst;
pst += 4;
nf = 8;
}
break;
#endif
#endif /* have FPRS */
case FFI_TYPE_UINT128:
/*
* Test if for the whole long double, 4 gprs are available.
* otherwise the stuff ends up on the stack.
*/
if (ng < 5) {
avalue[i] = pgr;
pgr += 4;
ng += 4;
} else {
avalue[i] = pst;
pst += 4;
ng = 8+4;
}
break;
case FFI_TYPE_SINT8:
case FFI_TYPE_UINT8:
/* there are 8 gpr registers used to pass values */
@ -1086,7 +1240,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
soft_float_closure:
/* there are 8 gpr registers used to pass values */
if (ng < 8)
{
@ -1102,9 +1255,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
break;
case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
do_struct:
#endif
/* Structs are passed by reference. The address will appear in a
gpr if it is one of the first 8 arguments. */
if (ng < 8)
@ -1122,7 +1272,6 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
case FFI_TYPE_SINT64:
case FFI_TYPE_UINT64:
soft_double_closure:
/* passing long long ints are complex, they must
* be passed in suitable register pairs such as
* (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
@ -1154,99 +1303,8 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
}
break;
case FFI_TYPE_FLOAT:
/* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
goto soft_float_closure;
/* unfortunately float values are stored as doubles
* in the ffi_closure_SYSV code (since we don't check
* the type in that routine).
*/
/* there are 8 64bit floating point registers */
if (nf < 8)
{
temp = pfr->d;
pfr->f = (float) temp;
avalue[i] = pfr;
nf++;
pfr++;
}
else
{
/* FIXME? here we are really changing the values
* stored in the original calling routines outgoing
* parameter stack. This is probably a really
* naughty thing to do but...
*/
avalue[i] = pst;
pst += 1;
}
break;
case FFI_TYPE_DOUBLE:
/* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
goto soft_double_closure;
/* On the outgoing stack all values are aligned to 8 */
/* there are 8 64bit floating point registers */
if (nf < 8)
{
avalue[i] = pfr;
nf++;
pfr++;
}
else
{
if (((long) pst) & 4)
pst++;
avalue[i] = pst;
pst += 2;
}
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
goto do_struct;
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
{ /* Test if for the whole long double, 4 gprs are available.
otherwise the stuff ends up on the stack. */
if (ng < 5)
{
avalue[i] = pgr;
pgr += 4;
ng += 4;
}
else
{
avalue[i] = pst;
pst += 4;
ng = 8;
}
break;
}
if (nf < 7)
{
avalue[i] = pfr;
pfr += 2;
nf += 2;
}
else
{
if (((long) pst) & 4)
pst++;
avalue[i] = pst;
pst += 4;
nf = 8;
}
break;
#endif
default:
FFI_ASSERT (0);
FFI_ASSERT (0);
}
i++;
@ -1263,39 +1321,9 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
already used and we never have a struct with size zero. That is the reason
for the subtraction of 1. See the comment in ffitarget.h about ordering.
*/
if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
&& size <= 8)
if (cif->abi == FFI_SYSV && rtypenum == FFI_TYPE_STRUCT && size <= 8)
return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
return FFI_TYPE_STRUCT;
#endif
/* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
respectivley UINT64. */
if (cif->abi == FFI_LINUX_SOFT_FLOAT)
{
switch (cif->rtype->type)
{
case FFI_TYPE_FLOAT:
return FFI_TYPE_UINT32;
break;
case FFI_TYPE_DOUBLE:
return FFI_TYPE_UINT64;
break;
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
return FFI_TYPE_UINT128;
break;
#endif
default:
return cif->rtype->type;
}
}
else
{
return cif->rtype->type;
}
return rtypenum;
}
int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,

View File

@ -1,6 +1,8 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for PowerPC.
Permission is hereby granted, free of charge, to any person obtaining
@ -28,6 +30,10 @@
#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 ----------------------------------- */
#if defined (POWERPC) && defined (__powerpc64__) /* linux64 */
@ -60,18 +66,14 @@ typedef enum ffi_abi {
FFI_LINUX64,
FFI_LINUX,
FFI_LINUX_SOFT_FLOAT,
# ifdef POWERPC64
# if defined(POWERPC64)
FFI_DEFAULT_ABI = FFI_LINUX64,
# else
# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
FFI_DEFAULT_ABI = FFI_LINUX,
# else
# ifdef __NO_FPRS__
# elif defined(__NO_FPRS__)
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT,
# else
# elif (__LDBL_MANT_DIG__ == 106)
FFI_DEFAULT_ABI = FFI_LINUX,
# else
FFI_DEFAULT_ABI = FFI_GCC_SYSV,
# endif
# endif
# endif
#endif

View File

@ -122,22 +122,41 @@ ENTRY(ffi_closure_SYSV)
blr
# case FFI_TYPE_FLOAT
#ifndef __NO_FPRS__
lfs %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
#else
nop
nop
nop
#endif
blr
# case FFI_TYPE_DOUBLE
#ifndef __NO_FPRS__
lfd %f1,112+0(%r1)
mtlr %r0
addi %r1,%r1,144
#else
nop
nop
nop
#endif
blr
# case FFI_TYPE_LONGDOUBLE
#ifndef __NO_FPRS__
lfd %f1,112+0(%r1)
lfd %f2,112+8(%r1)
mtlr %r0
b .Lfinish
#else
nop
nop
nop
blr
#endif
# case FFI_TYPE_UINT8
lbz %r3,112+3(%r1)

View File

@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV)
nop
1:
#ifndef __NO_FPRS__
/* Load all the FP registers. */
bf- 6,2f
lfd %f1,-16-(8*4)-(8*8)(%r28)
@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV)
lfd %f6,-16-(8*4)-(3*8)(%r28)
lfd %f7,-16-(8*4)-(2*8)(%r28)
lfd %f8,-16-(8*4)-(1*8)(%r28)
#endif
2:
/* Make the call. */
@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV)
mtcrf 0x01,%r31 /* cr7 */
bt- 31,L(small_struct_return_value)
bt- 30,L(done_return_value)
#ifndef __NO_FPRS__
bt- 29,L(fp_return_value)
#endif
stw %r3,0(%r30)
bf+ 28,L(done_return_value)
stw %r4,4(%r30)
@ -124,6 +128,7 @@ L(done_return_value):
lwz %r1,0(%r1)
blr
#ifndef __NO_FPRS__
L(fp_return_value):
bf 28,L(float_return_value)
stfd %f1,0(%r30)
@ -134,21 +139,17 @@ L(fp_return_value):
L(float_return_value):
stfs %f1,0(%r30)
b L(done_return_value)
#endif
L(small_struct_return_value):
extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */
mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */
extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */
subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */
bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */
/* smst_one_register: */
slw %r3,%r3,%r5 /* Left-justify value in r3 */
mtxer %r6 /* move byte count to XER ... */
stswx %r3,0,%r30 /* ... and store that many bytes */
bf+ 26,L(done_return_value) /* struct in r3:r4 ? */
add %r6,%r6,%r30 /* adjust pointer */
stswi %r4,%r6,4 /* store last four bytes */
b L(done_return_value)
/*
* The C code always allocates a properly-aligned 8-byte bounce
* buffer to make this assembly code very simple. Just write out
* r3 and r4 to the buffer to allow the C code to handle the rest.
*/
stw %r3, 0(%r30)
stw %r4, 4(%r30)
b L(done_return_value)
.LFE1:
END(ffi_call_SYSV)

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
prep_cif.c - Copyright (c) 2011, 2012 Anthony Green
Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@ -37,17 +38,21 @@ static ffi_status initialize_aggregate(ffi_type *arg)
{
ffi_type **ptr;
FFI_ASSERT(arg != NULL);
if (UNLIKELY(arg == NULL || arg->elements == NULL))
return FFI_BAD_TYPEDEF;
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
FFI_ASSERT(arg->alignment == 0);
arg->size = 0;
arg->alignment = 0;
ptr = &(arg->elements[0]);
if (UNLIKELY(ptr == 0))
return FFI_BAD_TYPEDEF;
while ((*ptr) != NULL)
{
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
if (UNLIKELY(((*ptr)->size == 0)
&& (initialize_aggregate((*ptr)) != FFI_OK)))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
@ -85,24 +90,38 @@ static ffi_status initialize_aggregate(ffi_type *arg)
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
ffi_type *rtype, ffi_type **atypes)
/* For non variadic functions isvariadic should be 0 and
nfixedargs==ntotalargs.
For variadic calls, isvariadic should be 1 and nfixedargs
and ntotalargs set as appropriate. nfixedargs must always be >=1 */
ffi_status FFI_HIDDEN 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)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
FFI_ASSERT(nfixedargs <= ntotalargs);
#ifndef X86_WIN32
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))
return FFI_BAD_ABI;
#else
FFI_ASSERT(abi > FFI_FIRST_ABI && abi <= FFI_DEFAULT_ABI
|| abi == FFI_THISCALL);
if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
return FFI_BAD_ABI;
#endif
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->nargs = ntotalargs;
cif->rtype = rtype;
cif->flags = 0;
@ -115,7 +134,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA
#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC
@ -136,7 +155,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if !defined __i386__ && !defined __x86_64__ && !defined S390 && !defined PA
#if !defined X86_ANY && !defined S390 && !defined PA
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
@ -158,10 +177,31 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
cif->bytes = bytes;
/* Perform machine dependent cif processing */
#ifdef FFI_TARGET_SPECIFIC_VARIADIC
if (isvariadic)
return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs);
#endif
return ffi_prep_cif_machdep(cif);
}
#endif /* not __CRIS__ */
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
ffi_type *rtype, ffi_type **atypes)
{
return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, 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)
{
return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes);
}
#if FFI_CLOSURES
ffi_status

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for S390.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
#if defined (__s390x__)
#ifndef S390X
#define S390X
@ -42,8 +47,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for SuperH.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
@ -36,8 +41,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#endif

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for SuperH - SHmedia.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
@ -36,8 +41,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi;
#define FFI_EXTRA_CIF_FIELDS long long flags2

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 2003, 2004, 2007, 2008 Red Hat, Inc.
ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
SPARC Foreign Function Interface
@ -406,8 +407,50 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
/* We don't yet support calling 32bit code from 64bit */
FFI_ASSERT(0);
#else
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
cif->flags, rvalue, fn);
if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| cif->flags == FFI_TYPE_LONGDOUBLE
#endif
))
{
/* For v8, we need an "unimp" with size of returning struct */
/* behind "call", so we alloc some executable space for it. */
/* l7 is used, we need to make sure v8.S doesn't use %l7. */
unsigned int *call_struct = NULL;
ffi_closure_alloc(32, &call_struct);
if (call_struct)
{
unsigned long f = (unsigned long)fn;
call_struct[0] = 0xae10001f; /* mov %i7, %l7 */
call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */
call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */
call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */
call_struct[4] = 0x01000000; /* nop */
if (cif->rtype->size < 0x7f)
call_struct[5] = cif->rtype->size; /* unimp */
else
call_struct[5] = 0x01000000; /* nop */
call_struct[6] = 0x81c7e008; /* ret */
call_struct[7] = 0xbe100017; /* mov %l7, %i7 */
asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : :
"r" (call_struct) : "memory");
/* SPARC v8 requires 5 instructions for flush to be visible */
asm volatile ("nop; nop; nop; nop; nop");
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
cif->flags, rvalue, call_struct);
ffi_closure_free(call_struct);
}
else
{
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
cif->flags, rvalue, fn);
}
}
else
{
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes,
cif->flags, rvalue, fn);
}
#endif
break;
case FFI_V9:
@ -425,7 +468,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
FFI_ASSERT(0);
break;
}
}
@ -447,7 +489,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
#ifdef SPARC64
/* Trampoline address is equal to the closure address. We take advantage
of that to reduce the trampoline size by 8 bytes. */
FFI_ASSERT (cif->abi == FFI_V9);
if (cif->abi != FFI_V9)
return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_v9;
tramp[0] = 0x83414000; /* rd %pc, %g1 */
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
@ -456,7 +499,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
*((unsigned long *) &tramp[4]) = fn;
#else
unsigned long ctx = (unsigned long) codeloc;
FFI_ASSERT (cif->abi == FFI_V8);
if (cif->abi != FFI_V8)
return FFI_BAD_ABI;
fn = (unsigned long) ffi_closure_v8;
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
@ -468,13 +512,13 @@ ffi_prep_closure_loc (ffi_closure* closure,
closure->fun = fun;
closure->user_data = user_data;
/* Flush the Icache. FIXME: alignment isn't certain, assume 8 bytes */
/* Flush the Icache. closure is 8 bytes aligned. */
#ifdef SPARC64
asm volatile ("flush %0" : : "r" (closure) : "memory");
asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory");
#else
asm volatile ("iflush %0" : : "r" (closure) : "memory");
asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory");
asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory");
/* SPARC v8 requires 5 instructions for flush to be visible */
asm volatile ("nop; nop; nop; nop; nop");
#endif
return FFI_OK;

View File

@ -1,5 +1,6 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for SPARC.
Permission is hereby granted, free of charge, to any person obtaining
@ -27,6 +28,10 @@
#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 ----------------------------------- */
#if defined(__arch64__) || defined(__sparcv9)
@ -44,12 +49,12 @@ typedef enum ffi_abi {
FFI_V8,
FFI_V8PLUS,
FFI_V9,
FFI_LAST_ABI,
#ifdef SPARC64
FFI_DEFAULT_ABI = FFI_V9,
FFI_DEFAULT_ABI = FFI_V9
#else
FFI_DEFAULT_ABI = FFI_V8,
FFI_DEFAULT_ABI = FFI_V8
#endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif

View File

@ -32,7 +32,7 @@
/* Only compile this in for 64bit builds, because otherwise the object file
will have inproper architecture due to used instructions. */
#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */
#define STACKFRAME 128 /* Minimum stack framesize for SPARC */
#define STACK_BIAS 2047
#define ARGS (128) /* Offset of register area in frame */

View File

@ -228,12 +228,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
switch (cif->rtype->type)
{
case FFI_TYPE_VOID:
#if defined(X86) || defined (X86_WIN32) || defined(X86_FREEBSD) || defined(X86_DARWIN) || defined(X86_WIN64)
case FFI_TYPE_UINT8:
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16:
#endif
#ifdef X86_WIN64
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
@ -364,27 +362,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{
#ifdef X86_WIN64
case FFI_WIN64:
{
/* Make copies of all struct arguments
NOTE: not sure if responsibility should be here or in caller */
unsigned int i;
for (i=0; i < cif->nargs;i++) {
size_t size = cif->arg_types[i]->size;
if ((cif->arg_types[i]->type == FFI_TYPE_STRUCT
&& (size != 1 && size != 2 && size != 4 && size != 8))
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|| cif->arg_types[i]->type == FFI_TYPE_LONGDOUBLE
#endif
)
{
void *local = alloca(size);
memcpy(local, avalue[i], size);
avalue[i] = local;
}
}
ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
}
ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
#elif defined(X86_WIN32)
case FFI_SYSV:
@ -447,8 +426,6 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
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 *)
@ -616,7 +593,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
{ 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 int __dis = __fun - (__ctx + 22); \
unsigned short __size = (unsigned short)(SIZE); \
*(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
*(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
@ -722,9 +699,6 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
int i;
if (cif->abi != FFI_SYSV) {
#ifdef X86_WIN32
if (cif->abi != FFI_THISCALL)
#endif
return FFI_BAD_ABI;
}
@ -739,20 +713,10 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
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;
@ -797,7 +761,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
#ifdef X86_WIN32
case FFI_SYSV:
case FFI_STDCALL:
ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
ecif.rvalue, fn);
break;
case FFI_THISCALL:
@ -825,7 +789,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
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,
ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
ecif.rvalue, fn);
}
break;

View File

@ -1,7 +1,8 @@
/* -----------------------------------------------------------------------
ffi64.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
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
@ -426,7 +427,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
/* If the return value is passed in memory, add the pointer as the
first integer argument. */
if (ret_in_memory)
reg_args->gpr[gprcount++] = (long) rvalue;
reg_args->gpr[gprcount++] = (unsigned long) rvalue;
avn = cif->nargs;
arg_types = cif->arg_types;
@ -498,12 +499,21 @@ ffi_prep_closure_loc (ffi_closure* closure,
{
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 */
*(void * volatile *) &tramp[1] = ffi_closure_unix64;
*((unsigned long long * volatile) &tramp[1])
= (unsigned long) ffi_closure_unix64;
tramp[5] = 0xba49; /* mov <data>, %r10 */
*(void * volatile *) &tramp[6] = codeloc;
*((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. */
@ -542,7 +552,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
{
/* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */
rvalue = (void *) reg_args->gpr[gprcount++];
rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++];
/* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID;
}

View File

@ -1,6 +1,7 @@
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003, 2010 Red Hat, Inc.
Copyright (C) 2008 Free Software Foundation, Inc.
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.
@ -29,8 +30,15 @@
#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
@ -53,9 +61,15 @@ typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#endif
#else
#if defined __x86_64__ && !defined __LP64__
#define FFI_SIZEOF_ARG 8
typedef unsigned long long ffi_arg;
typedef long long ffi_sarg;
#else
typedef unsigned long ffi_arg;
typedef signed long ffi_sarg;
#endif
#endif
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
@ -66,28 +80,26 @@ typedef enum ffi_abi {
FFI_STDCALL,
FFI_THISCALL,
FFI_FASTCALL,
FFI_LAST_ABI,
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV,
#endif
FFI_DEFAULT_ABI = FFI_SYSV
#ifdef X86_WIN64
#elif defined(X86_WIN64)
FFI_WIN64,
FFI_DEFAULT_ABI = FFI_WIN64,
#else
FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_WIN64
#else
/* ---- Intel x86 and AMD x86-64 - */
#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__) || defined(__i386) || defined(__amd64))
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,
FFI_DEFAULT_ABI = FFI_SYSV
#else
FFI_DEFAULT_ABI = FFI_UNIX64,
FFI_DEFAULT_ABI = FFI_UNIX64
#endif
#endif
#endif /* X86_WIN64 */
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif

View File

@ -264,18 +264,6 @@ ffi_closure_SYSV ENDP
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
ffi_closure_raw_THISCALL PROC NEAR
push ebp
mov ebp, esp
push esi
sub esp, 36
mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
mov [esp + 12], edx
lea edx, [ebp + 12], edx
jmp stubraw
ffi_closure_raw_SYSV ENDP
ffi_closure_raw_SYSV PROC NEAR USES esi
;; the ffi_closure ctx is passed in eax by the trampoline.
@ -284,7 +272,6 @@ ffi_closure_raw_SYSV PROC NEAR USES esi
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
mov [esp + 12], edx ;; user_data
lea edx, [ebp + 8]
stubraw:
mov [esp + 8], edx ;; raw_args
lea edx, [ebp - 24]
mov [esp + 4], edx ;; &res
@ -735,21 +722,7 @@ _ffi_closure_SYSV:
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20
.balign 16
.globl _ffi_closure_raw_THISCALL
#ifndef __OS2__
.def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef
#endif
_ffi_closure_raw_THISCALL:
pushl %ebp
movl %esp, %ebp
pushl %esi
subl $36, %esp
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
movl %edx, 12(%esp) /* user_data */
leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */
jmp .stubraw
# This assumes we are using gas.
.balign 16
.globl _ffi_closure_raw_SYSV
@ -769,7 +742,6 @@ _ffi_closure_raw_SYSV:
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
movl %edx, 12(%esp) /* user_data */
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
.stubraw:
movl %edx, 8(%esp) /* raw_args */
leal -24(%ebp), %edx
movl %edx, 4(%esp) /* &res */

View File

@ -232,10 +232,18 @@ ret_void$:
ffi_call_win64 ENDP
_TEXT ENDS
END
#else
#else
#ifdef SYMBOL_UNDERSCORE
#define SYMBOL_NAME(name) _##name
#else
#define SYMBOL_NAME(name) name
#endif
.text
.extern _ffi_closure_win64_inner
.extern SYMBOL_NAME(ffi_closure_win64_inner)
# ffi_closure_win64 will be called with these registers set:
# rax points to 'closure'
@ -246,8 +254,8 @@ END
# call ffi_closure_win64_inner for the actual work, then return the result.
#
.balign 16
.globl _ffi_closure_win64
_ffi_closure_win64:
.globl SYMBOL_NAME(ffi_closure_win64)
SYMBOL_NAME(ffi_closure_win64):
# copy register arguments onto stack
test $1,%r11
jne .Lfirst_is_float
@ -287,7 +295,7 @@ _ffi_closure_win64:
mov %rax, %rcx # context is first parameter
mov %rsp, %rdx # stack is second parameter
add $48, %rdx # point to start of arguments
mov $_ffi_closure_win64_inner, %rax
mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax
callq *%rax # call the real closure function
add $40, %rsp
movq %rax, %xmm0 # If the closure returned a float,
@ -296,8 +304,8 @@ _ffi_closure_win64:
.ffi_closure_win64_end:
.balign 16
.globl _ffi_call_win64
_ffi_call_win64:
.globl SYMBOL_NAME(ffi_call_win64)
SYMBOL_NAME(ffi_call_win64):
# copy registers onto stack
mov %r9,32(%rsp)
mov %r8,24(%rsp)

View File

@ -37,7 +37,8 @@ int main (void)
arg_types[1] = &ffi_type_double;
arg_types[2] = NULL;
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
/* 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;
@ -49,6 +50,9 @@ int main (void)
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);

View File

@ -37,7 +37,8 @@ int main (void)
arg_types[1] = &ffi_type_longdouble;
arg_types[2] = NULL;
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
/* 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;
@ -49,6 +50,10 @@ int main (void)
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);

View File

@ -4,7 +4,8 @@
PR: none.
Originator: Blake Chaffin 6/6/2007 */
/* { dg-do run { xfail *-*-* } } */
/* { dg-do run } */
#include "ffitest.h"
static void

View File

@ -4,7 +4,8 @@
PR: none.
Originator: Blake Chaffin 6/6/2007 */
/* { dg-do run { xfail *-*-* } } */
/* { dg-do run } */
#include "ffitest.h"
int main (void)

View File

@ -0,0 +1,107 @@
/* Area: fp and variadics
Purpose: check fp inputs and returns work on variadics, even the fixed params
Limitations: None
PR: none
Originator: <david.gilbert@linaro.org> 2011-01-25
Intended to stress the difference in ABI on ARM vfp
*/
/* { dg-do run } */
#include <stdarg.h>
#include "ffitest.h"
/* prints out all the parameters, and returns the sum of them all.
* 'x' is the number of variadic parameters all of which are double in this test
*/
double float_va_fn(unsigned int x, double y,...)
{
double total=0.0;
va_list ap;
unsigned int i;
total+=(double)x;
total+=y;
printf("%u: %.1lf :", x, y);
va_start(ap, y);
for(i=0;i<x;i++)
{
double arg=va_arg(ap, double);
total+=arg;
printf(" %d:%.1lf ", i, arg);
}
va_end(ap);
printf(" total: %.1lf\n", total);
return total;
}
int main (void)
{
ffi_cif cif;
ffi_type *arg_types[5];
void *values[5];
double doubles[5];
unsigned int firstarg;
double resfp;
/* First test, pass float_va_fn(0,2.0) - note there are no actual
* variadic parameters, but it's declared variadic so the ABI may be
* different. */
/* Call it statically and then via ffi */
resfp=float_va_fn(0,2.0);
// { dg-output "0: 2.0 : total: 2.0" }
printf("compiled: %.1lf\n", resfp);
// { dg-output "\ncompiled: 2.0" }
arg_types[0] = &ffi_type_uint;
arg_types[1] = &ffi_type_double;
arg_types[2] = NULL;
CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 2,
&ffi_type_double, arg_types) == FFI_OK);
firstarg = 0;
doubles[0] = 2.0;
values[0] = &firstarg;
values[1] = &doubles[0];
ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
// { dg-output "\n0: 2.0 : total: 2.0" }
printf("ffi: %.1lf\n", resfp);
// { dg-output "\nffi: 2.0" }
/* Second test, float_va_fn(2,2.0,3.0,4.0), now with variadic params */
/* Call it statically and then via ffi */
resfp=float_va_fn(2,2.0,3.0,4.0);
// { dg-output "\n2: 2.0 : 0:3.0 1:4.0 total: 11.0" }
printf("compiled: %.1lf\n", resfp);
// { dg-output "\ncompiled: 11.0" }
arg_types[0] = &ffi_type_uint;
arg_types[1] = &ffi_type_double;
arg_types[2] = &ffi_type_double;
arg_types[3] = &ffi_type_double;
arg_types[4] = NULL;
CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 2, 4,
&ffi_type_double, arg_types) == FFI_OK);
firstarg = 2;
doubles[0] = 2.0;
doubles[1] = 3.0;
doubles[2] = 4.0;
values[0] = &firstarg;
values[1] = &doubles[0];
values[2] = &doubles[1];
values[3] = &doubles[2];
ffi_call(&cif, FFI_FN(float_va_fn), &resfp, values);
// { dg-output "\n2: 2.0 : 0:3.0 1:4.0 total: 11.0" }
printf("ffi: %.1lf\n", resfp);
// { dg-output "\nffi: 11.0" }
exit(0);
}

View File

@ -30,7 +30,7 @@ int main (void)
sc < (signed char) 127; sc++)
{
ffi_call(&cif, FFI_FN(return_sc), &rint, values);
CHECK(rint == (ffi_arg) sc);
CHECK((signed char)rint == sc);
}
exit(0);
}