Commit 34fa7690 by Anthony Green

Merge upstream libffi

From-SVN: r184897
parent 8b59af5c
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 Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the 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 ...@@ -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 permit persons to whom the Software is furnished to do so, subject to
the following conditions: the following conditions:
The above copyright notice and this permission notice shall be included The above copyright notice and this permission notice shall be
in all copies or substantial portions of the Software. included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
OTHER DEALINGS IN THE SOFTWARE. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This directory contains the libffi package, which is not part of GCC but
shipped with GCC as convenience.
Status 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/>. page for updates: <URL:http://sourceware.org/libffi/>.
...@@ -46,7 +43,7 @@ Libffi has been ported to many different platforms. ...@@ -46,7 +43,7 @@ Libffi has been ported to many different platforms.
For specific configuration details and testing status, please For specific configuration details and testing status, please
refer to the wiki page here: 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 At the time of release, the following basic configurations have been
tested: tested:
...@@ -55,13 +52,18 @@ tested: ...@@ -55,13 +52,18 @@ tested:
| Architecture | Operating System | | Architecture | Operating System |
|--------------+------------------| |--------------+------------------|
| Alpha | Linux | | Alpha | Linux |
| Alpha | Tru64 |
| ARM | Linux | | ARM | Linux |
| ARM | iOS |
| AVR32 | Linux | | AVR32 | Linux |
| HPPA | HPUX | | HPPA | HPUX |
| IA-64 | Linux | | IA-64 | Linux |
| M68K | RTEMS |
| MIPS | IRIX | | MIPS | IRIX |
| MIPS | Linux | | MIPS | Linux |
| MIPS | RTEMS |
| MIPS64 | Linux | | MIPS64 | Linux |
| PowerPC | AMIGA |
| PowerPC | Linux | | PowerPC | Linux |
| PowerPC | Mac OSX | | PowerPC | Mac OSX |
| PowerPC | FreeBSD | | PowerPC | FreeBSD |
...@@ -73,8 +75,10 @@ tested: ...@@ -73,8 +75,10 @@ tested:
| SPARC64 | Linux | | SPARC64 | Linux |
| SPARC64 | FreeBSD | | SPARC64 | FreeBSD |
| X86 | FreeBSD | | X86 | FreeBSD |
| X86 | Interix |
| X86 | kFreeBSD | | X86 | kFreeBSD |
| X86 | Linux | | X86 | Linux |
| X86 | Linux/x32 |
| X86 | Mac OSX | | X86 | Mac OSX |
| X86 | OpenBSD | | X86 | OpenBSD |
| X86 | OS/2 | | X86 | OS/2 |
...@@ -84,6 +88,7 @@ tested: ...@@ -84,6 +88,7 @@ tested:
| X86-64 | FreeBSD | | X86-64 | FreeBSD |
| X86-64 | Linux | | X86-64 | Linux |
| X86-64 | OpenBSD | | X86-64 | OpenBSD |
| X86-64 | Windows/MingW |
|--------------+------------------| |--------------+------------------|
Please send additional platform test results to Please send additional platform test results to
...@@ -115,9 +120,15 @@ It's also possible to build libffi on Windows platforms with ...@@ -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 Microsoft's Visual C++ compiler. In this case, use the msvcc.sh
wrapper script during configuration like so: wrapper script during configuration like so:
path/to/configure --enable-shared --enable-static \ path/to/configure CC=path/to/msvcc.sh LD=link CPP=\"cl -nologo -EP\"
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. Configure has many other options. Use "configure --help" to see them all.
...@@ -135,11 +146,27 @@ History ...@@ -135,11 +146,27 @@ History
See the ChangeLog files for details. 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. Fix the N64 build on mips-sgi-irix6.5.
Testsuite fixes for Tru64 Unix.
Enable builds with Microsoft's compiler. 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 3.0.9 Dec-31-09
Add AVR32 and win64 ports. Add ARM softfp support. Add AVR32 and win64 ports. Add ARM softfp support.
...@@ -320,5 +347,6 @@ Alex Oliva solved the executable page problem for SElinux. ...@@ -320,5 +347,6 @@ Alex Oliva solved the executable page problem for SElinux.
The list above is almost certainly incomplete and inaccurate. I'm The list above is almost certainly incomplete and inaccurate. I'm
happy to make corrections or additions upon request. happy to make corrections or additions upon request.
If you have a problem, or have found a bug, please send a note to If you have a problem, or have found a bug, please send a note to the
green@redhat.com. author at green@moxielogic.com, or the project mailing list at
libffi-discuss@sourceware.org.
#!/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"
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
This manual is for Libffi, a portable foreign-function interface This manual is for Libffi, a portable foreign-function interface
library. library.
Copyright @copyright{} 2008, 2010 Red Hat, Inc. Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc.
@quotation @quotation
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
...@@ -133,8 +133,6 @@ This initializes @var{cif} according to the given parameters. ...@@ -133,8 +133,6 @@ This initializes @var{cif} according to the given parameters.
you want. @ref{Multiple ABIs} for more information. you want. @ref{Multiple ABIs} for more information.
@var{nargs} is the number of arguments that this function accepts. @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 @var{rtype} is a pointer to an @code{ffi_type} structure that
describes the return type of the function. @xref{Types}. 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 ...@@ -150,6 +148,30 @@ objects is incorrect; or @code{FFI_BAD_ABI} if the @var{abi} parameter
is invalid. is invalid.
@end defun @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 To call a function using an initialized @code{ffi_cif}, use the
@code{ffi_call} function: @code{ffi_call} function:
...@@ -171,7 +193,9 @@ discarded. ...@@ -171,7 +193,9 @@ discarded.
@var{avalues} is a vector of @code{void *} pointers that point to the @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} 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), 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 @end defun
...@@ -570,9 +594,7 @@ support for these. ...@@ -570,9 +594,7 @@ support for these.
@itemize @bullet @itemize @bullet
@item @item
There is no support for calling varargs functions. This may work on Variadic closures.
some platforms, depending on how the ABI is defined, but it is not
reliable.
@item @item
There is no support for bit fields in structures. There is no support for bit fields in structures.
...@@ -589,6 +611,8 @@ The ``raw'' API is undocumented. ...@@ -589,6 +611,8 @@ The ``raw'' API is undocumented.
@c anything else? @c anything else?
@end itemize @end itemize
Note that variadic support is very new and tested on a relatively
small number of platforms.
@node Index @node Index
@unnumbered Index @unnumbered Index
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
/* Define this if you want extra debugging. */ /* Define this if you want extra debugging. */
#undef FFI_DEBUG #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 */ /* Cannot use malloc on this target, so, we revert to alternative means */
#undef FFI_MMAP_EXEC_WRIT #undef FFI_MMAP_EXEC_WRIT
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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 Permission is hereby granted, free of charge, to any person
a copy of this software and associated documentation files (the obtaining a copy of this software and associated documentation
``Software''), to deal in the Software without restriction, including files (the ``Software''), to deal in the Software without
without limitation the rights to use, copy, modify, merge, publish, restriction, including without limitation the rights to use, copy,
distribute, sublicense, and/or sell copies of the Software, and to modify, merge, publish, distribute, sublicense, and/or sell copies
permit persons to whom the Software is furnished to do so, subject to of the Software, and to permit persons to whom the Software is
the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included The above copyright notice and this permission notice shall be
in all copies or substantial portions of the Software. included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
...@@ -77,15 +78,31 @@ extern "C" { ...@@ -77,15 +78,31 @@ extern "C" {
/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). /* 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 But we can find it either under the correct ANSI name, or under GNU
C's internal name. */ C's internal name. */
#define FFI_64_BIT_MAX 9223372036854775807
#ifdef LONG_LONG_MAX #ifdef LONG_LONG_MAX
# define FFI_LONG_LONG_MAX LONG_LONG_MAX # define FFI_LONG_LONG_MAX LONG_LONG_MAX
#else #else
# ifdef LLONG_MAX # ifdef LLONG_MAX
# define FFI_LONG_LONG_MAX 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 # else
# ifdef __GNUC__ # ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ # define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif # 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
#endif #endif
...@@ -132,17 +149,17 @@ typedef struct _ffi_type ...@@ -132,17 +149,17 @@ typedef struct _ffi_type
#endif #endif
#if LONG_MAX == 2147483647 #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" #error "no 64-bit data type supported"
# endif # endif
#elif LONG_MAX != 9223372036854775807 #elif LONG_MAX != FFI_64_BIT_MAX
#error "long size not supported" #error "long size not supported"
#endif #endif
#if LONG_MAX == 2147483647 #if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32 # define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32 # 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_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64 # define ffi_type_slong ffi_type_sint64
#else #else
...@@ -190,12 +207,21 @@ typedef struct { ...@@ -190,12 +207,21 @@ typedef struct {
#endif #endif
} ffi_cif; } 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 -------------------------------------- */ /* ---- Definitions for the raw API -------------------------------------- */
#ifndef FFI_SIZEOF_ARG #ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647 # if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4 # define FFI_SIZEOF_ARG 4
# elif LONG_MAX == 9223372036854775807 # elif LONG_MAX == FFI_64_BIT_MAX
# define FFI_SIZEOF_ARG 8 # define FFI_SIZEOF_ARG 8
# endif # endif
#endif #endif
...@@ -265,6 +291,9 @@ typedef struct { ...@@ -265,6 +291,9 @@ typedef struct {
} ffi_closure __attribute__((aligned (8))); } ffi_closure __attribute__((aligned (8)));
#else #else
} ffi_closure; } ffi_closure;
# ifdef __sgi
# pragma pack 0
# endif
#endif #endif
void *ffi_closure_alloc (size_t size, void **code); void *ffi_closure_alloc (size_t size, void **code);
...@@ -283,6 +312,9 @@ ffi_prep_closure_loc (ffi_closure*, ...@@ -283,6 +312,9 @@ ffi_prep_closure_loc (ffi_closure*,
void *user_data, void *user_data,
void*codeloc); void*codeloc);
#ifdef __sgi
# pragma pack 8
#endif
typedef struct { typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE]; char tramp[FFI_TRAMPOLINE_SIZE];
...@@ -361,6 +393,13 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ...@@ -361,6 +393,13 @@ ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_type *rtype, ffi_type *rtype,
ffi_type **atypes); 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 ffi_call(ffi_cif *cif,
void (*fn)(void), void (*fn)(void),
void *rvalue, void *rvalue,
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ffi_common.h - Copyright (C) 2011, 2012 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc Copyright (C) 2007 Free Software Foundation, Inc
Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building Common internal definitions and macros. Only necessary for building
libffi. libffi.
----------------------------------------------------------------------- */ ----------------------------------------------------------------------- */
...@@ -74,6 +75,8 @@ void ffi_type_test(ffi_type *a, char *file, int line); ...@@ -74,6 +75,8 @@ void ffi_type_test(ffi_type *a, char *file, int line);
/* Perform machine dependent cif processing */ /* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif); 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 */ /* Extended cif, used in callback from assembly routine */
typedef struct typedef struct
...@@ -112,11 +115,14 @@ typedef signed int SINT64 __attribute__((__mode__(__DI__))); ...@@ -112,11 +115,14 @@ typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32; 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 #ifdef __cplusplus
} }
#endif #endif
#endif #endif
...@@ -16,6 +16,15 @@ libffi, -lffi ...@@ -16,6 +16,15 @@ libffi, -lffi
.Fa "ffi_type **atypes" .Fa "ffi_type **atypes"
.Fc .Fc
.Ft void .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 .Fo ffi_call
.Fa "ffi_cif *cif" .Fa "ffi_cif *cif"
.Fa "void (*fn)(void)" .Fa "void (*fn)(void)"
...@@ -28,4 +37,5 @@ generate a call to another function at runtime without requiring knowledge of ...@@ -28,4 +37,5 @@ generate a call to another function at runtime without requiring knowledge of
the called function's interface at compile time. the called function's interface at compile time.
.Sh SEE ALSO .Sh SEE ALSO
.Xr ffi_prep_cif 3 , .Xr ffi_prep_cif 3 ,
.Xr ffi_prep_cif_var 3 ,
.Xr ffi_call 3 .Xr ffi_call 3
...@@ -37,7 +37,9 @@ structs that describe the data type, size and alignment of each argument. ...@@ -37,7 +37,9 @@ structs that describe the data type, size and alignment of each argument.
points to an points to an
.Nm ffi_type .Nm ffi_type
that describes the data type, size and alignment of the 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 .Sh RETURN VALUES
Upon successful completion, Upon successful completion,
.Nm ffi_prep_cif .Nm ffi_prep_cif
...@@ -63,4 +65,6 @@ defined in ...@@ -63,4 +65,6 @@ defined in
. .
.Sh SEE ALSO .Sh SEE ALSO
.Xr ffi 3 , .Xr ffi 3 ,
.Xr ffi_call 3 .Xr ffi_call 3 ,
.Xr ffi_prep_cif_var 3
.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
...@@ -42,10 +42,11 @@ ...@@ -42,10 +42,11 @@
# format and translated into something sensible for cl or ml. # format and translated into something sensible for cl or ml.
# #
args="-nologo" args="-nologo -W3"
md=-MD md=-MD
cl="cl" cl="cl"
ml="ml" ml="ml"
safeseh="-safeseh"
output= output=
while [ $# -gt 0 ] while [ $# -gt 0 ]
...@@ -63,15 +64,28 @@ do ...@@ -63,15 +64,28 @@ do
-m64) -m64)
cl="cl" # "$MSVC/x86_amd64/cl" cl="cl" # "$MSVC/x86_amd64/cl"
ml="ml64" # "$MSVC/x86_amd64/ml64" ml="ml64" # "$MSVC/x86_amd64/ml64"
safeseh=
shift 1
;;
-O0)
args="$args -Od"
shift 1 shift 1
;; ;;
-O*) -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 shift 1
;; ;;
-g) -g)
# Can't specify -RTC1 or -Zi in opt. -Gy is ok. Use -OPT:REF? # Enable debug symbol generation.
args="$args -D_DEBUG -RTC1 -Zi" 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 md=-MDd
shift 1 shift 1
;; ;;
...@@ -108,8 +122,8 @@ do ...@@ -108,8 +122,8 @@ do
shift 1 shift 1
;; ;;
-Wall) -Wall)
# -Wall on MSVC is overzealous. Use -W3 instead. # -Wall on MSVC is overzealous, and we already build with -W3. Nothing
args="$args -W3" # to do here.
shift 1 shift 1
;; ;;
-Werror) -Werror)
...@@ -164,7 +178,7 @@ if [ -n "$assembly" ]; then ...@@ -164,7 +178,7 @@ if [ -n "$assembly" ]; then
echo "$cl -nologo -EP $includes $defines $src > $ppsrc" echo "$cl -nologo -EP $includes $defines $src > $ppsrc"
"$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $? "$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $?
output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')" output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')"
args="-nologo -safeseh $single $output $ppsrc" args="-nologo $safeseh $single $output $ppsrc"
echo "$ml $args" echo "$ml $args"
eval "\"$ml\" $args" eval "\"$ml\" $args"
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 Alpha Foreign Function Interface
...@@ -178,6 +179,9 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -178,6 +179,9 @@ ffi_prep_closure_loc (ffi_closure* closure,
{ {
unsigned int *tramp; unsigned int *tramp;
if (cif->abi != FFI_OSF)
return FFI_BAD_ABI;
tramp = (unsigned int *) &closure->tramp[0]; tramp = (unsigned int *) &closure->tramp[0];
tramp[0] = 0x47fb0401; /* mov $27,$1 */ tramp[0] = 0x47fb0401; /* mov $27,$1 */
tramp[1] = 0xa77b0010; /* ldq $27,16($27) */ tramp[1] = 0xa77b0010; /* ldq $27,16($27) */
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for Alpha.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifndef LIBFFI_ASM
typedef unsigned long ffi_arg; typedef unsigned long ffi_arg;
typedef signed long ffi_sarg; typedef signed long ffi_sarg;
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (c) 2010 CodeSourcery Copyright (c) 2010 CodeSourcery
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for ARM. Target configuration macros for ARM.
...@@ -29,6 +30,10 @@ ...@@ -29,6 +30,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifndef LIBFFI_ASM
typedef unsigned long ffi_arg; typedef unsigned long ffi_arg;
typedef signed long ffi_sarg; typedef signed long ffi_sarg;
...@@ -55,6 +60,8 @@ typedef enum ffi_abi { ...@@ -55,6 +60,8 @@ typedef enum ffi_abi {
#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1) #define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1)
#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2) #define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2)
#define FFI_TARGET_SPECIFIC_VARIADIC
/* ---- Definitions for closures ----------------------------------------- */ /* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1 #define FFI_CLOSURES 1
...@@ -62,4 +69,3 @@ typedef enum ffi_abi { ...@@ -62,4 +69,3 @@ typedef enum ffi_abi {
#define FFI_NATIVE_RAW_API 0 #define FFI_NATIVE_RAW_API 0
#endif #endif
#!/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
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 ARM Foreign Function Interface
...@@ -39,7 +40,11 @@ ...@@ -39,7 +40,11 @@
#else #else
#define CNAME(x) x #define CNAME(x) x
#endif #endif
#ifdef __APPLE__
#define ENTRY(x) .globl CNAME(x); CNAME(x):
#else
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
#endif /* __APPLE__ */
#endif #endif
#ifdef __ELF__ #ifdef __ELF__
...@@ -48,6 +53,12 @@ ...@@ -48,6 +53,12 @@
#define LSYM(x) x #define LSYM(x) x
#endif #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 need a better way of testing for this, but for now, this is all
we can do. */ we can do. */
@ This selects the minimum architecture level required. @ This selects the minimum architecture level required.
...@@ -105,21 +116,33 @@ ...@@ -105,21 +116,33 @@
.align 0 .align 0
.thumb .thumb
.thumb_func .thumb_func
#ifdef __APPLE__
ENTRY($0)
#else
ENTRY(\name) ENTRY(\name)
#endif
bx pc bx pc
nop nop
.arm .arm
UNWIND .fnstart UNWIND .fnstart
/* A hook to tell gdb that we've switched to ARM mode. Also used to call /* A hook to tell gdb that we've switched to ARM mode. Also used to call
directly from other local arm routines. */ directly from other local arm routines. */
_L__\name: #ifdef __APPLE__
_L__$0:
#else
_L__\name:
#endif
.endm .endm
#else #else
.macro ARM_FUNC_START name .macro ARM_FUNC_START name
.text .text
.align 0 .align 0
.arm .arm
#ifdef __APPLE__
ENTRY($0)
#else
ENTRY(\name) ENTRY(\name)
#endif
UNWIND .fnstart UNWIND .fnstart
.endm .endm
#endif #endif
...@@ -141,8 +164,7 @@ _L__\name: ...@@ -141,8 +164,7 @@ _L__\name:
#endif #endif
.endm .endm
@ r0: ffi_prep_args
@ r0: fn
@ r1: &ecif @ r1: &ecif
@ r2: cif->bytes @ r2: cif->bytes
@ r3: fig->flags @ r3: fig->flags
...@@ -222,11 +244,18 @@ ARM_FUNC_START ffi_call_SYSV ...@@ -222,11 +244,18 @@ ARM_FUNC_START ffi_call_SYSV
#endif #endif
LSYM(Lepilogue): 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: .ffi_call_SYSV_end:
UNWIND .fnend UNWIND .fnend
#ifdef __ELF__
.size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
#endif
/* /*
...@@ -247,7 +276,7 @@ ARM_FUNC_START ffi_closure_SYSV ...@@ -247,7 +276,7 @@ ARM_FUNC_START ffi_closure_SYSV
sub sp, sp, #16 sub sp, sp, #16
str sp, [sp, #8] str sp, [sp, #8]
add r1, sp, #8 add r1, sp, #8
bl ffi_closure_SYSV_inner bl CNAME(ffi_closure_SYSV_inner)
cmp r0, #FFI_TYPE_INT cmp r0, #FFI_TYPE_INT
beq .Lretint beq .Lretint
...@@ -299,7 +328,9 @@ ARM_FUNC_START ffi_closure_SYSV ...@@ -299,7 +328,9 @@ ARM_FUNC_START ffi_closure_SYSV
.ffi_closure_SYSV_end: .ffi_closure_SYSV_end:
UNWIND .fnend UNWIND .fnend
#ifdef __ELF__
.size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
#endif
/* Below are VFP hard-float ABI call and closure implementations. /* Below are VFP hard-float ABI call and closure implementations.
...@@ -371,7 +402,7 @@ LSYM(Lbase_args): ...@@ -371,7 +402,7 @@ LSYM(Lbase_args):
@ assume no return value. @ assume no return value.
cmp r2, #0 cmp r2, #0
beq LSYM(Lepilogue_vfp) beq LSYM(Lepilogue_vfp)
cmp r3, #FFI_TYPE_INT cmp r3, #FFI_TYPE_INT
streq r0, [r2] streq r0, [r2]
beq LSYM(Lepilogue_vfp) beq LSYM(Lepilogue_vfp)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 AVR32 Foreign Function Interface
...@@ -394,7 +395,8 @@ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif, ...@@ -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 (*fun)(ffi_cif*, void*, void**, void*), void *user_data,
void *codeloc) 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 char *__tramp = (unsigned char*)(&closure->tramp[0]);
unsigned int __fun = (unsigned int)(&ffi_closure_SYSV); unsigned int __fun = (unsigned int)(&ffi_closure_SYSV);
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for AVR32.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifndef LIBFFI_ASM
typedef unsigned long ffi_arg; typedef unsigned long ffi_arg;
typedef signed long ffi_sarg; typedef signed long ffi_sarg;
...@@ -34,8 +39,8 @@ typedef signed long ffi_sarg; ...@@ -34,8 +39,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#endif #endif
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
closures.c - Copyright (c) 2007 Red Hat, Inc. closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc.
Copyright (C) 2007, 2009, 2010 Free Software Foundation, 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. Code to allocate and deallocate memory for closures.
...@@ -32,7 +33,7 @@ ...@@ -32,7 +33,7 @@
#include <ffi.h> #include <ffi.h>
#include <ffi_common.h> #include <ffi_common.h>
#ifndef FFI_MMAP_EXEC_WRIT #if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE
# if __gnu_linux__ # if __gnu_linux__
/* This macro indicates it may be forbidden to map anonymous memory /* This macro indicates it may be forbidden to map anonymous memory
with both write and execute permission. Code compiled when this with both write and execute permission. Code compiled when this
...@@ -63,7 +64,11 @@ ...@@ -63,7 +64,11 @@
#if FFI_CLOSURES #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_LOCKS 1
#define USE_DL_PREFIX 1 #define USE_DL_PREFIX 1
...@@ -167,7 +172,7 @@ selinux_enabled_check (void) ...@@ -167,7 +172,7 @@ selinux_enabled_check (void)
#endif /* !FFI_MMAP_EXEC_SELINUX */ #endif /* !FFI_MMAP_EXEC_SELINUX */
#elif defined (__CYGWIN__) #elif defined (__CYGWIN__) || defined(__INTERIX)
#include <sys/mman.h> #include <sys/mman.h>
...@@ -193,11 +198,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED; ...@@ -193,11 +198,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED;
static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED; static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
static void dlmalloc_stats(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. */ /* Use these for mmap and munmap within dlmalloc.c. */
static void *dlmmap(void *, size_t, int, int, int, off_t); static void *dlmmap(void *, size_t, int, int, int, off_t);
static int dlmunmap(void *, size_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 mmap dlmmap
#define munmap dlmunmap #define munmap dlmunmap
...@@ -207,7 +212,7 @@ static int dlmunmap(void *, size_t); ...@@ -207,7 +212,7 @@ static int dlmunmap(void *, size_t);
#undef mmap #undef mmap
#undef munmap #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. */ /* A mutex used to synchronize access to *exec* variables in this file. */
static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
...@@ -522,7 +527,7 @@ segment_holding_code (mstate m, char* addr) ...@@ -522,7 +527,7 @@ segment_holding_code (mstate m, char* addr)
} }
#endif #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 /* Allocate a chunk of memory with the given size. Returns a pointer
to the writable address, and sets *CODE to the executable to the writable address, and sets *CODE to the executable
......
...@@ -153,21 +153,24 @@ ffi_prep_args (char *stack, extended_cif * ecif) ...@@ -153,21 +153,24 @@ ffi_prep_args (char *stack, extended_cif * ecif)
return (struct_count); return (struct_count);
} }
ffi_status ffi_status FFI_HIDDEN
ffi_prep_cif (ffi_cif * cif, ffi_prep_cif_core (ffi_cif * cif,
ffi_abi abi, unsigned int nargs, ffi_abi abi, unsigned int isvariadic,
ffi_type * rtype, ffi_type ** atypes) unsigned int nfixedargs, unsigned int ntotalargs,
ffi_type * rtype, ffi_type ** atypes)
{ {
unsigned bytes = 0; unsigned bytes = 0;
unsigned int i; unsigned int i;
ffi_type **ptr; ffi_type **ptr;
FFI_ASSERT (cif != NULL); 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->abi = abi;
cif->arg_types = atypes; cif->arg_types = atypes;
cif->nargs = nargs; cif->nargs = ntotalargs;
cif->rtype = rtype; cif->rtype = rtype;
cif->flags = 0; cif->flags = 0;
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for CRIS.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifndef LIBFFI_ASM
typedef unsigned long ffi_arg; typedef unsigned long ffi_arg;
typedef signed long ffi_sarg; typedef signed long ffi_sarg;
...@@ -34,8 +39,8 @@ typedef signed long ffi_sarg; ...@@ -34,8 +39,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#endif #endif
......
...@@ -622,6 +622,9 @@ DEFAULT_MMAP_THRESHOLD default: 256K ...@@ -622,6 +622,9 @@ DEFAULT_MMAP_THRESHOLD default: 256K
#include "/usr/include/malloc.h" #include "/usr/include/malloc.h"
#else /* HAVE_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 { struct mallinfo {
MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */
MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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 Target configuration macros for FR-V
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------- */ /* ---- System specific configurations ----------------------------------- */
#ifndef LIBFFI_ASM #ifndef LIBFFI_ASM
...@@ -35,13 +40,9 @@ typedef signed long ffi_sarg; ...@@ -35,13 +40,9 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
#ifdef FRV
FFI_EABI, FFI_EABI,
FFI_DEFAULT_ABI = FFI_EABI, FFI_LAST_ABI,
#endif FFI_DEFAULT_ABI = FFI_EABI
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi; } ffi_abi;
#endif #endif
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc. ffi.c - Copyright (c) 1998, 2007, 2008, 2012 Red Hat, Inc.
Copyright (c) 2000 Hewlett Packard Company Copyright (c) 2000 Hewlett Packard Company
Copyright (c) 2011 Anthony Green
IA64 Foreign Function Interface IA64 Foreign Function Interface
...@@ -429,7 +430,8 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -429,7 +430,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
struct ffi_ia64_trampoline_struct *tramp; struct ffi_ia64_trampoline_struct *tramp;
struct ia64_fd *fd; 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; tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
fd = (struct ia64_fd *)(void *)ffi_closure_unix; fd = (struct ia64_fd *)(void *)ffi_closure_unix;
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for IA-64.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifndef LIBFFI_ASM
typedef unsigned long long ffi_arg; typedef unsigned long long ffi_arg;
typedef signed long long ffi_sarg; typedef signed long long ffi_sarg;
...@@ -34,8 +39,8 @@ typedef signed long long ffi_sarg; ...@@ -34,8 +39,8 @@ typedef signed long long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_UNIX, /* Linux and all Unix variants use the same conventions */ FFI_UNIX, /* Linux and all Unix variants use the same conventions */
FFI_DEFAULT_ABI = FFI_UNIX, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_UNIX
} ffi_abi; } ffi_abi;
#endif #endif
......
...@@ -311,7 +311,7 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue, ...@@ -311,7 +311,7 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue,
ffi_raw_closure *cl = (ffi_raw_closure*)user_data; ffi_raw_closure *cl = (ffi_raw_closure*)user_data;
ffi_java_ptrarray_to_raw (cif, avalue, raw); 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); ffi_java_raw_to_rvalue (cif, rvalue);
} }
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for M32R.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -26,6 +27,10 @@ ...@@ -26,6 +27,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------------- */ /* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM #ifndef LIBFFI_ASM
...@@ -36,8 +41,8 @@ typedef enum ffi_abi ...@@ -36,8 +41,8 @@ typedef enum ffi_abi
{ {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#endif #endif
......
...@@ -261,7 +261,8 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -261,7 +261,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
void *user_data, void *user_data,
void *codeloc) void *codeloc)
{ {
FFI_ASSERT (cif->abi == FFI_SYSV); if (cif->abi != FFI_SYSV)
return FFI_BAD_ABI;
*(unsigned short *)closure->tramp = 0x207c; *(unsigned short *)closure->tramp = 0x207c;
*(void **)(closure->tramp + 2) = codeloc; *(void **)(closure->tramp + 2) = codeloc;
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for Motorola 68K.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifndef LIBFFI_ASM
typedef unsigned long ffi_arg; typedef unsigned long ffi_arg;
typedef signed long ffi_sarg; typedef signed long ffi_sarg;
...@@ -34,8 +39,8 @@ typedef signed long ffi_sarg; ...@@ -34,8 +39,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#endif #endif
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 2007, 2008 Red Hat, Inc. ffi.c - Copyright (c) 2011 Anthony Green
Copyright (c) 2008 David Daney Copyright (c) 2008 David Daney
Copyright (c) 1996, 2007, 2008, 2011 Red Hat, Inc.
MIPS Foreign Function Interface MIPS Foreign Function Interface
...@@ -37,7 +38,11 @@ ...@@ -37,7 +38,11 @@
#endif #endif
#ifndef USE__BUILTIN___CLEAR_CACHE #ifndef USE__BUILTIN___CLEAR_CACHE
#include <sys/cachectl.h> # if defined(__OpenBSD__)
# include <mips64/sysarch.h>
# else
# include <sys/cachectl.h>
# endif
#endif #endif
#ifdef FFI_DEBUG #ifdef FFI_DEBUG
...@@ -662,10 +667,12 @@ ffi_prep_closure_loc (ffi_closure *closure, ...@@ -662,10 +667,12 @@ ffi_prep_closure_loc (ffi_closure *closure,
char *clear_location = (char *) codeloc; char *clear_location = (char *) codeloc;
#if defined(FFI_MIPS_O32) #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; fn = ffi_closure_O32;
#else /* FFI_MIPS_N32 */ #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; fn = ffi_closure_N32;
#endif /* FFI_MIPS_O32 */ #endif /* FFI_MIPS_O32 */
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for MIPS.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 #ifdef linux
# include <asm/sgidefs.h> # include <asm/sgidefs.h>
#elif defined(__rtems__) #elif defined(__rtems__)
...@@ -36,7 +41,7 @@ ...@@ -36,7 +41,7 @@
#define _MIPS_SIM_ABI32 1 #define _MIPS_SIM_ABI32 1
#define _MIPS_SIM_NABI32 2 #define _MIPS_SIM_NABI32 2
#define _MIPS_SIM_ABI64 3 #define _MIPS_SIM_ABI64 3
#else #elif !defined(__OpenBSD__)
# include <sgidefs.h> # include <sgidefs.h>
#endif #endif
...@@ -51,7 +56,7 @@ ...@@ -51,7 +56,7 @@
# endif # endif
#if !defined(_MIPS_SIM) #if !defined(_MIPS_SIM)
-- something is very wrong -- # error -- something is very wrong --
#else #else
# if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64)) # if (_MIPS_SIM==_ABIN32 && defined(_ABIN32)) || (_MIPS_SIM==_ABI64 && defined(_ABI64))
# define FFI_MIPS_N32 # define FFI_MIPS_N32
...@@ -59,7 +64,7 @@ ...@@ -59,7 +64,7 @@
# if (_MIPS_SIM==_ABIO32 && defined(_ABIO32)) # if (_MIPS_SIM==_ABIO32 && defined(_ABIO32))
# define FFI_MIPS_O32 # define FFI_MIPS_O32
# else # else
-- this is an unsupported platform -- # error -- this is an unsupported platform --
# endif # endif
# endif # endif
#endif #endif
...@@ -194,30 +199,29 @@ typedef enum ffi_abi { ...@@ -194,30 +199,29 @@ typedef enum ffi_abi {
FFI_O32_SOFT_FLOAT, FFI_O32_SOFT_FLOAT,
FFI_N32_SOFT_FLOAT, FFI_N32_SOFT_FLOAT,
FFI_N64_SOFT_FLOAT, FFI_N64_SOFT_FLOAT,
FFI_LAST_ABI,
#ifdef FFI_MIPS_O32 #ifdef FFI_MIPS_O32
#ifdef __mips_soft_float #ifdef __mips_soft_float
FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT, FFI_DEFAULT_ABI = FFI_O32_SOFT_FLOAT
#else #else
FFI_DEFAULT_ABI = FFI_O32, FFI_DEFAULT_ABI = FFI_O32
#endif #endif
#else #else
# if _MIPS_SIM==_ABI64 # if _MIPS_SIM==_ABI64
# ifdef __mips_soft_float # ifdef __mips_soft_float
FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT, FFI_DEFAULT_ABI = FFI_N64_SOFT_FLOAT
# else # else
FFI_DEFAULT_ABI = FFI_N64, FFI_DEFAULT_ABI = FFI_N64
# endif # endif
# else # else
# ifdef __mips_soft_float # ifdef __mips_soft_float
FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT, FFI_DEFAULT_ABI = FFI_N32_SOFT_FLOAT
# else # else
FFI_DEFAULT_ABI = FFI_N32, FFI_DEFAULT_ABI = FFI_N32
# endif # endif
# endif # endif
#endif #endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi; } ffi_abi;
#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag #define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org> ffi.c - (c) 2011 Anthony Green
(c) 2008 Red Hat, Inc. (c) 2008 Red Hat, Inc.
(c) 2006 Free Software Foundation, Inc.
(c) 2003-2004 Randolph Chung <tausq@debian.org>
HPPA Foreign Function Interface 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 Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
...@@ -633,7 +635,8 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -633,7 +635,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
UINT32 *tmp; UINT32 *tmp;
#endif #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 /* Make a small trampoline that will branch to our
handler function. Use PC-relative addressing. */ handler function. Use PC-relative addressing. */
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for hppa.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------- */ /* ---- System specific configurations ----------------------------------- */
#ifndef LIBFFI_ASM #ifndef LIBFFI_ASM
...@@ -38,21 +43,22 @@ typedef enum ffi_abi { ...@@ -38,21 +43,22 @@ typedef enum ffi_abi {
#ifdef PA_LINUX #ifdef PA_LINUX
FFI_PA32, FFI_PA32,
FFI_DEFAULT_ABI = FFI_PA32, FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_PA32
#endif #endif
#ifdef PA_HPUX #ifdef PA_HPUX
FFI_PA32, FFI_PA32,
FFI_DEFAULT_ABI = FFI_PA32, FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_PA32
#endif #endif
#ifdef PA64_HPUX #ifdef PA64_HPUX
#error "PA64_HPUX FFI is not yet implemented" #error "PA64_HPUX FFI is not yet implemented"
FFI_PA64, FFI_PA64,
FFI_DEFAULT_ABI = FFI_PA64, FFI_LAST_ABI,
FFI_DEFAULT_ABI = FFI_PA64
#endif #endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi; } ffi_abi;
#endif #endif
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 based on darwin.S by John Hornkvist
PowerPC Assembly glue. PowerPC Assembly glue.
...@@ -79,6 +79,8 @@ ...@@ -79,6 +79,8 @@
.set f20,20 .set f20,20
.set f21,21 .set f21,21
.extern .ffi_prep_args
#define LIBFFI_ASM #define LIBFFI_ASM
#include <fficonfig.h> #include <fficonfig.h>
#include <ffi.h> #include <ffi.h>
...@@ -125,6 +127,7 @@ ffi_call_AIX: ...@@ -125,6 +127,7 @@ ffi_call_AIX:
/* Call ffi_prep_args. */ /* Call ffi_prep_args. */
mr r4, r1 mr r4, r1
bl .ffi_prep_args bl .ffi_prep_args
nop
/* Now do the call. */ /* Now do the call. */
ld r0, 0(r29) ld r0, 0(r29)
...@@ -226,6 +229,7 @@ L(float_return_value): ...@@ -226,6 +229,7 @@ L(float_return_value):
/* Call ffi_prep_args. */ /* Call ffi_prep_args. */
mr r4, r1 mr r4, r1
bl .ffi_prep_args bl .ffi_prep_args
nop
/* Now do the call. */ /* Now do the call. */
lwz r0, 0(r29) lwz r0, 0(r29)
......
...@@ -79,6 +79,8 @@ ...@@ -79,6 +79,8 @@
.set f20,20 .set f20,20
.set f21,21 .set f21,21
.extern .ffi_closure_helper_DARWIN
#define LIBFFI_ASM #define LIBFFI_ASM
#define JUMPTARGET(name) name #define JUMPTARGET(name) name
#define L(x) x #define L(x) x
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
/* If compiled for profiling, call `_mcount' at the start of each function. */ /* If compiled for profiling, call `_mcount' at the start of each function. */
#ifdef PROF #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 to locate our caller and so it can restore it; so store one just
for its benefit. */ for its benefit. */
#ifdef PIC #ifdef PIC
......
...@@ -335,7 +335,7 @@ LSCIE1: ...@@ -335,7 +335,7 @@ LSCIE1:
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor .byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column .byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size .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 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1 .byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0 .byte 0x0 ; uleb128 0x0
......
...@@ -484,7 +484,7 @@ LSCIE1: ...@@ -484,7 +484,7 @@ LSCIE1:
.byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor .byte EH_DATA_ALIGN_FACT ; sleb128 -4; CIE Data Alignment Factor
.byte 0x41 ; CIE RA Column .byte 0x41 ; CIE RA Column
.byte 0x1 ; uleb128 0x1; Augmentation size .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 0xc ; DW_CFA_def_cfa
.byte 0x1 ; uleb128 0x1 .byte 0x1 ; uleb128 0x1
.byte 0x0 ; uleb128 0x0 .byte 0x0 ; uleb128 0x0
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc
Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for PowerPC. Target configuration macros for PowerPC.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -28,6 +30,10 @@ ...@@ -28,6 +30,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------- */ /* ---- System specific configurations ----------------------------------- */
#if defined (POWERPC) && defined (__powerpc64__) /* linux64 */ #if defined (POWERPC) && defined (__powerpc64__) /* linux64 */
...@@ -60,18 +66,14 @@ typedef enum ffi_abi { ...@@ -60,18 +66,14 @@ typedef enum ffi_abi {
FFI_LINUX64, FFI_LINUX64,
FFI_LINUX, FFI_LINUX,
FFI_LINUX_SOFT_FLOAT, FFI_LINUX_SOFT_FLOAT,
# ifdef POWERPC64 # if defined(POWERPC64)
FFI_DEFAULT_ABI = FFI_LINUX64, FFI_DEFAULT_ABI = FFI_LINUX64,
# else # elif defined(__NO_FPRS__)
# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106))
FFI_DEFAULT_ABI = FFI_LINUX,
# else
# ifdef __NO_FPRS__
FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT, 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, FFI_DEFAULT_ABI = FFI_GCC_SYSV,
# endif
# endif
# endif # endif
#endif #endif
......
...@@ -122,22 +122,41 @@ ENTRY(ffi_closure_SYSV) ...@@ -122,22 +122,41 @@ ENTRY(ffi_closure_SYSV)
blr blr
# case FFI_TYPE_FLOAT # case FFI_TYPE_FLOAT
#ifndef __NO_FPRS__
lfs %f1,112+0(%r1) lfs %f1,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
#else
nop
nop
nop
#endif
blr blr
# case FFI_TYPE_DOUBLE # case FFI_TYPE_DOUBLE
#ifndef __NO_FPRS__
lfd %f1,112+0(%r1) lfd %f1,112+0(%r1)
mtlr %r0 mtlr %r0
addi %r1,%r1,144 addi %r1,%r1,144
#else
nop
nop
nop
#endif
blr blr
# case FFI_TYPE_LONGDOUBLE # case FFI_TYPE_LONGDOUBLE
#ifndef __NO_FPRS__
lfd %f1,112+0(%r1) lfd %f1,112+0(%r1)
lfd %f2,112+8(%r1) lfd %f2,112+8(%r1)
mtlr %r0 mtlr %r0
b .Lfinish b .Lfinish
#else
nop
nop
nop
blr
#endif
# case FFI_TYPE_UINT8 # case FFI_TYPE_UINT8
lbz %r3,112+3(%r1) lbz %r3,112+3(%r1)
......
...@@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV) ...@@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV)
nop nop
1: 1:
#ifndef __NO_FPRS__
/* Load all the FP registers. */ /* Load all the FP registers. */
bf- 6,2f bf- 6,2f
lfd %f1,-16-(8*4)-(8*8)(%r28) lfd %f1,-16-(8*4)-(8*8)(%r28)
...@@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV) ...@@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV)
lfd %f6,-16-(8*4)-(3*8)(%r28) lfd %f6,-16-(8*4)-(3*8)(%r28)
lfd %f7,-16-(8*4)-(2*8)(%r28) lfd %f7,-16-(8*4)-(2*8)(%r28)
lfd %f8,-16-(8*4)-(1*8)(%r28) lfd %f8,-16-(8*4)-(1*8)(%r28)
#endif
2: 2:
/* Make the call. */ /* Make the call. */
...@@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV) ...@@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV)
mtcrf 0x01,%r31 /* cr7 */ mtcrf 0x01,%r31 /* cr7 */
bt- 31,L(small_struct_return_value) bt- 31,L(small_struct_return_value)
bt- 30,L(done_return_value) bt- 30,L(done_return_value)
#ifndef __NO_FPRS__
bt- 29,L(fp_return_value) bt- 29,L(fp_return_value)
#endif
stw %r3,0(%r30) stw %r3,0(%r30)
bf+ 28,L(done_return_value) bf+ 28,L(done_return_value)
stw %r4,4(%r30) stw %r4,4(%r30)
...@@ -124,6 +128,7 @@ L(done_return_value): ...@@ -124,6 +128,7 @@ L(done_return_value):
lwz %r1,0(%r1) lwz %r1,0(%r1)
blr blr
#ifndef __NO_FPRS__
L(fp_return_value): L(fp_return_value):
bf 28,L(float_return_value) bf 28,L(float_return_value)
stfd %f1,0(%r30) stfd %f1,0(%r30)
...@@ -134,21 +139,17 @@ L(fp_return_value): ...@@ -134,21 +139,17 @@ L(fp_return_value):
L(float_return_value): L(float_return_value):
stfs %f1,0(%r30) stfs %f1,0(%r30)
b L(done_return_value) b L(done_return_value)
#endif
L(small_struct_return_value): 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) */ * The C code always allocates a properly-aligned 8-byte bounce
extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */ * buffer to make this assembly code very simple. Just write out
subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */ * r3 and r4 to the buffer to allow the C code to handle the rest.
bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */ */
/* smst_one_register: */ stw %r3, 0(%r30)
slw %r3,%r3,%r5 /* Left-justify value in r3 */ stw %r4, 4(%r30)
mtxer %r6 /* move byte count to XER ... */ b L(done_return_value)
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)
.LFE1: .LFE1:
END(ffi_call_SYSV) END(ffi_call_SYSV)
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
...@@ -37,17 +38,21 @@ static ffi_status initialize_aggregate(ffi_type *arg) ...@@ -37,17 +38,21 @@ static ffi_status initialize_aggregate(ffi_type *arg)
{ {
ffi_type **ptr; ffi_type **ptr;
FFI_ASSERT(arg != NULL); if (UNLIKELY(arg == NULL || arg->elements == NULL))
return FFI_BAD_TYPEDEF;
FFI_ASSERT(arg->elements != NULL); arg->size = 0;
FFI_ASSERT(arg->size == 0); arg->alignment = 0;
FFI_ASSERT(arg->alignment == 0);
ptr = &(arg->elements[0]); ptr = &(arg->elements[0]);
if (UNLIKELY(ptr == 0))
return FFI_BAD_TYPEDEF;
while ((*ptr) != NULL) 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; return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */ /* Perform a sanity check on the argument type */
...@@ -85,24 +90,38 @@ static ffi_status initialize_aggregate(ffi_type *arg) ...@@ -85,24 +90,38 @@ static ffi_status initialize_aggregate(ffi_type *arg)
/* Perform machine independent ffi_cif preparation, then call /* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */ machine dependent routine. */
ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, /* For non variadic functions isvariadic should be 0 and
ffi_type *rtype, ffi_type **atypes) 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 bytes = 0;
unsigned int i; unsigned int i;
ffi_type **ptr; ffi_type **ptr;
FFI_ASSERT(cif != NULL); FFI_ASSERT(cif != NULL);
FFI_ASSERT((!isvariadic) || (nfixedargs >= 1));
FFI_ASSERT(nfixedargs <= ntotalargs);
#ifndef X86_WIN32 #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 #else
FFI_ASSERT(abi > FFI_FIRST_ABI && abi <= FFI_DEFAULT_ABI if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL))
|| abi == FFI_THISCALL); return FFI_BAD_ABI;
#endif #endif
cif->abi = abi; cif->abi = abi;
cif->arg_types = atypes; cif->arg_types = atypes;
cif->nargs = nargs; cif->nargs = ntotalargs;
cif->rtype = rtype; cif->rtype = rtype;
cif->flags = 0; cif->flags = 0;
...@@ -115,7 +134,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ...@@ -115,7 +134,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
FFI_ASSERT_VALID_TYPE(cif->rtype); FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */ /* 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 */ /* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT if (cif->rtype->type == FFI_TYPE_STRUCT
#ifdef SPARC #ifdef SPARC
...@@ -136,7 +155,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ...@@ -136,7 +155,7 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
check after the initialization. */ check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr); 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 #ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9)) && ((*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, ...@@ -158,10 +177,31 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
cif->bytes = bytes; cif->bytes = bytes;
/* Perform machine dependent cif processing */ /* 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); return ffi_prep_cif_machdep(cif);
} }
#endif /* not __CRIS__ */ #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 #if FFI_CLOSURES
ffi_status ffi_status
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for S390.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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__) #if defined (__s390x__)
#ifndef S390X #ifndef S390X
#define S390X #define S390X
...@@ -42,8 +47,8 @@ typedef signed long ffi_sarg; ...@@ -42,8 +47,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#endif #endif
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for SuperH.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------------- */ /* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM #ifndef LIBFFI_ASM
...@@ -36,8 +41,8 @@ typedef signed long ffi_sarg; ...@@ -36,8 +41,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#endif #endif
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for SuperH - SHmedia.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------------- */ /* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM #ifndef LIBFFI_ASM
...@@ -36,8 +41,8 @@ typedef signed long ffi_sarg; ...@@ -36,8 +41,8 @@ typedef signed long ffi_sarg;
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
FFI_SYSV, FFI_SYSV,
FFI_DEFAULT_ABI = FFI_SYSV, FFI_LAST_ABI,
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 FFI_DEFAULT_ABI = FFI_SYSV
} ffi_abi; } ffi_abi;
#define FFI_EXTRA_CIF_FIELDS long long flags2 #define FFI_EXTRA_CIF_FIELDS long long flags2
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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 SPARC Foreign Function Interface
...@@ -406,8 +407,50 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ...@@ -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 */ /* We don't yet support calling 32bit code from 64bit */
FFI_ASSERT(0); FFI_ASSERT(0);
#else #else
ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT
cif->flags, rvalue, fn); #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 #endif
break; break;
case FFI_V9: case FFI_V9:
...@@ -425,7 +468,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ...@@ -425,7 +468,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
FFI_ASSERT(0); FFI_ASSERT(0);
break; break;
} }
} }
...@@ -447,7 +489,8 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -447,7 +489,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
#ifdef SPARC64 #ifdef SPARC64
/* Trampoline address is equal to the closure address. We take advantage /* Trampoline address is equal to the closure address. We take advantage
of that to reduce the trampoline size by 8 bytes. */ 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; fn = (unsigned long) ffi_closure_v9;
tramp[0] = 0x83414000; /* rd %pc, %g1 */ tramp[0] = 0x83414000; /* rd %pc, %g1 */
tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */
...@@ -456,7 +499,8 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -456,7 +499,8 @@ ffi_prep_closure_loc (ffi_closure* closure,
*((unsigned long *) &tramp[4]) = fn; *((unsigned long *) &tramp[4]) = fn;
#else #else
unsigned long ctx = (unsigned long) codeloc; 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; fn = (unsigned long) ffi_closure_v8;
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */ tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */
...@@ -468,13 +512,13 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -468,13 +512,13 @@ ffi_prep_closure_loc (ffi_closure* closure,
closure->fun = fun; closure->fun = fun;
closure->user_data = user_data; 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 #ifdef SPARC64
asm volatile ("flush %0" : : "r" (closure) : "memory"); asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory");
asm volatile ("flush %0" : : "r" (((char *) closure) + 8) : "memory");
#else #else
asm volatile ("iflush %0" : : "r" (closure) : "memory"); asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory");
asm volatile ("iflush %0" : : "r" (((char *) closure) + 8) : "memory"); /* SPARC v8 requires 5 instructions for flush to be visible */
asm volatile ("nop; nop; nop; nop; nop");
#endif #endif
return FFI_OK; return FFI_OK;
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-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. Target configuration macros for SPARC.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
...@@ -27,6 +28,10 @@ ...@@ -27,6 +28,10 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------- */ /* ---- System specific configurations ----------------------------------- */
#if defined(__arch64__) || defined(__sparcv9) #if defined(__arch64__) || defined(__sparcv9)
...@@ -44,12 +49,12 @@ typedef enum ffi_abi { ...@@ -44,12 +49,12 @@ typedef enum ffi_abi {
FFI_V8, FFI_V8,
FFI_V8PLUS, FFI_V8PLUS,
FFI_V9, FFI_V9,
FFI_LAST_ABI,
#ifdef SPARC64 #ifdef SPARC64
FFI_DEFAULT_ABI = FFI_V9, FFI_DEFAULT_ABI = FFI_V9
#else #else
FFI_DEFAULT_ABI = FFI_V8, FFI_DEFAULT_ABI = FFI_V8
#endif #endif
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi; } ffi_abi;
#endif #endif
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
/* Only compile this in for 64bit builds, because otherwise the object file /* Only compile this in for 64bit builds, because otherwise the object file
will have inproper architecture due to used instructions. */ 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 STACK_BIAS 2047
#define ARGS (128) /* Offset of register area in frame */ #define ARGS (128) /* Offset of register area in frame */
......
...@@ -228,12 +228,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) ...@@ -228,12 +228,10 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
switch (cif->rtype->type) switch (cif->rtype->type)
{ {
case FFI_TYPE_VOID: 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_UINT8:
case FFI_TYPE_UINT16: case FFI_TYPE_UINT16:
case FFI_TYPE_SINT8: case FFI_TYPE_SINT8:
case FFI_TYPE_SINT16: case FFI_TYPE_SINT16:
#endif
#ifdef X86_WIN64 #ifdef X86_WIN64
case FFI_TYPE_UINT32: case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32: case FFI_TYPE_SINT32:
...@@ -364,27 +362,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ...@@ -364,27 +362,8 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
{ {
#ifdef X86_WIN64 #ifdef X86_WIN64
case FFI_WIN64: case FFI_WIN64:
{ ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
/* Make copies of all struct arguments cif->flags, ecif.rvalue, fn);
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);
}
break; break;
#elif defined(X86_WIN32) #elif defined(X86_WIN32)
case FFI_SYSV: case FFI_SYSV:
...@@ -447,8 +426,6 @@ unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) ...@@ -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 *) void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
__attribute__ ((regparm(1))); __attribute__ ((regparm(1)));
#ifdef X86_WIN32 #ifdef X86_WIN32
void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
__attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
__attribute__ ((regparm(1))); __attribute__ ((regparm(1)));
void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
...@@ -616,7 +593,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, ...@@ -616,7 +593,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ { unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \ unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \ 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 short __size = (unsigned short)(SIZE); \
*(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \ *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
*(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \ *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
...@@ -722,9 +699,6 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, ...@@ -722,9 +699,6 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
int i; int i;
if (cif->abi != FFI_SYSV) { if (cif->abi != FFI_SYSV) {
#ifdef X86_WIN32
if (cif->abi != FFI_THISCALL)
#endif
return FFI_BAD_ABI; return FFI_BAD_ABI;
} }
...@@ -739,20 +713,10 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, ...@@ -739,20 +713,10 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); 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, FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
codeloc); 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->cif = cif;
closure->user_data = user_data; closure->user_data = user_data;
closure->fun = fun; closure->fun = fun;
...@@ -797,7 +761,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) ...@@ -797,7 +761,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
#ifdef X86_WIN32 #ifdef X86_WIN32
case FFI_SYSV: case FFI_SYSV:
case FFI_STDCALL: 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); ecif.rvalue, fn);
break; break;
case FFI_THISCALL: case FFI_THISCALL:
...@@ -825,7 +789,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) ...@@ -825,7 +789,7 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
cif->abi = abi = FFI_THISCALL; cif->abi = abi = FFI_THISCALL;
if (passed_regs < 1 && abi == FFI_THISCALL) if (passed_regs < 1 && abi == FFI_THISCALL)
cif->abi = abi = FFI_STDCALL; 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); ecif.rvalue, fn);
} }
break; break;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
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) 2008, 2010 Red Hat, Inc.
Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
x86-64 Foreign Function Interface x86-64 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining 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) ...@@ -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 /* If the return value is passed in memory, add the pointer as the
first integer argument. */ first integer argument. */
if (ret_in_memory) if (ret_in_memory)
reg_args->gpr[gprcount++] = (long) rvalue; reg_args->gpr[gprcount++] = (unsigned long) rvalue;
avn = cif->nargs; avn = cif->nargs;
arg_types = cif->arg_types; arg_types = cif->arg_types;
...@@ -498,12 +499,21 @@ ffi_prep_closure_loc (ffi_closure* closure, ...@@ -498,12 +499,21 @@ ffi_prep_closure_loc (ffi_closure* closure,
{ {
volatile unsigned short *tramp; 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 = (volatile unsigned short *) &closure->tramp[0];
tramp[0] = 0xbb49; /* mov <code>, %r11 */ 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 */ 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. /* Set the carry bit iff the function uses any sse registers.
This is clc or stc, together with the first byte of the jmp. */ 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, ...@@ -542,7 +552,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
{ {
/* The return value goes in memory. Arrange for the closure /* The return value goes in memory. Arrange for the closure
return value to go directly back to the original caller. */ 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. */ /* We don't have to do anything in asm for the return. */
ret = FFI_TYPE_VOID; ret = FFI_TYPE_VOID;
} }
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003, 2010 Red Hat, Inc. ffitarget.h - Copyright (c) 2012 Anthony Green
Copyright (C) 2008 Free Software Foundation, Inc. Copyright (c) 1996-2003, 2010 Red Hat, Inc.
Copyright (C) 2008 Free Software Foundation, Inc.
Target configuration macros for x86 and x86-64. Target configuration macros for x86 and x86-64.
...@@ -29,8 +30,15 @@ ...@@ -29,8 +30,15 @@
#ifndef LIBFFI_TARGET_H #ifndef LIBFFI_TARGET_H
#define 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 ----------------------------------- */ /* ---- System specific configurations ----------------------------------- */
/* For code common to all platforms on x86 and x86_64. */
#define X86_ANY
#if defined (X86_64) && defined (__i386__) #if defined (X86_64) && defined (__i386__)
#undef X86_64 #undef X86_64
#define X86 #define X86
...@@ -53,9 +61,15 @@ typedef unsigned long long ffi_arg; ...@@ -53,9 +61,15 @@ typedef unsigned long long ffi_arg;
typedef long long ffi_sarg; typedef long long ffi_sarg;
#endif #endif
#else #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 unsigned long ffi_arg;
typedef signed long ffi_sarg; typedef signed long ffi_sarg;
#endif #endif
#endif
typedef enum ffi_abi { typedef enum ffi_abi {
FFI_FIRST_ABI = 0, FFI_FIRST_ABI = 0,
...@@ -66,28 +80,26 @@ typedef enum ffi_abi { ...@@ -66,28 +80,26 @@ typedef enum ffi_abi {
FFI_STDCALL, FFI_STDCALL,
FFI_THISCALL, FFI_THISCALL,
FFI_FASTCALL, FFI_FASTCALL,
FFI_LAST_ABI,
/* TODO: Add fastcall support for the sake of completeness */ /* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV
#endif
#ifdef X86_WIN64 #elif defined(X86_WIN64)
FFI_WIN64, FFI_WIN64,
FFI_DEFAULT_ABI = FFI_WIN64, FFI_LAST_ABI,
#else FFI_DEFAULT_ABI = FFI_WIN64
#else
/* ---- Intel x86 and AMD x86-64 - */ /* ---- Intel x86 and AMD x86-64 - */
#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__) || defined(__i386) || defined(__amd64))
FFI_SYSV, FFI_SYSV,
FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */
FFI_LAST_ABI,
#if defined(__i386__) || defined(__i386) #if defined(__i386__) || defined(__i386)
FFI_DEFAULT_ABI = FFI_SYSV, FFI_DEFAULT_ABI = FFI_SYSV
#else #else
FFI_DEFAULT_ABI = FFI_UNIX64, FFI_DEFAULT_ABI = FFI_UNIX64
#endif #endif
#endif #endif
#endif /* X86_WIN64 */
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi; } ffi_abi;
#endif #endif
......
...@@ -264,18 +264,6 @@ ffi_closure_SYSV ENDP ...@@ -264,18 +264,6 @@ ffi_closure_SYSV ENDP
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20 #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 ffi_closure_raw_SYSV PROC NEAR USES esi
;; the ffi_closure ctx is passed in eax by the trampoline. ;; the ffi_closure ctx is passed in eax by the trampoline.
...@@ -284,7 +272,6 @@ ffi_closure_raw_SYSV PROC NEAR USES esi ...@@ -284,7 +272,6 @@ ffi_closure_raw_SYSV PROC NEAR USES esi
mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data
mov [esp + 12], edx ;; user_data mov [esp + 12], edx ;; user_data
lea edx, [ebp + 8] lea edx, [ebp + 8]
stubraw:
mov [esp + 8], edx ;; raw_args mov [esp + 8], edx ;; raw_args
lea edx, [ebp - 24] lea edx, [ebp - 24]
mov [esp + 4], edx ;; &res mov [esp + 4], edx ;; &res
...@@ -735,21 +722,7 @@ _ffi_closure_SYSV: ...@@ -735,21 +722,7 @@ _ffi_closure_SYSV:
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) #define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) #define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
#define CIF_FLAGS_OFFSET 20 #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. # This assumes we are using gas.
.balign 16 .balign 16
.globl _ffi_closure_raw_SYSV .globl _ffi_closure_raw_SYSV
...@@ -769,7 +742,6 @@ _ffi_closure_raw_SYSV: ...@@ -769,7 +742,6 @@ _ffi_closure_raw_SYSV:
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
movl %edx, 12(%esp) /* user_data */ movl %edx, 12(%esp) /* user_data */
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
.stubraw:
movl %edx, 8(%esp) /* raw_args */ movl %edx, 8(%esp) /* raw_args */
leal -24(%ebp), %edx leal -24(%ebp), %edx
movl %edx, 4(%esp) /* &res */ movl %edx, 4(%esp) /* &res */
......
...@@ -232,10 +232,18 @@ ret_void$: ...@@ -232,10 +232,18 @@ ret_void$:
ffi_call_win64 ENDP ffi_call_win64 ENDP
_TEXT ENDS _TEXT ENDS
END END
#else
#else
#ifdef SYMBOL_UNDERSCORE
#define SYMBOL_NAME(name) _##name
#else
#define SYMBOL_NAME(name) name
#endif
.text .text
.extern _ffi_closure_win64_inner .extern SYMBOL_NAME(ffi_closure_win64_inner)
# ffi_closure_win64 will be called with these registers set: # ffi_closure_win64 will be called with these registers set:
# rax points to 'closure' # rax points to 'closure'
...@@ -246,8 +254,8 @@ END ...@@ -246,8 +254,8 @@ END
# call ffi_closure_win64_inner for the actual work, then return the result. # call ffi_closure_win64_inner for the actual work, then return the result.
# #
.balign 16 .balign 16
.globl _ffi_closure_win64 .globl SYMBOL_NAME(ffi_closure_win64)
_ffi_closure_win64: SYMBOL_NAME(ffi_closure_win64):
# copy register arguments onto stack # copy register arguments onto stack
test $1,%r11 test $1,%r11
jne .Lfirst_is_float jne .Lfirst_is_float
...@@ -287,7 +295,7 @@ _ffi_closure_win64: ...@@ -287,7 +295,7 @@ _ffi_closure_win64:
mov %rax, %rcx # context is first parameter mov %rax, %rcx # context is first parameter
mov %rsp, %rdx # stack is second parameter mov %rsp, %rdx # stack is second parameter
add $48, %rdx # point to start of arguments 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 callq *%rax # call the real closure function
add $40, %rsp add $40, %rsp
movq %rax, %xmm0 # If the closure returned a float, movq %rax, %xmm0 # If the closure returned a float,
...@@ -296,8 +304,8 @@ _ffi_closure_win64: ...@@ -296,8 +304,8 @@ _ffi_closure_win64:
.ffi_closure_win64_end: .ffi_closure_win64_end:
.balign 16 .balign 16
.globl _ffi_call_win64 .globl SYMBOL_NAME(ffi_call_win64)
_ffi_call_win64: SYMBOL_NAME(ffi_call_win64):
# copy registers onto stack # copy registers onto stack
mov %r9,32(%rsp) mov %r9,32(%rsp)
mov %r8,24(%rsp) mov %r8,24(%rsp)
......
...@@ -37,7 +37,8 @@ int main (void) ...@@ -37,7 +37,8 @@ int main (void)
arg_types[1] = &ffi_type_double; arg_types[1] = &ffi_type_double;
arg_types[2] = NULL; 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); arg_types) == FFI_OK);
args[0] = &format; args[0] = &format;
...@@ -49,6 +50,9 @@ int main (void) ...@@ -49,6 +50,9 @@ int main (void)
printf("res: %d\n", (int) res); printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" } // { 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); CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, code) == FFI_OK);
res = ((int(*)(char*, double))(code))(format, doubleArg); res = ((int(*)(char*, double))(code))(format, doubleArg);
......
...@@ -37,7 +37,8 @@ int main (void) ...@@ -37,7 +37,8 @@ int main (void)
arg_types[1] = &ffi_type_longdouble; arg_types[1] = &ffi_type_longdouble;
arg_types[2] = NULL; 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); arg_types) == FFI_OK);
args[0] = &format; args[0] = &format;
...@@ -49,6 +50,10 @@ int main (void) ...@@ -49,6 +50,10 @@ int main (void)
printf("res: %d\n", (int) res); printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" } // { 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); CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, code) == FFI_OK);
res = ((int(*)(char*, long double))(code))(format, ldArg); res = ((int(*)(char*, long double))(code))(format, ldArg);
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
PR: none. PR: none.
Originator: Blake Chaffin 6/6/2007 */ Originator: Blake Chaffin 6/6/2007 */
/* { dg-do run { xfail *-*-* } } */ /* { dg-do run } */
#include "ffitest.h" #include "ffitest.h"
static void static void
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
PR: none. PR: none.
Originator: Blake Chaffin 6/6/2007 */ Originator: Blake Chaffin 6/6/2007 */
/* { dg-do run { xfail *-*-* } } */ /* { dg-do run } */
#include "ffitest.h" #include "ffitest.h"
int main (void) int main (void)
......
/* 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);
}
...@@ -30,7 +30,7 @@ int main (void) ...@@ -30,7 +30,7 @@ int main (void)
sc < (signed char) 127; sc++) sc < (signed char) 127; sc++)
{ {
ffi_call(&cif, FFI_FN(return_sc), &rint, values); ffi_call(&cif, FFI_FN(return_sc), &rint, values);
CHECK(rint == (ffi_arg) sc); CHECK((signed char)rint == sc);
} }
exit(0); exit(0);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment