Commit 667ce06d authored by Thomas Heller's avatar Thomas Heller

Merged revisions 80761,80766 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r80761 | thomas.heller | 2010-05-04 20:44:42 +0200 (Di, 04 Mai 2010) | 8 lines

  On Windows, ctypes does no longer check the stack before and after
  calling a foreign function.  This allows to use the unmodified libffi
  library.

  Remove most files from _ctypes/libffi_msvc, only two include files
  stay (updated from _ctypes/libffi/...).  Other files are used in the
  cross-platform _ctypes/libffi directory.
........
  r80766 | thomas.heller | 2010-05-04 21:08:18 +0200 (Di, 04 Mai 2010) | 2 lines

  Remove reference to unused source file.
........
parent a9eb87a1
......@@ -6,32 +6,6 @@ import unittest, sys
import _ctypes_test
if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int):
# Only windows 32-bit has different calling conventions.
class WindowsTestCase(unittest.TestCase):
def test_callconv_1(self):
# Testing stdcall function
IsWindow = windll.user32.IsWindow
# ValueError: Procedure probably called with not enough arguments (4 bytes missing)
self.assertRaises(ValueError, IsWindow)
# This one should succeeed...
self.assertEqual(0, IsWindow(0))
# ValueError: Procedure probably called with too many arguments (8 bytes in excess)
self.assertRaises(ValueError, IsWindow, 0, 0, 0)
def test_callconv_2(self):
# Calling stdcall function as cdecl
IsWindow = cdll.user32.IsWindow
# ValueError: Procedure called with not enough arguments (4 bytes missing)
# or wrong calling convention
self.assertRaises(ValueError, IsWindow, None)
if sys.platform == "win32":
class FunctionCallTestCase(unittest.TestCase):
......
......@@ -761,7 +761,6 @@ static int _call_function_pointer(int flags,
ffi_cif cif;
int cc;
#ifdef MS_WIN32
int delta;
#ifndef DONT_USE_SEH
DWORD dwExceptionCode = 0;
EXCEPTION_RECORD record;
......@@ -812,9 +811,8 @@ static int _call_function_pointer(int flags,
#ifndef DONT_USE_SEH
__try {
#endif
delta =
#endif
ffi_call(&cif, (void *)pProc, resmem, avalues);
ffi_call(&cif, (void *)pProc, resmem, avalues);
#ifdef MS_WIN32
#ifndef DONT_USE_SEH
}
......@@ -846,35 +844,6 @@ static int _call_function_pointer(int flags,
return -1;
}
#endif
#ifdef MS_WIN64
if (delta != 0) {
PyErr_Format(PyExc_RuntimeError,
"ffi_call failed with code %d",
delta);
return -1;
}
#else
if (delta < 0) {
if (flags & FUNCFLAG_CDECL)
PyErr_Format(PyExc_ValueError,
"Procedure called with not enough "
"arguments (%d bytes missing) "
"or wrong calling convention",
-delta);
else
PyErr_Format(PyExc_ValueError,
"Procedure probably called with not enough "
"arguments (%d bytes missing)",
-delta);
return -1;
} else if (delta > 0) {
PyErr_Format(PyExc_ValueError,
"Procedure probably called with too many "
"arguments (%d bytes in excess)",
delta);
return -1;
}
#endif
#endif
if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
return -1;
......@@ -1147,11 +1116,7 @@ PyObject *_ctypes_callproc(PPROC pProc,
}
for (i = 0; i < argcount; ++i) {
atypes[i] = args[i].ffi_type;
if (atypes[i]->type == FFI_TYPE_STRUCT
#ifdef _WIN64
&& atypes[i]->size <= sizeof(void *)
#endif
)
if (atypes[i]->type == FFI_TYPE_STRUCT)
avalues[i] = (void *)args[i].value.p;
else
avalues[i] = (void *)&args[i].value;
......
libffi - Copyright (c) 1996-2003 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
This diff is collapsed.
The purpose is to hack the libffi sources so that they can be compiled
with MSVC, and to extend them so that they have the features I need
for ctypes.
I retrieved the libffi sources from the gcc cvs repository on
2004-01-27. Then I did 'configure' in a 'build' subdirectory on a x86
linux system, and copied the files I found useful.
This diff is collapsed.
/* -----------------------------------------------------------------*-C-*-
libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc.
libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
......@@ -12,13 +12,14 @@
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
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.
----------------------------------------------------------------------- */
......@@ -56,7 +57,7 @@ extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
//XXX #define X86
/* #define @TARGET@ */
/* ---- System configuration information --------------------------------- */
......@@ -64,6 +65,10 @@ extern "C" {
#ifndef LIBFFI_ASM
#ifdef _MSC_VER
#define __attribute__(X)
#endif
#include <stddef.h>
#include <limits.h>
......@@ -79,12 +84,21 @@ extern "C" {
# ifdef __GNUC__
# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
# endif
# ifdef _MSC_VER
# define FFI_LONG_LONG_MAX _I64_MAX
# endif
# endif
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t */
/* can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
struct _ffi_type **elements;
} ffi_type;
#ifndef LIBFFI_HIDE_BASIC_TYPES
#if SCHAR_MAX == 127
# define ffi_type_uchar ffi_type_uint8
# define ffi_type_schar ffi_type_sint8
......@@ -115,26 +129,23 @@ extern "C" {
#error "int size not supported"
#endif
#define ffi_type_ulong ffi_type_uint64
#define ffi_type_slong ffi_type_sint64
#if LONG_MAX == 2147483647
# if FFI_LONG_LONG_MAX != 9223372036854775807
#error "no 64-bit data type supported"
#error "no 64-bit data type supported"
# endif
#elif LONG_MAX != 9223372036854775807
#error "long size not supported"
#endif
/* The closure code assumes that this works on pointers, i.e. a size_t */
/* can hold a pointer. */
typedef struct _ffi_type
{
size_t size;
unsigned short alignment;
unsigned short type;
/*@null@*/ struct _ffi_type **elements;
} ffi_type;
#if LONG_MAX == 2147483647
# define ffi_type_ulong ffi_type_uint32
# define ffi_type_slong ffi_type_sint32
#elif LONG_MAX == 9223372036854775807
# define ffi_type_ulong ffi_type_uint64
# define ffi_type_slong ffi_type_sint64
#else
#error "long size not supported"
#endif
/* These are defined in types.c */
extern ffi_type ffi_type_void;
......@@ -148,14 +159,19 @@ extern ffi_type ffi_type_uint64;
extern ffi_type ffi_type_sint64;
extern ffi_type ffi_type_float;
extern ffi_type ffi_type_double;
extern ffi_type ffi_type_longdouble;
extern ffi_type ffi_type_pointer;
#if HAVE_LONG_DOUBLE
extern ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
#endif
#endif /* LIBFFI_HIDE_BASIC_TYPES */
typedef enum {
FFI_OK = 0,
FFI_BAD_TYPEDEF,
FFI_BAD_ABI
FFI_BAD_ABI
} ffi_status;
typedef unsigned FFI_TYPE;
......@@ -163,8 +179,8 @@ typedef unsigned FFI_TYPE;
typedef struct {
ffi_abi abi;
unsigned nargs;
/*@dependent@*/ ffi_type **arg_types;
/*@dependent@*/ ffi_type *rtype;
ffi_type **arg_types;
ffi_type *rtype;
unsigned bytes;
unsigned flags;
#ifdef FFI_EXTRA_CIF_FIELDS
......@@ -174,10 +190,16 @@ typedef struct {
/* ---- Definitions for the raw API -------------------------------------- */
#ifdef _WIN64
#define FFI_SIZEOF_ARG 8
#else
#define FFI_SIZEOF_ARG 4
#ifndef FFI_SIZEOF_ARG
# if LONG_MAX == 2147483647
# define FFI_SIZEOF_ARG 4
# elif LONG_MAX == 9223372036854775807
# define FFI_SIZEOF_ARG 8
# endif
#endif
#ifndef FFI_SIZEOF_JAVA_RAW
# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG
#endif
typedef union {
......@@ -188,10 +210,25 @@ typedef union {
void* ptr;
} ffi_raw;
void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *avalue);
#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8
/* This is a special case for mips64/n32 ABI (and perhaps others) where
sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */
typedef union {
signed int sint;
unsigned int uint;
float flt;
char data[FFI_SIZEOF_JAVA_RAW];
void* ptr;
} ffi_java_raw;
#else
typedef ffi_raw ffi_java_raw;
#endif
void ffi_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_raw *avalue);
void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
......@@ -201,25 +238,35 @@ size_t ffi_raw_size (ffi_cif *cif);
/* packing, even on 64-bit machines. I.e. on 64-bit machines */
/* longs and doubles are followed by an empty 64-bit word. */
void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ ffi_raw *avalue);
void ffi_java_raw_call (ffi_cif *cif,
void (*fn)(void),
void *rvalue,
ffi_java_raw *avalue);
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);
size_t ffi_java_raw_size (ffi_cif *cif);
/* ---- Definitions for closures ----------------------------------------- */
#if FFI_CLOSURES
#ifdef _MSC_VER
__declspec(align(8))
#endif
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
ffi_cif *cif;
void (*fun)(ffi_cif*,void*,void**,void*);
void *user_data;
#ifdef __GNUC__
} ffi_closure __attribute__((aligned (8)));
#else
} ffi_closure;
#endif
void *ffi_closure_alloc (size_t size, void **code);
void ffi_closure_free (void *);
ffi_status
ffi_prep_closure (ffi_closure*,
......@@ -227,6 +274,13 @@ ffi_prep_closure (ffi_closure*,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data);
ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
......@@ -248,6 +302,27 @@ typedef struct {
} ffi_raw_closure;
typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE];
ffi_cif *cif;
#if !FFI_NATIVE_RAW_API
/* if this is enabled, then a raw closure has the same layout
as a regular closure. We use this to install an intermediate
handler to do the transaltion, void** -> ffi_raw*. */
void (*translate_args)(ffi_cif*,void*,void**,void*);
void *this_closure;
#endif
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);
void *user_data;
} ffi_java_raw_closure;
ffi_status
ffi_prep_raw_closure (ffi_raw_closure*,
ffi_cif *cif,
......@@ -255,29 +330,42 @@ ffi_prep_raw_closure (ffi_raw_closure*,
void *user_data);
ffi_status
ffi_prep_java_raw_closure (ffi_raw_closure*,
ffi_prep_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data);
ffi_status
ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc);
#endif /* FFI_CLOSURES */
/* ---- Public interface definition -------------------------------------- */
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
ffi_status ffi_prep_cif(ffi_cif *cif,
ffi_abi abi,
unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
/*@dependent@*/ ffi_type **atypes);
unsigned int nargs,
ffi_type *rtype,
ffi_type **atypes);
int
ffi_call(/*@dependent@*/ ffi_cif *cif,
void (*fn)(),
/*@out@*/ void *rvalue,
/*@dependent@*/ void **avalue);
void ffi_call(ffi_cif *cif,
void (*fn)(void),
void *rvalue,
void **avalue);
/* Useful for eliminating compiler warnings */
#define FFI_FN(f) ((void (*)())f)
#define FFI_FN(f) ((void (*)(void))f)
/* ---- Definitions shared with assembly code ---------------------------- */
......@@ -288,7 +376,7 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#if HAVE_LONG_DOUBLE
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
......@@ -312,4 +400,3 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
#endif
#endif
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
#ifndef FFI_COMMON_H
#define FFI_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <fficonfig.h>
#include <malloc.h>
/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#if defined(FFI_DEBUG)
#include <stdio.h>
#endif
#ifdef FFI_DEBUG
/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
void ffi_stop_here(void);
void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
#endif
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
/* Extended cif, used in callback from assembly routine */
typedef struct
{
/*@dependent@*/ ffi_cif *cif;
/*@dependent@*/ void *rvalue;
/*@dependent@*/ void **avalue;
} extended_cif;
/* Terse sized type definitions. */
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
#ifdef __cplusplus
}
#endif
#endif
/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */
/* fficonfig.h. Generated automatically by configure. */
/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
/* Define this for MSVC, but not for mingw32! */
#ifdef _MSC_VER
#define __attribute__(x) /* */
#endif
#define alloca _alloca
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/*----------------------------------------------------------------*/
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define if using alloca.c. */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
/* Define to the flags needed for the .section .eh_frame directive. */
/* #undef EH_FRAME_FLAGS */
/* Define if you have alloca, as a function or macro. */
#define HAVE_ALLOCA 1
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
/* #define HAVE_ALLOCA_H 1 */
/* Cannot use malloc on this target, so, we revert to alternative means */
/* #undef FFI_MMAP_EXEC_WRIT */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
/* #undef STACK_DIRECTION */
/* Define this is you do not want support for the raw API. */
#define FFI_NO_RAW_API 1
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define this is you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define if you have the memcpy function. */
#define HAVE_MEMCPY 1
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define if read-only mmap of a plain file works. */
//#define HAVE_MMAP_FILE 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
/* #undef HAVE_ALLOCA_H */
/* Define if mmap of /dev/zero works. */
//#define HAVE_MMAP_DEV_ZERO 1
/* Define if your assembler supports .cfi_* directives. */
/* #undef HAVE_AS_CFI_PSEUDO_OP */
/* Define if mmap with MAP_ANON(YMOUS) works. */
//#define HAVE_MMAP_ANON 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* The number of bytes in type double */
#define SIZEOF_DOUBLE 8
/* Define if your assembler and linker support unaligned PC relative relocs.
*/
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* The number of bytes in type long double */
#define SIZEOF_LONG_DOUBLE 12
/* Define if your assembler supports PC relative relocs. */
/* #undef HAVE_AS_X86_PCREL */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define if __attribute__((visibility("hidden"))) is supported. */
/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
/* Define to 1 if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */
/* Define if you have the long double type and it is bigger than a double */
#define HAVE_LONG_DOUBLE 1
/* #undef HAVE_LONG_DOUBLE */
/* whether byteorder is bigendian */
/* #undef WORDS_BIGENDIAN */
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
/* Define if the host machine stores words of multi-word integers in
big-endian order. */
/* #undef HOST_WORDS_BIG_ENDIAN */
/* Define to 1 if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H */
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
#define BYTEORDER 1234
/* Define to 1 if you have the `mmap' function. */
/* #undef HAVE_MMAP */
/* Define if your assembler and linker support unaligned PC relative relocs. */
/* #undef HAVE_AS_SPARC_UA_PCREL */
/* Define if mmap with MAP_ANON(YMOUS) works. */
/* #undef HAVE_MMAP_ANON */
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
/* Define if read-only mmap of a plain file works. */
/* #undef HAVE_MMAP_FILE */
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
/* Define to the flags needed for the .section .eh_frame directive. */
/* #define EH_FRAME_FLAGS "aw" */
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to the flags needed for the .section .eh_frame directive. */
/* #define EH_FRAME_FLAGS "aw" */
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define this is you do not want support for aggregate types. */
/* #undef FFI_NO_STRUCTS */
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define this is you do not want support for the raw API. */
/* #undef FFI_NO_RAW_API */
/* Define to 1 if you have the <sys/mman.h> header file. */
/* #undef HAVE_SYS_MMAN_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
/* #undef HAVE_SYS_STAT_H */
/* Define to 1 if you have the <sys/types.h> header file. */
/* #undef HAVE_SYS_TYPES_H */
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
/* #undef LT_OBJDIR */
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
/* #undef PACKAGE */
/* Define to the address where bug reports for this package should be sent. */
/* #undef PACKAGE_BUGREPORT */
/* Define to the full name of this package. */
/* #undef PACKAGE_NAME */
/* Define to the full name and version of this package. */
/* #undef PACKAGE_STRING */
/* Define to the one symbol short name of this package. */
/* #undef PACKAGE_TARNAME */
/* Define to the home page for this package. */
/* #undef PACKAGE_URL */
/* Define this if you are using Purify and want to suppress spurious messages. */
/* Define to the version of this package. */
/* #undef PACKAGE_VERSION */
/* The size of `double', as computed by sizeof. */
#define SIZEOF_DOUBLE 8
/* The size of `long double', as computed by sizeof. */
#undef SIZEOF_LONG_DOUBLE
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at runtime.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define this if you are using Purify and want to suppress spurious messages.
*/
/* #undef USING_PURIFY */
/* Version number of package */
/* #undef VERSION */
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE
#ifdef LIBFFI_ASM
#define FFI_HIDDEN(name) .hidden name
#else
#define FFI_HIDDEN __attribute__ ((visibility ("hidden")))
#endif
#else
#ifdef LIBFFI_ASM
#define FFI_HIDDEN(name)
#else
#define FFI_HIDDEN
#endif
#endif
/* -----------------------------------------------------------------*-C-*-
ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
Target configuration macros for x86 and x86-64.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef LIBFFI_TARGET_H
#define LIBFFI_TARGET_H
/* ---- System specific configurations ----------------------------------- */
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#define X86
#endif
/* ---- Generic type definitions ----------------------------------------- */
#ifndef LIBFFI_ASM
#ifndef _WIN64
typedef unsigned long ffi_arg;
#else
typedef unsigned __int64 ffi_arg;
#endif
typedef signed long ffi_sarg;
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
/* ---- Intel x86 Win32 ---------- */
FFI_SYSV,
#ifndef _WIN64
FFI_STDCALL,
#endif
/* TODO: Add fastcall support for the sake of completeness */
FFI_DEFAULT_ABI = FFI_SYSV,
/* ---- Intel x86 and AMD x86-64 - */
/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
/* FFI_SYSV, */
/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */
/* #ifdef __i386__ */
/* FFI_DEFAULT_ABI = FFI_SYSV, */
/* #else */
/* FFI_DEFAULT_ABI = FFI_UNIX64, */
/* #endif */
/* #endif */
FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
} ffi_abi;
#endif
/* ---- Definitions for closures ----------------------------------------- */
#define FFI_CLOSURES 1
#ifdef _WIN64
#define FFI_TRAMPOLINE_SIZE 29
#define FFI_NATIVE_RAW_API 0
#else
#define FFI_TRAMPOLINE_SIZE 15
#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
#endif
#endif
/* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
/* Round up to FFI_SIZEOF_ARG. */
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
/* Perform machine independent initialization of aggregate type
specifications. */
static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
{
ffi_type **ptr;
FFI_ASSERT(arg != NULL);
/*@-usedef@*/
FFI_ASSERT(arg->elements != NULL);
FFI_ASSERT(arg->size == 0);
FFI_ASSERT(arg->alignment == 0);
ptr = &(arg->elements[0]);
while ((*ptr) != NULL)
{
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type */
FFI_ASSERT_VALID_TYPE(*ptr);
arg->size = ALIGN(arg->size, (*ptr)->alignment);
arg->size += (*ptr)->size;
arg->alignment = (arg->alignment > (*ptr)->alignment) ?
arg->alignment : (*ptr)->alignment;
ptr++;
}
/* Structure size includes tail padding. This is important for
structures that fit in one register on ABIs like the PowerPC64
Linux ABI that right justify small structs in a register.
It's also needed for nested structure layout, for example
struct A { long a; char b; }; struct B { struct A x; char y; };
should find y at an offset of 2*sizeof(long) and result in a
total size of 3*sizeof(long). */
arg->size = ALIGN (arg->size, arg->alignment);
if (arg->size == 0)
return FFI_BAD_TYPEDEF;
else
return FFI_OK;
/*@=usedef@*/
}
/* Perform machine independent ffi_cif preparation, then call
machine dependent routine. */
ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
ffi_abi abi, unsigned int nargs,
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
/*@dependent@*/ ffi_type **atypes)
{
unsigned bytes = 0;
unsigned int i;
ffi_type **ptr;
FFI_ASSERT(cif != NULL);
FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
cif->abi = abi;
cif->arg_types = atypes;
cif->nargs = nargs;
cif->rtype = rtype;
cif->flags = 0;
/* Initialize the return type if necessary */
/*@-usedef@*/
if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
return FFI_BAD_TYPEDEF;
/*@=usedef@*/
/* Perform a sanity check on the return type */
FFI_ASSERT_VALID_TYPE(cif->rtype);
/* x86-64 and s390 stack space allocation is handled in prep_machdep. */
#if !defined M68K && !defined __x86_64__ && !defined S390
/* Make space for the return structure pointer */
if (cif->rtype->type == FFI_TYPE_STRUCT
/* MSVC returns small structures in registers. But we have a different
workaround: pretend int32 or int64 return type, and converting to
structure afterwards. */
#ifdef SPARC
&& (cif->abi != FFI_V9 || cif->rtype->size > 32)
#endif
)
bytes = STACK_ARG_SIZE(sizeof(void*));
#endif
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
{
/* Initialize any uninitialized aggregate type definitions */
if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
return FFI_BAD_TYPEDEF;
/* Perform a sanity check on the argument type, do this
check after the initialization. */
FFI_ASSERT_VALID_TYPE(*ptr);
#if !defined __x86_64__ && !defined S390
#ifdef SPARC
if (((*ptr)->type == FFI_TYPE_STRUCT
&& ((*ptr)->size > 16 || cif->abi != FFI_V9))
|| ((*ptr)->type == FFI_TYPE_LONGDOUBLE
&& cif->abi != FFI_V9))
bytes += sizeof(void*);
else
#endif
{
#if !defined(_MSC_VER) && !defined(__MINGW32__)
/* Don't know if this is a libffi bug or not. At least on
Windows with MSVC, function call parameters are *not*
aligned in the same way as structure fields are, they are
only aligned in integer boundaries.
This doesn't do any harm for cdecl functions and closures,
since the caller cleans up the stack, but it is wrong for
stdcall functions where the callee cleans.
*/
/* Add any padding if necessary */
if (((*ptr)->alignment - 1) & bytes)
bytes = ALIGN(bytes, (*ptr)->alignment);
#endif
bytes += (unsigned)STACK_ARG_SIZE((*ptr)->size);
}
#endif
}
cif->bytes = bytes;
/* Perform machine dependent cif processing */
return ffi_prep_cif_machdep(cif);
}
/* -----------------------------------------------------------------------
types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
Predefined ffi_types needed by libffi.
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 CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#include <ffi.h>
#include <ffi_common.h>
/* Type definitions */
#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
/* Size and alignment are fake here. They must not be 0. */
FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
|| defined IA64
FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
#else
FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
#endif
#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
#elif defined SH
FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
#else
FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
#endif
#if defined X86 || defined X86_WIN32 || defined M68K
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
#elif defined SPARC
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
#ifdef SPARC64
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
#else
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
#endif
#elif defined X86_64
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
#else
FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
#endif
/* -----------------------------------------------------------------------
win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
Copyright (c) 2001 John Beniton
Copyright (c) 2002 Ranjit Mathew
X86 Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
/* theller: almost verbatim translation from gas syntax to MSVC inline
assembler code. */
/* theller: ffi_call_x86 now returns an integer - the difference of the stack
pointer before and after the function call. If everything is ok, zero is
returned. If stdcall functions are passed the wrong number of arguments,
the difference will be nonzero. */
#include <ffi.h>
#include <ffi_common.h>
__declspec(naked) int
ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
extended_cif *ecif, /* 12 */
unsigned bytes, /* 16 */
unsigned flags, /* 20 */
unsigned *rvalue, /* 24 */
void (*fn)()) /* 28 */
{
_asm {
push ebp
mov ebp, esp
push esi // NEW: this register must be preserved across function calls
// XXX SAVE ESP NOW!
mov esi, esp // save stack pointer before the call
// Make room for all of the new args.
mov ecx, [ebp+16]
sub esp, ecx // sub esp, bytes
mov eax, esp
// Place all of the ffi_prep_args in position
push [ebp + 12] // ecif
push eax
call [ebp + 8] // prepfunc
// Return stack to previous state and call the function
add esp, 8
// FIXME: Align the stack to a 128-bit boundary to avoid
// potential performance hits.
call [ebp + 28]
// Load ecif->cif->abi
mov ecx, [ebp + 12]
mov ecx, [ecx]ecif.cif
mov ecx, [ecx]ecif.cif.abi
cmp ecx, FFI_STDCALL
je noclean
// STDCALL: Remove the space we pushed for the args
mov ecx, [ebp + 16]
add esp, ecx
// CDECL: Caller has already cleaned the stack
noclean:
// Check that esp has the same value as before!
sub esi, esp
// Load %ecx with the return type code
mov ecx, [ebp + 20]
// If the return value pointer is NULL, assume no return value.
/*
Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
otherwise only one BYTE will be compared (instead of a DWORD)!
*/
cmp DWORD PTR [ebp + 24], 0
jne sc_retint
// Even if there is no space for the return value, we are
// obliged to handle floating-point values.
cmp ecx, FFI_TYPE_FLOAT
jne sc_noretval
// fstp %st(0)
fstp st(0)
jmp sc_epilogue
sc_retint:
cmp ecx, FFI_TYPE_INT
jne sc_retfloat
// # Load %ecx with the pointer to storage for the return value
mov ecx, [ebp + 24]
mov [ecx + 0], eax
jmp sc_epilogue
sc_retfloat:
cmp ecx, FFI_TYPE_FLOAT
jne sc_retdouble
// Load %ecx with the pointer to storage for the return value
mov ecx, [ebp+24]
// fstps (%ecx)
fstp DWORD PTR [ecx]
jmp sc_epilogue
sc_retdouble:
cmp ecx, FFI_TYPE_DOUBLE
jne sc_retlongdouble
// movl 24(%ebp),%ecx
mov ecx, [ebp+24]
fstp QWORD PTR [ecx]
jmp sc_epilogue
jmp sc_retlongdouble // avoid warning about unused label
sc_retlongdouble:
cmp ecx, FFI_TYPE_LONGDOUBLE
jne sc_retint64
// Load %ecx with the pointer to storage for the return value
mov ecx, [ebp+24]
// fstpt (%ecx)
fstp QWORD PTR [ecx] /* XXX ??? */
jmp sc_epilogue
sc_retint64:
cmp ecx, FFI_TYPE_SINT64
jne sc_retstruct
// Load %ecx with the pointer to storage for the return value
mov ecx, [ebp+24]
mov [ecx+0], eax
mov [ecx+4], edx
sc_retstruct:
// Nothing to do!
sc_noretval:
sc_epilogue:
mov eax, esi
pop esi // NEW restore: must be preserved across function calls
mov esp, ebp
pop ebp
ret
}
}
PUBLIC ffi_call_AMD64
EXTRN __chkstk:NEAR
EXTRN ffi_closure_SYSV:NEAR
_TEXT SEGMENT
;;; ffi_closure_OUTER will be called with these registers set:
;;; rax points to 'closure'
;;; r11 contains a bit mask that specifies which of the
;;; first four parameters are float or double
;;;
;;; It must move the parameters passed in registers to their stack location,
;;; call ffi_closure_SYSV for the actual work, then return the result.
;;;
ffi_closure_OUTER PROC FRAME
;; save actual arguments to their stack space.
test r11, 1
jne first_is_float
mov QWORD PTR [rsp+8], rcx
jmp second
first_is_float:
movlpd QWORD PTR [rsp+8], xmm0
second:
test r11, 2
jne second_is_float
mov QWORD PTR [rsp+16], rdx
jmp third
second_is_float:
movlpd QWORD PTR [rsp+16], xmm1
third:
test r11, 4
jne third_is_float
mov QWORD PTR [rsp+24], r8
jmp forth
third_is_float:
movlpd QWORD PTR [rsp+24], xmm2
forth:
test r11, 8
jne forth_is_float
mov QWORD PTR [rsp+32], r9
jmp done
forth_is_float:
movlpd QWORD PTR [rsp+32], xmm3
done:
.ALLOCSTACK 40
sub rsp, 40
.ENDPROLOG
mov rcx, rax ; context is first parameter
mov rdx, rsp ; stack is second parameter
add rdx, 40 ; correct our own area
mov rax, ffi_closure_SYSV
call rax ; call the real closure function
;; Here, code is missing that handles float return values
add rsp, 40
movd xmm0, rax ; In case the closure returned a float.
ret 0
ffi_closure_OUTER ENDP
;;; ffi_call_AMD64
stack$ = 0
prepfunc$ = 32
ecif$ = 40
bytes$ = 48
flags$ = 56
rvalue$ = 64
fn$ = 72
ffi_call_AMD64 PROC FRAME
mov QWORD PTR [rsp+32], r9
mov QWORD PTR [rsp+24], r8
mov QWORD PTR [rsp+16], rdx
mov QWORD PTR [rsp+8], rcx
.PUSHREG rbp
push rbp
.ALLOCSTACK 48
sub rsp, 48 ; 00000030H
.SETFRAME rbp, 32
lea rbp, QWORD PTR [rsp+32]
.ENDPROLOG
mov eax, DWORD PTR bytes$[rbp]
add rax, 15
and rax, -16
call __chkstk
sub rsp, rax
lea rax, QWORD PTR [rsp+32]
mov QWORD PTR stack$[rbp], rax
mov rdx, QWORD PTR ecif$[rbp]
mov rcx, QWORD PTR stack$[rbp]
call QWORD PTR prepfunc$[rbp]
mov rsp, QWORD PTR stack$[rbp]
movlpd xmm3, QWORD PTR [rsp+24]
movd r9, xmm3
movlpd xmm2, QWORD PTR [rsp+16]
movd r8, xmm2
movlpd xmm1, QWORD PTR [rsp+8]
movd rdx, xmm1
movlpd xmm0, QWORD PTR [rsp]
movd rcx, xmm0
call QWORD PTR fn$[rbp]
ret_int$:
cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
jne ret_float$
mov rcx, QWORD PTR rvalue$[rbp]
mov DWORD PTR [rcx], eax
jmp SHORT ret_nothing$
ret_float$:
cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
jne SHORT ret_double$
mov rax, QWORD PTR rvalue$[rbp]
movlpd QWORD PTR [rax], xmm0
jmp SHORT ret_nothing$
ret_double$:
cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
jne SHORT ret_int64$
mov rax, QWORD PTR rvalue$[rbp]
movlpd QWORD PTR [rax], xmm0
jmp SHORT ret_nothing$
ret_int64$:
cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
jne ret_nothing$
mov rcx, QWORD PTR rvalue$[rbp]
mov QWORD PTR [rcx], rax
jmp SHORT ret_nothing$
ret_nothing$:
xor eax, eax
lea rsp, QWORD PTR [rbp+16]
pop rbp
ret 0
ffi_call_AMD64 ENDP
_TEXT ENDS
END
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Version="9,00"
Name="_ctypes"
ProjectGUID="{0E9791DB-593A-465F-98BC-681011311618}"
RootNamespace="_ctypes"
......@@ -42,7 +42,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN32"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -103,7 +104,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN64"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -164,7 +166,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN32"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -228,7 +231,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN64"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -291,7 +295,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN32"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -355,7 +360,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN64"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -419,7 +425,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN32"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -483,7 +490,8 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc"
AdditionalIncludeDirectories="..\Modules\_ctypes\libffi_msvc;..\Modules\_ctypes\libffi\include;..\Modules\_ctypes\libffi\src\x86"
PreprocessorDefinitions="X86_WIN64"
/>
<Tool
Name="VCManagedResourceCompilerTool"
......@@ -543,7 +551,7 @@
>
</File>
<File
RelativePath="..\Modules\_ctypes\libffi_msvc\ffi_common.h"
RelativePath="..\Modules\_ctypes\libffi\include\ffi_common.h"
>
</File>
<File
......@@ -551,7 +559,7 @@
>
</File>
<File
RelativePath="..\Modules\_ctypes\libffi_msvc\ffitarget.h"
RelativePath="..\Modules\_ctypes\libffi\src\x86\ffitarget.h"
>
</File>
</Filter>
......@@ -575,15 +583,23 @@
>
</File>
<File
RelativePath="..\Modules\_ctypes\libffi_msvc\ffi.c"
RelativePath="..\Modules\_ctypes\libffi\src\x86\ffi.c"
>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="X86_WIN64"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\Modules\_ctypes\malloc_closure.c"
>
</File>
<File
RelativePath="..\Modules\_ctypes\libffi_msvc\prep_cif.c"
RelativePath="..\Modules\_ctypes\libffi\src\prep_cif.c"
>
</File>
<File
......@@ -591,14 +607,32 @@
>
</File>
<File
RelativePath="..\Modules\_ctypes\libffi_msvc\win32.c"
RelativePath="..\Modules\_ctypes\libffi\src\x86\win32.S"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /Zi /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
......@@ -606,7 +640,16 @@
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="PGInstrument|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /Zi /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
......@@ -614,7 +657,16 @@
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
Name="VCCustomBuildTool"
/>
</FileConfiguration>
<FileConfiguration
Name="PGUpdate|Win32"
>
<Tool
Name="VCCustomBuildTool"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml /nologo /Zi /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
......@@ -622,12 +674,12 @@
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
Name="VCCustomBuildTool"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\Modules\_ctypes\libffi_msvc\win64.asm"
RelativePath="..\Modules\_ctypes\libffi\src\x86\win64.S"
>
<FileConfiguration
Name="Debug|Win32"
......@@ -642,8 +694,8 @@
>
<Tool
Name="VCCustomBuildTool"
CommandLine="ml64 /nologo /c /Zi /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\win64.obj"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /Zi /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
......@@ -659,8 +711,8 @@
>
<Tool
Name="VCCustomBuildTool"
CommandLine="ml64 /nologo /c /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\win64.obj"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
......@@ -676,8 +728,8 @@
>
<Tool
Name="VCCustomBuildTool"
CommandLine="ml64 /nologo /c /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\win64.obj"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
<FileConfiguration
......@@ -693,8 +745,8 @@
>
<Tool
Name="VCCustomBuildTool"
CommandLine="ml64 /nologo /c /Fo &quot;$(IntDir)\win64.obj&quot; &quot;$(InputPath)&quot;&#x0D;&#x0A;"
Outputs="$(IntDir)\win64.obj"
CommandLine="cl /nologo /EP /I ..\Modules\_ctypes\libffi_msvc /I ..\Modules\_ctypes\libffi\src\x86 $(InputPath) &gt; $(IntDir)$(InputName).asm&#x0D;&#x0A;ml64 /nologo /c /Fo $(IntDir)$(InputName).obj $(IntDir)$(InputName).asm&#x0D;&#x0A;"
Outputs="$(IntDir)$(InputName).obj"
/>
</FileConfiguration>
</File>
......
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