From bdb2b7fa251170fbb35192b3d832e8fb24913a21 Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Thu, 6 Feb 2020 20:45:43 -0700 Subject: [PATCH] Add windows libffi.dll and remove old code --- common/ffi.h | 331 ---------------- common/ffi_common.h | 77 ---- common/fficonfig.h | 96 ----- common/ffitarget.h | 150 ------- common/malloc_closure.c | 110 ------ common/raw_api.c | 254 ------------ gcc/closures.c | 627 ------------------------------ gcc/ffi.c | 841 ---------------------------------------- gcc/ffi64.c | 673 -------------------------------- gcc/prep_cif.c | 237 ----------- gcc/types.c | 77 ---- gcc/win32_asm.asm | 759 ------------------------------------ gcc/win32_asm.s | 736 ----------------------------------- gcc/win64_asm.asm | 467 ---------------------- gcc/win64_asm.s | 227 ----------- libffi.nim | 31 +- libs/win32/libffi-7.dll | Bin 0 -> 70845 bytes libs/win64/libffi-7.dll | Bin 0 -> 73112 bytes msvc/ffi.c | 457 ---------------------- msvc/prep_cif.c | 175 --------- msvc/types.c | 104 ----- msvc/win32.c | 162 -------- msvc/win32_asm.asm | 470 ---------------------- msvc/win64_asm.asm | 156 -------- 24 files changed, 5 insertions(+), 7212 deletions(-) delete mode 100644 common/ffi.h delete mode 100644 common/ffi_common.h delete mode 100644 common/fficonfig.h delete mode 100644 common/ffitarget.h delete mode 100644 common/malloc_closure.c delete mode 100644 common/raw_api.c delete mode 100644 gcc/closures.c delete mode 100644 gcc/ffi.c delete mode 100644 gcc/ffi64.c delete mode 100644 gcc/prep_cif.c delete mode 100644 gcc/types.c delete mode 100644 gcc/win32_asm.asm delete mode 100644 gcc/win32_asm.s delete mode 100644 gcc/win64_asm.asm delete mode 100644 gcc/win64_asm.s create mode 100644 libs/win32/libffi-7.dll create mode 100644 libs/win64/libffi-7.dll delete mode 100644 msvc/ffi.c delete mode 100644 msvc/prep_cif.c delete mode 100644 msvc/types.c delete mode 100644 msvc/win32.c delete mode 100644 msvc/win32_asm.asm delete mode 100644 msvc/win64_asm.asm diff --git a/common/ffi.h b/common/ffi.h deleted file mode 100644 index 07d650e..0000000 --- a/common/ffi.h +++ /dev/null @@ -1,331 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - libffi 2.00-beta - 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. - - ----------------------------------------------------------------------- */ - -/* ------------------------------------------------------------------- - The basic API is described in the README file. - - The raw API is designed to bypass some of the argument packing - and unpacking on architectures for which it can be avoided. - - The closure API allows interpreted functions to be packaged up - inside a C function pointer, so that they can be called as C functions, - with no understanding on the client side that they are interpreted. - It can also be used in other cases in which it is necessary to package - up a user specified parameter and a function pointer as a single - function pointer. - - The closure API must be implemented in order to get its functionality, - e.g. for use by gij. Routines are provided to emulate the raw API - if the underlying platform doesn't allow faster implementation. - - More details on the raw and cloure API can be found in: - - http://gcc.gnu.org/ml/java/1999-q3/msg00138.html - - and - - http://gcc.gnu.org/ml/java/1999-q3/msg00174.html - -------------------------------------------------------------------- */ - -#ifndef LIBFFI_H -#define LIBFFI_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Specify which architecture libffi is configured for. */ -//XXX #define X86 - -/* ---- System configuration information --------------------------------- */ - -#include - -#ifndef LIBFFI_ASM - -#include -#include - -/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). - But we can find it either under the correct ANSI name, or under GNU - C's internal name. */ -#ifdef LONG_LONG_MAX -# define FFI_LONG_LONG_MAX LONG_LONG_MAX -#else -# ifdef LLONG_MAX -# define FFI_LONG_LONG_MAX LLONG_MAX -# else -# ifdef __GNUC__ -# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ -# endif -# ifdef _MSC_VER -# define FFI_LONG_LONG_MAX _I64_MAX -# endif -# endif -#endif - -#if SCHAR_MAX == 127 -# define ffi_type_uchar ffi_type_uint8 -# define ffi_type_schar ffi_type_sint8 -#else - #error "char size not supported" -#endif - -#if SHRT_MAX == 32767 -# define ffi_type_ushort ffi_type_uint16 -# define ffi_type_sshort ffi_type_sint16 -#elif SHRT_MAX == 2147483647 -# define ffi_type_ushort ffi_type_uint32 -# define ffi_type_sshort ffi_type_sint32 -#else - #error "short size not supported" -#endif - -#if INT_MAX == 32767 -# define ffi_type_uint ffi_type_uint16 -# define ffi_type_sint ffi_type_sint16 -#elif INT_MAX == 2147483647 -# define ffi_type_uint ffi_type_uint32 -# define ffi_type_sint ffi_type_sint32 -#elif INT_MAX == 9223372036854775807 -# define ffi_type_uint ffi_type_uint64 -# define ffi_type_sint ffi_type_sint64 -#else - #error "int size not supported" -#endif - -#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" -# 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; - -/* These are defined in types.c */ -extern const ffi_type ffi_type_void; -extern const ffi_type ffi_type_uint8; -extern const ffi_type ffi_type_sint8; -extern const ffi_type ffi_type_uint16; -extern const ffi_type ffi_type_sint16; -extern const ffi_type ffi_type_uint32; -extern const ffi_type ffi_type_sint32; -extern const ffi_type ffi_type_uint64; -extern const ffi_type ffi_type_sint64; -extern const ffi_type ffi_type_float; -extern const ffi_type ffi_type_double; -extern const ffi_type ffi_type_longdouble; -extern const ffi_type ffi_type_pointer; - - -typedef enum { - FFI_OK = 0, - FFI_BAD_TYPEDEF, - FFI_BAD_ABI -} ffi_status; - -typedef unsigned FFI_TYPE; - -typedef struct { - ffi_abi abi; - unsigned nargs; - /*@dependent@*/ ffi_type **arg_types; - /*@dependent@*/ ffi_type *rtype; - unsigned bytes; - unsigned flags; -#ifdef FFI_EXTRA_CIF_FIELDS - FFI_EXTRA_CIF_FIELDS; -#endif -} ffi_cif; - -/* ---- Definitions for the raw API -------------------------------------- */ - -#ifdef _WIN64 -#define FFI_SIZEOF_ARG 8 -#else -#define FFI_SIZEOF_ARG 4 -#endif - -typedef union { - ffi_sarg sint; - ffi_arg uint; - float flt; - char data[FFI_SIZEOF_ARG]; - void* ptr; -} ffi_raw; - -void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, - void (*fn)(), - /*@out@*/ void *rvalue, - /*@dependent@*/ ffi_raw *avalue); - -void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); -void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); -size_t ffi_raw_size (ffi_cif *cif); - -/* This is analogous to the raw API, except it uses Java parameter */ -/* packing, even on 64-bit machines. I.e. on 64-bit machines */ -/* longs and doubles are followed by an empty 64-bit word. */ - -void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, - void (*fn)(), - /*@out@*/ void *rvalue, - /*@dependent@*/ ffi_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); -size_t ffi_java_raw_size (ffi_cif *cif); - -/* ---- Definitions for closures ----------------------------------------- */ - -#if FFI_CLOSURES - -typedef struct { - char tramp[FFI_TRAMPOLINE_SIZE]; - ffi_cif *cif; - void (*fun)(ffi_cif*,void*,void**,void*); - void *user_data; -} ffi_closure; - -void ffi_closure_free(void *); -void *ffi_closure_alloc (size_t size, void **code); - -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]; - - ffi_cif *cif; - -#if !FFI_NATIVE_RAW_API - - /* if this is enabled, then a raw closure has the same layout - as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ - - void (*translate_args)(ffi_cif*,void*,void**,void*); - void *this_closure; - -#endif - - void (*fun)(ffi_cif*,void*,ffi_raw*,void*); - void *user_data; - -} ffi_raw_closure; - -ffi_status -ffi_prep_raw_closure (ffi_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data); - -ffi_status -ffi_prep_java_raw_closure (ffi_raw_closure*, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data); - -#endif /* FFI_CLOSURES */ - -/* ---- Public interface definition -------------------------------------- */ - -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); - -void -ffi_call(/*@dependent@*/ ffi_cif *cif, - void (*fn)(), - /*@out@*/ void *rvalue, - /*@dependent@*/ void **avalue); - -/* Useful for eliminating compiler warnings */ -#define FFI_FN(f) ((void (*)())f) - -/* ---- Definitions shared with assembly code ---------------------------- */ - -#endif - -/* If these change, update src/mips/ffitarget.h. */ -#define FFI_TYPE_VOID 0 -#define FFI_TYPE_INT 1 -#define FFI_TYPE_FLOAT 2 -#define FFI_TYPE_DOUBLE 3 -#if 1 -#define FFI_TYPE_LONGDOUBLE 4 -#else -#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE -#endif -#define FFI_TYPE_UINT8 5 -#define FFI_TYPE_SINT8 6 -#define FFI_TYPE_UINT16 7 -#define FFI_TYPE_SINT16 8 -#define FFI_TYPE_UINT32 9 -#define FFI_TYPE_SINT32 10 -#define FFI_TYPE_UINT64 11 -#define FFI_TYPE_SINT64 12 -#define FFI_TYPE_STRUCT 13 -#define FFI_TYPE_POINTER 14 - -/* This should always refer to the last type code (for sanity checks) */ -#define FFI_TYPE_LAST FFI_TYPE_POINTER - -#define FFI_HIDDEN /* no idea what the origial definition looks like ... */ - -#ifdef __GNUC__ -# define LIKELY(x) __builtin_expect(x, 1) -# define UNLIKELY(x) __builtin_expect(x, 0) -#else -# define LIKELY(x) (x) -# define UNLIKELY(x) (x) -#endif - -#define MAYBE_UNUSED - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/common/ffi_common.h b/common/ffi_common.h deleted file mode 100644 index 43fb83b..0000000 --- a/common/ffi_common.h +++ /dev/null @@ -1,77 +0,0 @@ -/* ----------------------------------------------------------------------- - 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 -#include - -/* Check for the existence of memcpy. */ -#if STDC_HEADERS -# include -#else -# ifndef HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# endif -#endif - -#if defined(FFI_DEBUG) -#include -#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 - - diff --git a/common/fficonfig.h b/common/fficonfig.h deleted file mode 100644 index c14f653..0000000 --- a/common/fficonfig.h +++ /dev/null @@ -1,96 +0,0 @@ -/* 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. */ - -/* Define this for MSVC, but not for mingw32! */ -#ifdef _MSC_VER -#define __attribute__(x) /* */ -#endif -#define alloca _alloca - -/*----------------------------------------------------------------*/ - -/* Define 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 if you have alloca, as a function or macro. */ -#define HAVE_ALLOCA 1 - -/* Define if you have and it should be used (not on Ultrix). */ -/* #define HAVE_ALLOCA_H 1 */ - -/* 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 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if you have the memcpy function. */ -#define HAVE_MEMCPY 1 - -/* Define if read-only mmap of a plain file works. */ -//#define HAVE_MMAP_FILE 1 - -/* Define if mmap of /dev/zero works. */ -//#define HAVE_MMAP_DEV_ZERO 1 - -/* Define if mmap with MAP_ANON(YMOUS) works. */ -//#define HAVE_MMAP_ANON 1 - -/* The number of bytes in type double */ -#define SIZEOF_DOUBLE 8 - -/* The number of bytes in type long double */ -#define SIZEOF_LONG_DOUBLE 12 - -/* Define if you have the long double type and it is bigger than a double */ -#define HAVE_LONG_DOUBLE 1 - -/* whether byteorder is bigendian */ -/* #undef WORDS_BIGENDIAN */ - -/* Define if the host machine stores words of multi-word integers in - big-endian order. */ -/* #undef HOST_WORDS_BIG_ENDIAN */ - -/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ -#define BYTEORDER 1234 - -/* Define if your assembler and linker support unaligned PC relative relocs. */ -/* #undef HAVE_AS_SPARC_UA_PCREL */ - -/* Define if your assembler supports .register. */ -/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ - -/* 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 the flags needed for the .section .eh_frame directive. */ -/* #define EH_FRAME_FLAGS "aw" */ - -/* Define this if you want extra debugging. */ -/* #undef FFI_DEBUG */ - -/* Define this is you do not want support for aggregate types. */ -/* #undef FFI_NO_STRUCTS */ - -/* Define this is you do not want support for the raw API. */ -/* #undef FFI_NO_RAW_API */ - -/* Define this if you are using Purify and want to suppress spurious messages. */ -/* #undef USING_PURIFY */ - diff --git a/common/ffitarget.h b/common/ffitarget.h deleted file mode 100644 index d8d60f2..0000000 --- a/common/ffitarget.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -----------------------------------------------------------------*-C-*- - ffitarget.h - Copyright (c) 2012 Anthony Green - Copyright (c) 1996-2003, 2010 Red Hat, Inc. - Copyright (C) 2008 Free Software Foundation, Inc. - - Target configuration macros for x86 and x86-64. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - ----------------------------------------------------------------------- */ - -#ifndef LIBFFI_TARGET_H -#define LIBFFI_TARGET_H - -#ifndef LIBFFI_H -#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." -#endif - -/* ---- System specific configurations ----------------------------------- */ - -/* For code common to all platforms on x86 and x86_64. */ -#define X86_ANY - -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) -# if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) -# define X86_64 -# define X86_WIN64 -# else -# define X86_32 -# define X86_WIN32 -# endif -#endif - -#if defined (X86_64) && defined (__i386__) -#undef X86_64 -#define X86 -#endif - -#ifdef X86_WIN64 -#define FFI_SIZEOF_ARG 8 -#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */ -#endif - -/* ---- Generic type definitions ----------------------------------------- */ - -#ifndef LIBFFI_ASM -#ifdef X86_WIN64 -#ifdef _MSC_VER -typedef unsigned __int64 ffi_arg; -typedef __int64 ffi_sarg; -#else -typedef unsigned long long ffi_arg; -typedef long long ffi_sarg; -#endif -#else -#if defined __x86_64__ && defined __ILP32__ -#define FFI_SIZEOF_ARG 8 -#define FFI_SIZEOF_JAVA_RAW 4 -typedef unsigned long long ffi_arg; -typedef long long ffi_sarg; -#else -typedef unsigned long ffi_arg; -typedef signed long ffi_sarg; -#endif -#endif - -typedef enum ffi_abi { - FFI_FIRST_ABI = 0, - - /* ---- Intel x86 Win32 ---------- */ -#ifdef X86_WIN32 - FFI_SYSV, - FFI_STDCALL, - FFI_THISCALL, - FFI_FASTCALL, - FFI_MS_CDECL, - FFI_LAST_ABI, -#ifdef _MSC_VER - FFI_DEFAULT_ABI = FFI_MS_CDECL -#else - FFI_DEFAULT_ABI = FFI_SYSV -#endif - -#elif defined(X86_WIN64) - FFI_WIN64, - FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_WIN64 - -#else - /* ---- Intel x86 and AMD x86-64 - */ - FFI_SYSV, - FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ - FFI_LAST_ABI, -#if defined(__i386__) || defined(__i386) - FFI_DEFAULT_ABI = FFI_SYSV -#else - FFI_DEFAULT_ABI = FFI_UNIX64 -#endif -#endif -} ffi_abi; -#endif - -/* ---- Definitions for closures ----------------------------------------- */ - -#define FFI_CLOSURES 1 -#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) -#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) -#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3) -#define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4) - -#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) -#define FFI_TRAMPOLINE_SIZE 24 -#define FFI_NATIVE_RAW_API 0 -#else -#ifdef X86_WIN32 -#define FFI_TRAMPOLINE_SIZE 52 -#else -#ifdef X86_WIN64 -#define FFI_TRAMPOLINE_SIZE 29 -#define FFI_NATIVE_RAW_API 0 -#define FFI_NO_RAW_API 1 -#else -#define FFI_TRAMPOLINE_SIZE 10 -#endif -#endif -#ifndef X86_WIN64 -#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ -#endif -#endif - -#endif - diff --git a/common/malloc_closure.c b/common/malloc_closure.c deleted file mode 100644 index 5b33aa4..0000000 --- a/common/malloc_closure.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#ifdef MS_WIN32 -#include -#else -#include -#include -# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -# define MAP_ANONYMOUS MAP_ANON -# endif -#endif -#include "ctypes.h" - -/* BLOCKSIZE can be adjusted. Larger blocksize will take a larger memory - overhead, but allocate less blocks from the system. It may be that some - systems have a limit of how many mmap'd blocks can be open. -*/ - -#define BLOCKSIZE _pagesize - -/* #define MALLOC_CLOSURE_DEBUG */ /* enable for some debugging output */ - -/******************************************************************/ - -typedef union _tagITEM { - ffi_closure closure; - union _tagITEM *next; -} ITEM; - -static ITEM *free_list; -static int _pagesize; - -static void more_core(void) -{ - ITEM *item; - int count, i; - -/* determine the pagesize */ -#ifdef MS_WIN32 - if (!_pagesize) { - SYSTEM_INFO systeminfo; - GetSystemInfo(&systeminfo); - _pagesize = systeminfo.dwPageSize; - } -#else - if (!_pagesize) { -#ifdef _SC_PAGESIZE - _pagesize = sysconf(_SC_PAGESIZE); -#else - _pagesize = getpagesize(); -#endif - } -#endif - - /* calculate the number of nodes to allocate */ - count = BLOCKSIZE / sizeof(ITEM); - - /* allocate a memory block */ -#ifdef MS_WIN32 - item = (ITEM *)VirtualAlloc(NULL, - count * sizeof(ITEM), - MEM_COMMIT, - PAGE_EXECUTE_READWRITE); - if (item == NULL) - return; -#else - item = (ITEM *)mmap(NULL, - count * sizeof(ITEM), - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, - 0); - if (item == (void *)MAP_FAILED) - return; -#endif - -#ifdef MALLOC_CLOSURE_DEBUG - printf("block at %p allocated (%d bytes), %d ITEMs\n", - item, count * sizeof(ITEM), count); -#endif - /* put them into the free list */ - for (i = 0; i < count; ++i) { - item->next = free_list; - free_list = item; - ++item; - } -} - -/******************************************************************/ - -/* put the item back into the free list */ -void ffi_closure_free(void *p) -{ - ITEM *item = (ITEM *)p; - item->next = free_list; - free_list = item; -} - -/* return one item from the free list, allocating more if needed */ -void *ffi_closure_alloc(size_t ignored, void** codeloc) -{ - ITEM *item; - if (!free_list) - more_core(); - if (!free_list) - return NULL; - item = free_list; - free_list = item->next; - *codeloc = (void *)item; - return (void *)item; -} diff --git a/common/raw_api.c b/common/raw_api.c deleted file mode 100644 index ce21372..0000000 --- a/common/raw_api.c +++ /dev/null @@ -1,254 +0,0 @@ -/* ----------------------------------------------------------------------- - raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc. - - Author: Kresten Krab Thorup - - 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. - ----------------------------------------------------------------------- */ - -/* This file defines generic functions for use with the raw api. */ - -#include -#include - -#if !FFI_NO_RAW_API - -size_t -ffi_raw_size (ffi_cif *cif) -{ - size_t result = 0; - int i; - - ffi_type **at = cif->arg_types; - - for (i = cif->nargs-1; i >= 0; i--, at++) - { -#if !FFI_NO_STRUCTS - if ((*at)->type == FFI_TYPE_STRUCT) - result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG); - else -#endif - result += ALIGN ((*at)->size, FFI_SIZEOF_ARG); - } - - return result; -} - - -void -ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) -{ - unsigned i; - ffi_type **tp = cif->arg_types; - -#if WORDS_BIGENDIAN - - for (i = 0; i < cif->nargs; i++, tp++, args++) - { - switch ((*tp)->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 1); - break; - - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 2); - break; - -#if FFI_SIZEOF_ARG >= 4 - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - *args = (void*) ((char*)(raw++) + FFI_SIZEOF_ARG - 4); - break; -#endif - -#if !FFI_NO_STRUCTS - case FFI_TYPE_STRUCT: - *args = (raw++)->ptr; - break; -#endif - - case FFI_TYPE_POINTER: - *args = (void*) &(raw++)->ptr; - break; - - default: - *args = raw; - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - } - } - -#else /* WORDS_BIGENDIAN */ - -#if !PDP - - /* then assume little endian */ - for (i = 0; i < cif->nargs; i++, tp++, args++) - { -#if !FFI_NO_STRUCTS - if ((*tp)->type == FFI_TYPE_STRUCT) - { - *args = (raw++)->ptr; - } - else -#endif - { - *args = (void*) raw; - raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); - } - } - -#else -#error "pdp endian not supported" -#endif /* ! PDP */ - -#endif /* WORDS_BIGENDIAN */ -} - -void -ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) -{ - unsigned i; - ffi_type **tp = cif->arg_types; - - for (i = 0; i < cif->nargs; i++, tp++, args++) - { - switch ((*tp)->type) - { - case FFI_TYPE_UINT8: - (raw++)->uint = *(UINT8*) (*args); - break; - - case FFI_TYPE_SINT8: - (raw++)->sint = *(SINT8*) (*args); - break; - - case FFI_TYPE_UINT16: - (raw++)->uint = *(UINT16*) (*args); - break; - - case FFI_TYPE_SINT16: - (raw++)->sint = *(SINT16*) (*args); - break; - -#if FFI_SIZEOF_ARG >= 4 - case FFI_TYPE_UINT32: - (raw++)->uint = *(UINT32*) (*args); - break; - - case FFI_TYPE_SINT32: - (raw++)->sint = *(SINT32*) (*args); - break; -#endif - -#if !FFI_NO_STRUCTS - case FFI_TYPE_STRUCT: - (raw++)->ptr = *args; - break; -#endif - - case FFI_TYPE_POINTER: - (raw++)->ptr = **(void***) args; - break; - - default: - memcpy ((void*) raw->data, (void*)*args, (*tp)->size); - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - } - } -} - -#if !FFI_NATIVE_RAW_API - - -/* This is a generic definition of ffi_raw_call, to be used if the - * native system does not provide a machine-specific implementation. - * Having this, allows code to be written for the raw API, without - * the need for system-specific code to handle input in that format; - * these following couple of functions will handle the translation forth - * and back automatically. */ - -void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *raw) -{ - void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); - ffi_raw_to_ptrarray (cif, raw, avalue); - ffi_call (cif, fn, rvalue, avalue); -} - -#if FFI_CLOSURES /* base system provides closures */ - -static void -ffi_translate_args (ffi_cif *cif, void *rvalue, - void **avalue, void *user_data) -{ - ffi_raw *raw = (ffi_raw*)alloca (ffi_raw_size (cif)); - ffi_raw_closure *cl = (ffi_raw_closure*)user_data; - - ffi_ptrarray_to_raw (cif, avalue, raw); - (*cl->fun) (cif, rvalue, raw, cl->user_data); -} - -ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure* cl, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc) -{ - ffi_status status; - - status = ffi_prep_closure_loc ((ffi_closure*) cl, - cif, - &ffi_translate_args, - codeloc, - codeloc); - if (status == FFI_OK) - { - cl->fun = fun; - cl->user_data = user_data; - } - - return status; -} - -#endif /* FFI_CLOSURES */ -#endif /* !FFI_NATIVE_RAW_API */ - -#if FFI_CLOSURES - -/* Again, here is the generic version of ffi_prep_raw_closure, which - * will install an intermediate "hub" for translation of arguments from - * the pointer-array format, to the raw format */ - -ffi_status -ffi_prep_raw_closure (ffi_raw_closure* cl, - ffi_cif *cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data) -{ - return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl); -} - -#endif /* FFI_CLOSURES */ - -#endif /* !FFI_NO_RAW_API */ diff --git a/gcc/closures.c b/gcc/closures.c deleted file mode 100644 index f12013e..0000000 --- a/gcc/closures.c +++ /dev/null @@ -1,627 +0,0 @@ -/* ----------------------------------------------------------------------- - closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc - Copyright (c) 2011 Plausible Labs Cooperative, Inc. - - Code to allocate and deallocate memory for closures. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#if defined __linux__ && !defined _GNU_SOURCE -#define _GNU_SOURCE 1 -#endif - -#include -#include - -#if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE -# if __gnu_linux__ -/* This macro indicates it may be forbidden to map anonymous memory - with both write and execute permission. Code compiled when this - option is defined will attempt to map such pages once, but if it - fails, it falls back to creating a temporary file in a writable and - executable filesystem and mapping pages from it into separate - locations in the virtual memory space, one location writable and - another executable. */ -# define FFI_MMAP_EXEC_WRIT 1 -# define HAVE_MNTENT 1 -# endif -# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__) -/* Windows systems may have Data Execution Protection (DEP) enabled, - which requires the use of VirtualMalloc/VirtualFree to alloc/free - executable memory. */ -# define FFI_MMAP_EXEC_WRIT 1 -# endif -#endif - -#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX -# ifdef __linux__ -/* When defined to 1 check for SELinux and if SELinux is active, - don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that - might cause audit messages. */ -# define FFI_MMAP_EXEC_SELINUX 1 -# endif -#endif - -#if FFI_CLOSURES - -# if FFI_EXEC_TRAMPOLINE_TABLE - -// Per-target implementation; It's unclear what can reasonable be shared -// between two OS/architecture implementations. - -# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ - -#define USE_LOCKS 1 -#define USE_DL_PREFIX 1 -#ifdef __GNUC__ -#ifndef USE_BUILTIN_FFS -#define USE_BUILTIN_FFS 1 -#endif -#endif - -/* We need to use mmap, not sbrk. */ -#define HAVE_MORECORE 0 - -/* We could, in theory, support mremap, but it wouldn't buy us anything. */ -#define HAVE_MREMAP 0 - -/* We have no use for this, so save some code and data. */ -#define NO_MALLINFO 1 - -/* We need all allocations to be in regular segments, otherwise we - lose track of the corresponding code address. */ -#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T - -/* Don't allocate more than a page unless needed. */ -#define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize) - -#if FFI_CLOSURE_TEST -/* Don't release single pages, to avoid a worst-case scenario of - continuously allocating and releasing single pages, but release - pairs of pages, which should do just as well given that allocations - are likely to be small. */ -#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize) -#endif - -#include -#include -#include -#include -#ifndef _MSC_VER -//#include -#endif -#include -#include -#if !defined(X86_WIN32) && !defined(X86_WIN64) -#ifdef HAVE_MNTENT -#include -#endif /* HAVE_MNTENT */ -#include -#include - -/* We don't want sys/mman.h to be included after we redefine mmap and - dlmunmap. */ -#include -#define LACKS_SYS_MMAN_H 1 - -#if FFI_MMAP_EXEC_SELINUX -#include -#include - -static int selinux_enabled = -1; - -static int -selinux_enabled_check (void) -{ - struct statfs sfs; - FILE *f; - char *buf = NULL; - size_t len = 0; - - if (statfs ("/selinux", &sfs) >= 0 - && (unsigned int) sfs.f_type == 0xf97cff8cU) - return 1; - f = fopen ("/proc/mounts", "r"); - if (f == NULL) - return 0; - while (getline (&buf, &len, f) >= 0) - { - char *p = strchr (buf, ' '); - if (p == NULL) - break; - p = strchr (p + 1, ' '); - if (p == NULL) - break; - if (strncmp (p + 1, "selinuxfs ", 10) == 0) - { - free (buf); - fclose (f); - return 1; - } - } - free (buf); - fclose (f); - return 0; -} - -#define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \ - : (selinux_enabled = selinux_enabled_check ())) - -#else - -#define is_selinux_enabled() 0 - -#endif /* !FFI_MMAP_EXEC_SELINUX */ - -/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */ -#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX -#include - -static int emutramp_enabled = -1; - -static int -emutramp_enabled_check (void) -{ - if (getenv ("FFI_DISABLE_EMUTRAMP") == NULL) - return 1; - else - return 0; -} - -#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \ - : (emutramp_enabled = emutramp_enabled_check ())) -#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */ - -#elif defined (__CYGWIN__) || defined(__INTERIX) - -#include - -/* Cygwin is Linux-like, but not quite that Linux-like. */ -#define is_selinux_enabled() 0 - -#endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */ - -#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX -#define is_emutramp_enabled() 0 -#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */ - -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) -/* Use these for mmap and munmap within dlmalloc.c. */ -static void *dlmmap(void *, size_t, int, int, int, off_t); -static int dlmunmap(void *, size_t); -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ - -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) - -/* A mutex used to synchronize access to *exec* variables in this file. */ -static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER; - -/* A file descriptor of a temporary file from which we'll map - executable pages. */ -static int execfd = -1; - -/* The amount of space already allocated from the temporary file. */ -static size_t execsize = 0; - -/* Open a temporary file name, and immediately unlink it. */ -static int -open_temp_exec_file_name (char *name) -{ - int fd = mkstemp (name); - - if (fd != -1) - unlink (name); - - return fd; -} - -/* Open a temporary file in the named directory. */ -static int -open_temp_exec_file_dir (const char *dir) -{ - static const char suffix[] = "/ffiXXXXXX"; - int lendir = strlen (dir); - char *tempname = __builtin_alloca (lendir + sizeof (suffix)); - - if (!tempname) - return -1; - - memcpy (tempname, dir, lendir); - memcpy (tempname + lendir, suffix, sizeof (suffix)); - - return open_temp_exec_file_name (tempname); -} - -/* Open a temporary file in the directory in the named environment - variable. */ -static int -open_temp_exec_file_env (const char *envvar) -{ - const char *value = getenv (envvar); - - if (!value) - return -1; - - return open_temp_exec_file_dir (value); -} - -#ifdef HAVE_MNTENT -/* Open a temporary file in an executable and writable mount point - listed in the mounts file. Subsequent calls with the same mounts - keep searching for mount points in the same file. Providing NULL - as the mounts file closes the file. */ -static int -open_temp_exec_file_mnt (const char *mounts) -{ - static const char *last_mounts; - static FILE *last_mntent; - - if (mounts != last_mounts) - { - if (last_mntent) - endmntent (last_mntent); - - last_mounts = mounts; - - if (mounts) - last_mntent = setmntent (mounts, "r"); - else - last_mntent = NULL; - } - - if (!last_mntent) - return -1; - - for (;;) - { - int fd; - struct mntent mnt; - char buf[MAXPATHLEN * 3]; - - if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)) == NULL) - return -1; - - if (hasmntopt (&mnt, "ro") - || hasmntopt (&mnt, "noexec") - || access (mnt.mnt_dir, W_OK)) - continue; - - fd = open_temp_exec_file_dir (mnt.mnt_dir); - - if (fd != -1) - return fd; - } -} -#endif /* HAVE_MNTENT */ - -/* Instructions to look for a location to hold a temporary file that - can be mapped in for execution. */ -static struct -{ - int (*func)(const char *); - const char *arg; - int repeat; -} open_temp_exec_file_opts[] = { - { open_temp_exec_file_env, "TMPDIR", 0 }, - { open_temp_exec_file_dir, "/tmp", 0 }, - { open_temp_exec_file_dir, "/var/tmp", 0 }, - { open_temp_exec_file_dir, "/dev/shm", 0 }, - { open_temp_exec_file_env, "HOME", 0 }, -#ifdef HAVE_MNTENT - { open_temp_exec_file_mnt, "/etc/mtab", 1 }, - { open_temp_exec_file_mnt, "/proc/mounts", 1 }, -#endif /* HAVE_MNTENT */ -}; - -/* Current index into open_temp_exec_file_opts. */ -static int open_temp_exec_file_opts_idx = 0; - -/* Reset a current multi-call func, then advances to the next entry. - If we're at the last, go back to the first and return nonzero, - otherwise return zero. */ -static int -open_temp_exec_file_opts_next (void) -{ - if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat) - open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL); - - open_temp_exec_file_opts_idx++; - if (open_temp_exec_file_opts_idx - == (sizeof (open_temp_exec_file_opts) - / sizeof (*open_temp_exec_file_opts))) - { - open_temp_exec_file_opts_idx = 0; - return 1; - } - - return 0; -} - -/* Return a file descriptor of a temporary zero-sized file in a - writable and exexutable filesystem. */ -static int -open_temp_exec_file (void) -{ - int fd; - - do - { - fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func - (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg); - - if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat - || fd == -1) - { - if (open_temp_exec_file_opts_next ()) - break; - } - } - while (fd == -1); - - return fd; -} - -/* Map in a chunk of memory from the temporary exec file into separate - locations in the virtual memory address space, one writable and one - executable. Returns the address of the writable portion, after - storing an offset to the corresponding executable portion at the - last word of the requested chunk. */ -static void * -dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) -{ - void *ptr; - - if (execfd == -1) - { - open_temp_exec_file_opts_idx = 0; - retry_open: - execfd = open_temp_exec_file (); - if (execfd == -1) - return MFAIL; - } - - offset = execsize; - - if (ftruncate (execfd, offset + length)) - return MFAIL; - - flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS); - flags |= MAP_SHARED; - - ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC, - flags, execfd, offset); - if (ptr == MFAIL) - { - if (!offset) - { - close (execfd); - goto retry_open; - } - ftruncate (execfd, offset); - return MFAIL; - } - else if (!offset - && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat) - open_temp_exec_file_opts_next (); - - start = mmap (start, length, prot, flags, execfd, offset); - - if (start == MFAIL) - { - munmap (ptr, length); - ftruncate (execfd, offset); - return start; - } - - mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start; - - execsize += length; - - return start; -} - -/* Map in a writable and executable chunk of memory if possible. - Failing that, fall back to dlmmap_locked. */ -static void * -dlmmap (void *start, size_t length, int prot, - int flags, int fd, off_t offset) -{ - void *ptr; - - assert (start == NULL && length % malloc_getpagesize == 0 - && prot == (PROT_READ | PROT_WRITE) - && flags == (MAP_PRIVATE | MAP_ANONYMOUS) - && fd == -1 && offset == 0); - -#if FFI_CLOSURE_TEST - printf ("mapping in %zi\n", length); -#endif - - if (execfd == -1 && is_emutramp_enabled ()) - { - ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset); - return ptr; - } - - if (execfd == -1 && !is_selinux_enabled ()) - { - ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset); - - if (ptr != MFAIL || (errno != EPERM && errno != EACCES)) - /* Cool, no need to mess with separate segments. */ - return ptr; - - /* If MREMAP_DUP is ever introduced and implemented, try mmap - with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with - MREMAP_DUP and prot at this point. */ - } - - if (execsize == 0 || execfd == -1) - { - pthread_mutex_lock (&open_temp_exec_file_mutex); - ptr = dlmmap_locked (start, length, prot, flags, offset); - pthread_mutex_unlock (&open_temp_exec_file_mutex); - - return ptr; - } - - return dlmmap_locked (start, length, prot, flags, offset); -} - -/* Release memory at the given address, as well as the corresponding - executable page if it's separate. */ -static int -dlmunmap (void *start, size_t length) -{ - /* We don't bother decreasing execsize or truncating the file, since - we can't quite tell whether we're unmapping the end of the file. - We don't expect frequent deallocation anyway. If we did, we - could locate pages in the file by writing to the pages being - deallocated and checking that the file contents change. - Yuck. */ - msegmentptr seg = segment_holding (gm, start); - void *code; - -#if FFI_CLOSURE_TEST - printf ("unmapping %zi\n", length); -#endif - - if (seg && (code = add_segment_exec_offset (start, seg)) != start) - { - int ret = munmap (code, length); - if (ret) - return ret; - } - - return munmap (start, length); -} - -#if FFI_CLOSURE_FREE_CODE -/* Return segment holding given code address. */ -static msegmentptr -segment_holding_code (mstate m, char* addr) -{ - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= add_segment_exec_offset (sp->base, sp) - && addr < add_segment_exec_offset (sp->base, sp) + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} -#endif - -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ - -/* Allocate a chunk of memory with the given size. Returns a pointer - to the writable address, and sets *CODE to the executable - corresponding virtual address. */ -void * -ffi_closure_alloc (size_t size, void **code) -{ - *code = malloc(size); - return *code; -#if 0 - void *ptr; - - if (!code) - return NULL; - - ptr = dlmalloc (size); - - if (ptr) - { - msegmentptr seg = segment_holding (gm, ptr); - - *code = add_segment_exec_offset (ptr, seg); - } - - return ptr; -#endif -} - -/* Release a chunk of memory allocated with ffi_closure_alloc. If - FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the - writable or the executable address given. Otherwise, only the - writable address can be provided here. */ -void -ffi_closure_free (void *ptr) -{ -#if 0 -#if FFI_CLOSURE_FREE_CODE - msegmentptr seg = segment_holding_code(gm, ptr); - - if (seg) - ptr = sub_segment_exec_offset(ptr, seg); -#endif - - dlfree(ptr); -#endif - free(ptr); -} - - -#if FFI_CLOSURE_TEST -/* Do some internal sanity testing to make sure allocation and - deallocation of pages are working as intended. */ -int main () -{ - void *p[3]; -#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0) -#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0) - GET (0, malloc_getpagesize / 2); - GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*)); - PUT (1); - GET (1, 2 * malloc_getpagesize); - GET (2, malloc_getpagesize / 2); - PUT (1); - PUT (0); - PUT (2); - return 0; -} -#endif /* FFI_CLOSURE_TEST */ -# else /* ! FFI_MMAP_EXEC_WRIT */ - -/* On many systems, memory returned by malloc is writable and - executable, so just use it. */ - -#include - -void * -ffi_closure_alloc (size_t size, void **code) -{ - if (!code) - return NULL; - - return *code = malloc (size); -} - -void -ffi_closure_free (void *ptr) -{ - free (ptr); -} - -# endif /* ! FFI_MMAP_EXEC_WRIT */ -#endif /* FFI_CLOSURES */ diff --git a/gcc/ffi.c b/gcc/ffi.c deleted file mode 100644 index 0600414..0000000 --- a/gcc/ffi.c +++ /dev/null @@ -1,841 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. - Copyright (c) 2002 Ranjit Mathew - Copyright (c) 2002 Bo Thorsen - Copyright (c) 2002 Roger Sayle - Copyright (C) 2008, 2010 Free Software Foundation, Inc. - - x86 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#if !defined(__x86_64__) || defined(_WIN64) - -#ifdef _WIN64 -#include -#endif - -#include -#include - -#include - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void ffi_prep_args(char *stack, extended_cif *ecif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; -#ifdef X86_WIN32 - size_t p_stack_args[2]; - void *p_stack_data[2]; - char *argp2 = stack; - int stack_args_count = 0; - int cabi = ecif->cif->abi; -#endif - - argp = stack; - - if ((ecif->cif->flags == FFI_TYPE_STRUCT - || ecif->cif->flags == FFI_TYPE_MS_STRUCT) -#ifdef X86_WIN64 - && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2 - && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8) -#endif - ) - { - *(void **) argp = ecif->rvalue; -#ifdef X86_WIN32 - /* For fastcall/thiscall this is first register-passed - argument. */ - if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL) - { - p_stack_args[stack_args_count] = sizeof (void*); - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } -#endif - argp += sizeof(void*); - } - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - i != 0; - i--, p_arg++) - { - size_t z; - - /* Align if necessary */ - if ((sizeof(void*) - 1) & (size_t) argp) - argp = (char *) ALIGN(argp, sizeof(void*)); - - z = (*p_arg)->size; -#ifdef X86_WIN64 - if (z > sizeof(ffi_arg) - || ((*p_arg)->type == FFI_TYPE_STRUCT - && (z != 1 && z != 2 && z != 4 && z != 8)) -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE) -#endif - ) - { - z = sizeof(ffi_arg); - *(void **)argp = *p_argv; - } - else if ((*p_arg)->type == FFI_TYPE_FLOAT) - { - memcpy(argp, *p_argv, z); - } - else -#endif - if (z < sizeof(ffi_arg)) - { - z = sizeof(ffi_arg); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: - *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - *(ffi_arg *) argp = *(ffi_arg *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else - { - memcpy(argp, *p_argv, z); - } - -#ifdef X86_WIN32 - /* For thiscall/fastcall convention register-passed arguments - are the first two none-floating-point arguments with a size - smaller or equal to sizeof (void*). */ - if ((cabi == FFI_THISCALL && stack_args_count < 1) - || (cabi == FFI_FASTCALL && stack_args_count < 2)) - { - if (z <= 4 - && ((*p_arg)->type != FFI_TYPE_FLOAT - && (*p_arg)->type != FFI_TYPE_STRUCT)) - { - p_stack_args[stack_args_count] = z; - p_stack_data[stack_args_count] = argp; - ++stack_args_count; - } - } -#endif - p_argv++; -#ifdef X86_WIN64 - argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); -#else - argp += z; -#endif - } - -#ifdef X86_WIN32 - /* We need to move the register-passed arguments for thiscall/fastcall - on top of stack, so that those can be moved to registers ecx/edx by - call-handler. */ - if (stack_args_count > 0) - { - size_t zz = (p_stack_args[0] + 3) & ~3; - char *h; - - /* Move first argument to top-stack position. */ - if (p_stack_data[0] != argp2) - { - h = alloca (zz + 1); - memcpy (h, p_stack_data[0], zz); - memmove (argp2 + zz, argp2, - (size_t) ((char *) p_stack_data[0] - (char*)argp2)); - memcpy (argp2, h, zz); - } - - argp2 += zz; - --stack_args_count; - if (zz > 4) - stack_args_count = 0; - - /* If we have a second argument, then move it on top - after the first one. */ - if (stack_args_count > 0 && p_stack_data[1] != argp2) - { - zz = p_stack_args[1]; - zz = (zz + 3) & ~3; - h = alloca (zz + 1); - h = alloca (zz + 1); - memcpy (h, p_stack_data[1], zz); - memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2)); - memcpy (argp2, h, zz); - } - } -#endif - return; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - unsigned int i; - ffi_type **ptr; - - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_UINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT8: - case FFI_TYPE_SINT16: -#ifdef X86_WIN64 - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: -#endif - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#ifndef X86_WIN64 -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif -#endif - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_UINT64: -#ifdef X86_WIN64 - case FFI_TYPE_POINTER: -#endif - cif->flags = FFI_TYPE_SINT64; - break; - - case FFI_TYPE_STRUCT: -#ifndef X86 - if (cif->rtype->size == 1) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */ - } - else if (cif->rtype->size == 2) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */ - } - else if (cif->rtype->size == 4) - { -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SMALL_STRUCT_4B; -#else - cif->flags = FFI_TYPE_INT; /* same as int type */ -#endif - } - else if (cif->rtype->size == 8) - { - cif->flags = FFI_TYPE_SINT64; /* same as int64 type */ - } - else -#endif - { -#ifdef X86_WIN32 - if (cif->abi == FFI_MS_CDECL) - cif->flags = FFI_TYPE_MS_STRUCT; - else -#endif - cif->flags = FFI_TYPE_STRUCT; - /* allocate space for return value pointer */ - cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG); - } - break; - - default: -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SINT64; - break; - case FFI_TYPE_INT: - cif->flags = FFI_TYPE_SINT32; -#else - cif->flags = FFI_TYPE_INT; -#endif - break; - } - - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) - { - if (((*ptr)->alignment - 1) & cif->bytes) - cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment); - cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG); - } - -#ifdef X86_WIN64 - /* ensure space for storing four registers */ - cif->bytes += 4 * sizeof(ffi_arg); -#endif - - cif->bytes = (cif->bytes + 15) & ~0xF; - - return FFI_OK; -} - -#ifdef X86_WIN64 -extern int -ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); -#elif defined(X86_WIN32) -extern void -ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); -#else -extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, - unsigned, unsigned, unsigned *, void (*fn)(void)); -#endif - -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - -#ifdef X86_WIN64 - if (rvalue == NULL - && cif->flags == FFI_TYPE_STRUCT - && cif->rtype->size != 1 && cif->rtype->size != 2 - && cif->rtype->size != 4 && cif->rtype->size != 8) - { - ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); - } -#else - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } -#endif - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifdef X86_WIN64 - case FFI_WIN64: - ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; -#elif defined(X86_WIN32) - case FFI_SYSV: - case FFI_STDCALL: - case FFI_MS_CDECL: - ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; - case FFI_THISCALL: - case FFI_FASTCALL: - { - unsigned int abi = cif->abi; - unsigned int i, passed_regs = 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - for (i=0; i < cif->nargs && passed_regs < 2;i++) - { - size_t sz; - - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - sz = (cif->arg_types[i]->size + 3) & ~3; - if (sz == 0 || sz > 4) - continue; - ++passed_regs; - } - if (passed_regs < 2 && abi == FFI_FASTCALL) - abi = FFI_THISCALL; - if (passed_regs < 1 && abi == FFI_THISCALL) - abi = FFI_STDCALL; - ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - } - break; -#else - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, - fn); - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - - -/** private members **/ - -/* The following __attribute__((regparm(1))) decorations will have no effect - on MSVC or SUNPRO_C -- standard conventions apply. */ -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif); -void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *) - __attribute__ ((regparm(1))); -unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *) - __attribute__ ((regparm(1))); -#ifdef X86_WIN32 -void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *) - __attribute__ ((regparm(1))); -void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *) - __attribute__ ((regparm(1))); -#endif -#ifdef X86_WIN64 -void FFI_HIDDEN ffi_closure_win64 (ffi_closure *); -#endif - -/* This function is jumped to by the trampoline */ - -#ifdef X86_WIN64 -void * FFI_HIDDEN -ffi_closure_win64_inner (ffi_closure *closure, void *args) { - ffi_cif *cif; - void **arg_area; - void *result; - void *resp = &result; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - /* The result is returned in rax. This does the right thing for - result types except for floats; we have to 'mov xmm0, rax' in the - caller to correct this. - TODO: structure sizes of 3 5 6 7 are returned by reference, too!!! - */ - return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp; -} - -#else -unsigned int FFI_HIDDEN __attribute__ ((regparm(1))) -ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args) -{ - /* our various things... */ - ffi_cif *cif; - void **arg_area; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will change RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); - - (closure->fun) (cif, *respp, arg_area, closure->user_data); - - return cif->flags; -} -#endif /* !X86_WIN64 */ - -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, - ffi_cif *cif) -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - -#ifdef X86_WIN64 - if (cif->rtype->size > sizeof(ffi_arg) - || (cif->flags == FFI_TYPE_STRUCT - && (cif->rtype->size != 1 && cif->rtype->size != 2 - && cif->rtype->size != 4 && cif->rtype->size != 8))) { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } -#else - if ( cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT ) { - *rvalue = *(void **) argp; - argp += sizeof(void *); - } -#endif - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) - { - size_t z; - - /* Align if necessary */ - if ((sizeof(void*) - 1) & (size_t) argp) { - argp = (char *) ALIGN(argp, sizeof(void*)); - } - -#ifdef X86_WIN64 - if ((*p_arg)->size > sizeof(ffi_arg) - || ((*p_arg)->type == FFI_TYPE_STRUCT - && ((*p_arg)->size != 1 && (*p_arg)->size != 2 - && (*p_arg)->size != 4 && (*p_arg)->size != 8))) - { - z = sizeof(void *); - *p_argv = *(void **)argp; - } - else -#endif - { - z = (*p_arg)->size; - - /* because we're little endian, this is what it turns into. */ - - *p_argv = (void*) argp; - } - - p_argv++; -#ifdef X86_WIN64 - argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); -#else - argp += z; -#endif - } - - return; -} - -#define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - void* __fun = (void*)(FUN); \ - void* __ctx = (void*)(CTX); \ - *(unsigned char*) &__tramp[0] = 0x41; \ - *(unsigned char*) &__tramp[1] = 0xbb; \ - *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \ - *(unsigned char*) &__tramp[6] = 0x48; \ - *(unsigned char*) &__tramp[7] = 0xb8; \ - *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \ - *(unsigned char *) &__tramp[16] = 0x49; \ - *(unsigned char *) &__tramp[17] = 0xba; \ - *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \ - *(unsigned char *) &__tramp[26] = 0x41; \ - *(unsigned char *) &__tramp[27] = 0xff; \ - *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \ - } - -/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */ - -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 10); \ - *(unsigned char*) &__tramp[0] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[5] = 0xe9; \ - *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \ - } - -#define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 49); \ - unsigned short __size = (unsigned short)(SIZE); \ - *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \ - *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \ - *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \ - *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \ - *(unsigned char*) &__tramp[13] = 0xb8; \ - *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \ - *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \ - *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \ - *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \ - *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \ - *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \ - *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \ - *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \ - *(unsigned char*) &__tramp[39] = 0xb8; \ - *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[44] = 0xe8; \ - *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \ - *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \ - *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \ - } - -#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \ -{ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned int __dis = __fun - (__ctx + 10); \ - unsigned short __size = (unsigned short)(SIZE); \ - *(unsigned char*) &__tramp[0] = 0xb8; \ - *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ - *(unsigned char *) &__tramp[5] = 0xe8; \ - *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \ - *(unsigned char *) &__tramp[10] = 0xc2; \ - *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \ - } - -/* the cif must already be prep'ed */ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ -#ifdef X86_WIN64 -#define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE) -#define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0) - if (cif->abi == FFI_WIN64) - { - int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3); - FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0], - &ffi_closure_win64, - codeloc, mask); - /* make sure we can execute here */ - } -#else - if (cif->abi == FFI_SYSV) - { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); - } -#ifdef X86_WIN32 - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], - &ffi_closure_THISCALL, - (void*)codeloc, - cif->bytes); - } - else if (cif->abi == FFI_STDCALL) - { - FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0], - &ffi_closure_STDCALL, - (void*)codeloc, cif->bytes); - } - else if (cif->abi == FFI_MS_CDECL) - { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); - } -#endif /* X86_WIN32 */ -#endif /* !X86_WIN64 */ - else - { - return FFI_BAD_ABI; - } - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -/* ------- Native raw API support -------------------------------- */ - -#if !FFI_NO_RAW_API - -ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,ffi_raw*,void*), - void *user_data, - void *codeloc) -{ - int i; - - if (cif->abi != FFI_SYSV) { -#ifdef X86_WIN32 - if (cif->abi != FFI_THISCALL) -#endif - return FFI_BAD_ABI; - } - - /* we currently don't support certain kinds of arguments for raw - closures. This should be implemented by a separate assembly - language routine, since it would require argument processing, - something we don't do now for performance. */ - - for (i = cif->nargs-1; i >= 0; i--) - { - FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT); - FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); - } - -#ifdef X86_WIN32 - if (cif->abi == FFI_SYSV) - { -#endif - FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, - codeloc); -#ifdef X86_WIN32 - } - else if (cif->abi == FFI_THISCALL) - { - FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, - codeloc, cif->bytes); - } -#endif - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - - return FFI_OK; -} - -static void -ffi_prep_args_raw(char *stack, extended_cif *ecif) -{ - memcpy (stack, ecif->avalue, ecif->cif->bytes); -} - -/* we borrow this routine from libffi (it must be changed, though, to - * actually call the function passed in the first argument. as of - * libffi-1.20, this is not the case.) - */ - -void -ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) -{ - extended_cif ecif; - void **avalue = (void **)fake_avalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#ifdef X86_WIN32 - case FFI_SYSV: - case FFI_STDCALL: - case FFI_MS_CDECL: - ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; - case FFI_THISCALL: - case FFI_FASTCALL: - { - unsigned int abi = cif->abi; - unsigned int i, passed_regs = 0; - - if (cif->flags == FFI_TYPE_STRUCT) - ++passed_regs; - - for (i=0; i < cif->nargs && passed_regs < 2;i++) - { - size_t sz; - - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - sz = (cif->arg_types[i]->size + 3) & ~3; - if (sz == 0 || sz > 4) - continue; - ++passed_regs; - } - if (passed_regs < 2 && abi == FFI_FASTCALL) - cif->abi = abi = FFI_THISCALL; - if (passed_regs < 1 && abi == FFI_THISCALL) - cif->abi = abi = FFI_STDCALL; - ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags, - ecif.rvalue, fn); - } - break; -#else - case FFI_SYSV: - ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, - ecif.rvalue, fn); - break; -#endif - default: - FFI_ASSERT(0); - break; - } -} - -#endif - -#endif /* !__x86_64__ || X86_WIN64 */ - diff --git a/gcc/ffi64.c b/gcc/ffi64.c deleted file mode 100644 index 2014af2..0000000 --- a/gcc/ffi64.c +++ /dev/null @@ -1,673 +0,0 @@ -/* ----------------------------------------------------------------------- - ffi64.c - Copyright (c) 2013 The Written Word, Inc. - Copyright (c) 2011 Anthony Green - Copyright (c) 2008, 2010 Red Hat, Inc. - Copyright (c) 2002, 2007 Bo Thorsen - - x86-64 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include - -#include -#include - -#ifdef __x86_64__ - -#define MAX_GPR_REGS 6 -#define MAX_SSE_REGS 8 - -#if defined(__INTEL_COMPILER) -#define UINT128 __m128 -#else -#if defined(__SUNPRO_C) -#include -#define UINT128 __m128i -#else -#define UINT128 __int128_t -#endif -#endif - -union big_int_union -{ - UINT32 i32; - UINT64 i64; - UINT128 i128; -}; - -struct register_args -{ - /* Registers for argument passing. */ - UINT64 gpr[MAX_GPR_REGS]; - union big_int_union sse[MAX_SSE_REGS]; -}; - -extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void), unsigned ssecount); - -/* All reference to register classes here is identical to the code in - gcc/config/i386/i386.c. Do *not* change one without the other. */ - -/* Register class used for passing given 64bit part of the argument. - These represent classes as documented by the PS ABI, with the - exception of SSESF, SSEDF classes, that are basically SSE class, - just gcc will use SF or DFmode move instead of DImode to avoid - reformatting penalties. - - Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves - whenever possible (upper half does contain padding). */ -enum x86_64_reg_class - { - X86_64_NO_CLASS, - X86_64_INTEGER_CLASS, - X86_64_INTEGERSI_CLASS, - X86_64_SSE_CLASS, - X86_64_SSESF_CLASS, - X86_64_SSEDF_CLASS, - X86_64_SSEUP_CLASS, - X86_64_X87_CLASS, - X86_64_X87UP_CLASS, - X86_64_COMPLEX_X87_CLASS, - X86_64_MEMORY_CLASS - }; - -#define MAX_CLASSES 4 - -#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) - -/* x86-64 register passing implementation. See x86-64 ABI for details. Goal - of this code is to classify each 8bytes of incoming argument by the register - class and assign registers accordingly. */ - -/* Return the union class of CLASS1 and CLASS2. - See the x86-64 PS ABI for details. */ - -static enum x86_64_reg_class -merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2) -{ - /* Rule #1: If both classes are equal, this is the resulting class. */ - if (class1 == class2) - return class1; - - /* Rule #2: If one of the classes is NO_CLASS, the resulting class is - the other class. */ - if (class1 == X86_64_NO_CLASS) - return class2; - if (class2 == X86_64_NO_CLASS) - return class1; - - /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ - if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) - return X86_64_MEMORY_CLASS; - - /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ - if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) - || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) - return X86_64_INTEGERSI_CLASS; - if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS - || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) - return X86_64_INTEGER_CLASS; - - /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, - MEMORY is used. */ - if (class1 == X86_64_X87_CLASS - || class1 == X86_64_X87UP_CLASS - || class1 == X86_64_COMPLEX_X87_CLASS - || class2 == X86_64_X87_CLASS - || class2 == X86_64_X87UP_CLASS - || class2 == X86_64_COMPLEX_X87_CLASS) - return X86_64_MEMORY_CLASS; - - /* Rule #6: Otherwise class SSE is used. */ - return X86_64_SSE_CLASS; -} - -/* Classify the argument of type TYPE and mode MODE. - CLASSES will be filled by the register class used to pass each word - of the operand. The number of words is returned. In case the parameter - should be passed in memory, 0 is returned. As a special case for zero - sized containers, classes[0] will be NO_CLASS and 1 is returned. - - See the x86-64 PS ABI for details. -*/ -static int -classify_argument (ffi_type *type, enum x86_64_reg_class classes[], - size_t byte_offset) -{ - switch (type->type) - { - case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: - case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: - case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: - case FFI_TYPE_UINT64: - case FFI_TYPE_SINT64: - case FFI_TYPE_POINTER: - { - int size = byte_offset + type->size; - - if (size <= 4) - { - classes[0] = X86_64_INTEGERSI_CLASS; - return 1; - } - else if (size <= 8) - { - classes[0] = X86_64_INTEGER_CLASS; - return 1; - } - else if (size <= 12) - { - classes[0] = X86_64_INTEGER_CLASS; - classes[1] = X86_64_INTEGERSI_CLASS; - return 2; - } - else if (size <= 16) - { - classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; - return 2; - } - else - FFI_ASSERT (0); - } - case FFI_TYPE_FLOAT: - if (!(byte_offset % 8)) - classes[0] = X86_64_SSESF_CLASS; - else - classes[0] = X86_64_SSE_CLASS; - return 1; - case FFI_TYPE_DOUBLE: - classes[0] = X86_64_SSEDF_CLASS; - return 1; - case FFI_TYPE_LONGDOUBLE: - classes[0] = X86_64_X87_CLASS; - classes[1] = X86_64_X87UP_CLASS; - return 2; - case FFI_TYPE_STRUCT: - { - const int UNITS_PER_WORD = 8; - int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; - ffi_type **ptr; - int i; - enum x86_64_reg_class subclasses[MAX_CLASSES]; - - /* If the struct is larger than 32 bytes, pass it on the stack. */ - if (type->size > 32) - return 0; - - for (i = 0; i < words; i++) - classes[i] = X86_64_NO_CLASS; - - /* Zero sized arrays or structures are NO_CLASS. We return 0 to - signalize memory class, so handle it as special case. */ - if (!words) - { - classes[0] = X86_64_NO_CLASS; - return 1; - } - - /* Merge the fields of structure. */ - for (ptr = type->elements; *ptr != NULL; ptr++) - { - int num; - - byte_offset = ALIGN (byte_offset, (*ptr)->alignment); - - num = classify_argument (*ptr, subclasses, byte_offset % 8); - if (num == 0) - return 0; - for (i = 0; i < num; i++) - { - int pos = byte_offset / 8; - classes[i + pos] = - merge_classes (subclasses[i], classes[i + pos]); - } - - byte_offset += (*ptr)->size; - } - - if (words > 2) - { - /* When size > 16 bytes, if the first one isn't - X86_64_SSE_CLASS or any other ones aren't - X86_64_SSEUP_CLASS, everything should be passed in - memory. */ - if (classes[0] != X86_64_SSE_CLASS) - return 0; - - for (i = 1; i < words; i++) - if (classes[i] != X86_64_SSEUP_CLASS) - return 0; - } - - /* Final merger cleanup. */ - for (i = 0; i < words; i++) - { - /* If one class is MEMORY, everything should be passed in - memory. */ - if (classes[i] == X86_64_MEMORY_CLASS) - return 0; - - /* The X86_64_SSEUP_CLASS should be always preceded by - X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */ - if (classes[i] == X86_64_SSEUP_CLASS - && classes[i - 1] != X86_64_SSE_CLASS - && classes[i - 1] != X86_64_SSEUP_CLASS) - { - /* The first one should never be X86_64_SSEUP_CLASS. */ - FFI_ASSERT (i != 0); - classes[i] = X86_64_SSE_CLASS; - } - - /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, - everything should be passed in memory. */ - if (classes[i] == X86_64_X87UP_CLASS - && (classes[i - 1] != X86_64_X87_CLASS)) - { - /* The first one should never be X86_64_X87UP_CLASS. */ - FFI_ASSERT (i != 0); - return 0; - } - } - return words; - } - - default: - FFI_ASSERT(0); - } - return 0; /* Never reached. */ -} - -/* Examine the argument and return set number of register required in each - class. Return zero iff parameter should be passed in memory, otherwise - the number of registers. */ - -static int -examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], - _Bool in_return, int *pngpr, int *pnsse) -{ - int i, n, ngpr, nsse; - - n = classify_argument (type, classes, 0); - if (n == 0) - return 0; - - ngpr = nsse = 0; - for (i = 0; i < n; ++i) - switch (classes[i]) - { - case X86_64_INTEGER_CLASS: - case X86_64_INTEGERSI_CLASS: - ngpr++; - break; - case X86_64_SSE_CLASS: - case X86_64_SSESF_CLASS: - case X86_64_SSEDF_CLASS: - nsse++; - break; - case X86_64_NO_CLASS: - case X86_64_SSEUP_CLASS: - break; - case X86_64_X87_CLASS: - case X86_64_X87UP_CLASS: - case X86_64_COMPLEX_X87_CLASS: - return in_return != 0; - default: - abort (); - } - - *pngpr = ngpr; - *pnsse = nsse; - - return n; -} - -/* Perform machine dependent cif processing. */ - -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) -{ - int gprcount, ssecount, i, avn, n, ngpr, nsse, flags; - enum x86_64_reg_class classes[MAX_CLASSES]; - size_t bytes; - - gprcount = ssecount = 0; - - flags = cif->rtype->type; - if (flags != FFI_TYPE_VOID) - { - n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); - if (n == 0) - { - /* The return value is passed in memory. A pointer to that - memory is the first argument. Allocate a register for it. */ - gprcount++; - /* We don't have to do anything in asm for the return. */ - flags = FFI_TYPE_VOID; - } - else if (flags == FFI_TYPE_STRUCT) - { - /* Mark which registers the result appears in. */ - _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]); - if (sse0 && !sse1) - flags |= 1 << 8; - else if (!sse0 && sse1) - flags |= 1 << 9; - else if (sse0 && sse1) - flags |= 1 << 10; - /* Mark the true size of the structure. */ - flags |= cif->rtype->size << 12; - } - } - - /* Go over all arguments and determine the way they should be passed. - If it's in a register and there is space for it, let that be so. If - not, add it's size to the stack byte count. */ - for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) - { - if (examine_argument (cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = cif->arg_types[i]->alignment; - - if (align < 8) - align = 8; - - bytes = ALIGN (bytes, align); - bytes += cif->arg_types[i]->size; - } - else - { - gprcount += ngpr; - ssecount += nsse; - } - } - if (ssecount) - flags |= 1 << 11; - cif->flags = flags; - cif->bytes = ALIGN (bytes, 8); - - return FFI_OK; -} - -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - enum x86_64_reg_class classes[MAX_CLASSES]; - char *stack, *argp; - ffi_type **arg_types; - int gprcount, ssecount, ngpr, nsse, i, avn; - _Bool ret_in_memory; - struct register_args *reg_args; - - /* Can't call 32-bit mode from 64-bit mode. */ - FFI_ASSERT (cif->abi == FFI_UNIX64); - - /* If the return value is a struct and we don't have a return value - address then we need to make one. Note the setting of flags to - VOID above in ffi_prep_cif_machdep. */ - ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT - && (cif->flags & 0xff) == FFI_TYPE_VOID); - if (rvalue == NULL && ret_in_memory) - rvalue = alloca (cif->rtype->size); - - /* Allocate the space for the arguments, plus 4 words of temp space. */ - stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8); - reg_args = (struct register_args *) stack; - argp = stack + sizeof (struct register_args); - - gprcount = ssecount = 0; - - /* If the return value is passed in memory, add the pointer as the - first integer argument. */ - if (ret_in_memory) - reg_args->gpr[gprcount++] = (unsigned long) rvalue; - - avn = cif->nargs; - arg_types = cif->arg_types; - - for (i = 0; i < avn; ++i) - { - size_t size = arg_types[i]->size; - int n; - - n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); - if (n == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = arg_types[i]->alignment; - - /* Stack arguments are *always* at least 8 byte aligned. */ - if (align < 8) - align = 8; - - /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); - memcpy (argp, avalue[i], size); - argp += size; - } - else - { - /* The argument is passed entirely in registers. */ - char *a = (char *) avalue[i]; - int j; - - for (j = 0; j < n; j++, a += 8, size -= 8) - { - switch (classes[j]) - { - case X86_64_INTEGER_CLASS: - case X86_64_INTEGERSI_CLASS: - /* Sign-extend integer arguments passed in general - purpose registers, to cope with the fact that - LLVM incorrectly assumes that this will be done - (the x86-64 PS ABI does not specify this). */ - switch (arg_types[i]->type) - { - case FFI_TYPE_SINT8: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a); - break; - case FFI_TYPE_SINT16: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a); - break; - case FFI_TYPE_SINT32: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a); - break; - default: - reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); - } - gprcount++; - break; - case X86_64_SSE_CLASS: - case X86_64_SSEDF_CLASS: - reg_args->sse[ssecount++].i64 = *(UINT64 *) a; - break; - case X86_64_SSESF_CLASS: - reg_args->sse[ssecount++].i32 = *(UINT32 *) a; - break; - default: - abort(); - } - } - } - } - - ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args), - cif->flags, rvalue, fn, ssecount); -} - - -extern void ffi_closure_unix64(void); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*, void*, void**, void*), - void *user_data, - void *codeloc) -{ - volatile unsigned short *tramp; - - /* Sanity check on the cif ABI. */ - { - int abi = cif->abi; - if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))) - return FFI_BAD_ABI; - } - - tramp = (volatile unsigned short *) &closure->tramp[0]; - - tramp[0] = 0xbb49; /* mov , %r11 */ - *((unsigned long long * volatile) &tramp[1]) - = (unsigned long) ffi_closure_unix64; - tramp[5] = 0xba49; /* mov , %r10 */ - *((unsigned long long * volatile) &tramp[6]) - = (unsigned long) codeloc; - - /* Set the carry bit iff the function uses any sse registers. - This is clc or stc, together with the first byte of the jmp. */ - tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; - - tramp[11] = 0xe3ff; /* jmp *%r11 */ - - closure->cif = cif; - closure->fun = fun; - closure->user_data = user_data; - - return FFI_OK; -} - -int -ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, - struct register_args *reg_args, char *argp) -{ - ffi_cif *cif; - void **avalue; - ffi_type **arg_types; - long i, avn; - int gprcount, ssecount, ngpr, nsse; - int ret; - - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); - gprcount = ssecount = 0; - - ret = cif->rtype->type; - if (ret != FFI_TYPE_VOID) - { - enum x86_64_reg_class classes[MAX_CLASSES]; - int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); - if (n == 0) - { - /* The return value goes in memory. Arrange for the closure - return value to go directly back to the original caller. */ - rvalue = (void *) (unsigned long) reg_args->gpr[gprcount++]; - /* We don't have to do anything in asm for the return. */ - ret = FFI_TYPE_VOID; - } - else if (ret == FFI_TYPE_STRUCT && n == 2) - { - /* Mark which register the second word of the structure goes in. */ - _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = SSE_CLASS_P (classes[1]); - if (!sse0 && sse1) - ret |= 1 << 8; - else if (sse0 && !sse1) - ret |= 1 << 9; - } - } - - avn = cif->nargs; - arg_types = cif->arg_types; - - for (i = 0; i < avn; ++i) - { - enum x86_64_reg_class classes[MAX_CLASSES]; - int n; - - n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); - if (n == 0 - || gprcount + ngpr > MAX_GPR_REGS - || ssecount + nsse > MAX_SSE_REGS) - { - long align = arg_types[i]->alignment; - - /* Stack arguments are *always* at least 8 byte aligned. */ - if (align < 8) - align = 8; - - /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); - avalue[i] = argp; - argp += arg_types[i]->size; - } - /* If the argument is in a single register, or two consecutive - integer registers, then we can use that address directly. */ - else if (n == 1 - || (n == 2 && !(SSE_CLASS_P (classes[0]) - || SSE_CLASS_P (classes[1])))) - { - /* The argument is in a single register. */ - if (SSE_CLASS_P (classes[0])) - { - avalue[i] = ®_args->sse[ssecount]; - ssecount += n; - } - else - { - avalue[i] = ®_args->gpr[gprcount]; - gprcount += n; - } - } - /* Otherwise, allocate space to make them consecutive. */ - else - { - char *a = alloca (16); - int j; - - avalue[i] = a; - for (j = 0; j < n; j++, a += 8) - { - if (SSE_CLASS_P (classes[j])) - memcpy (a, ®_args->sse[ssecount++], 8); - else - memcpy (a, ®_args->gpr[gprcount++], 8); - } - } - } - - /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); - - /* Tell assembly how to perform return type promotions. */ - return ret; -} - -#endif /* __x86_64__ */ diff --git a/gcc/prep_cif.c b/gcc/prep_cif.c deleted file mode 100644 index e8ec5cf..0000000 --- a/gcc/prep_cif.c +++ /dev/null @@ -1,237 +0,0 @@ -/* ----------------------------------------------------------------------- - prep_cif.c - Copyright (c) 2011, 2012 Anthony Green - Copyright (c) 1996, 1998, 2007 Red Hat, Inc. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#include -#include -#include - -/* 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(ffi_type *arg) -{ - ffi_type **ptr; - - if (UNLIKELY(arg == NULL || arg->elements == NULL)) - return FFI_BAD_TYPEDEF; - - arg->size = 0; - arg->alignment = 0; - - ptr = &(arg->elements[0]); - - if (UNLIKELY(ptr == 0)) - return FFI_BAD_TYPEDEF; - - while ((*ptr) != NULL) - { - if (UNLIKELY(((*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; -} - -#ifndef __CRIS__ -/* The CRIS ABI specifies structure elements to have byte - alignment only, so it completely overrides this functions, - which assumes "natural" alignment and padding. */ - -/* Perform machine independent ffi_cif preparation, then call - machine dependent routine. */ - -/* For non variadic functions isvariadic should be 0 and - nfixedargs==ntotalargs. - - For variadic calls, isvariadic should be 1 and nfixedargs - and ntotalargs set as appropriate. nfixedargs must always be >=1 */ - - -ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, - unsigned int isvariadic, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, ffi_type **atypes) -{ - unsigned bytes = 0; - unsigned int i; - ffi_type **ptr; - - FFI_ASSERT(cif != NULL); - FFI_ASSERT((!isvariadic) || (nfixedargs >= 1)); - FFI_ASSERT(nfixedargs <= ntotalargs); - -#ifndef X86_WIN32 - if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)) - return FFI_BAD_ABI; -#else - if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI || abi == FFI_THISCALL)) - return FFI_BAD_ABI; -#endif - - cif->abi = abi; - cif->arg_types = atypes; - cif->nargs = ntotalargs; - cif->rtype = rtype; - - cif->flags = 0; - - /* Initialize the return type if necessary */ - if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) - return FFI_BAD_TYPEDEF; - - /* Perform a sanity check on the return type */ - FFI_ASSERT_VALID_TYPE(cif->rtype); - - /* x86, x86-64 and s390 stack space allocation is handled in prep_machdep. */ -#if !defined M68K && !defined X86_ANY && !defined S390 && !defined PA - /* Make space for the return structure pointer */ - if (cif->rtype->type == FFI_TYPE_STRUCT -#ifdef SPARC - && (cif->abi != FFI_V9 || cif->rtype->size > 32) -#endif -#ifdef TILE - && (cif->rtype->size > 10 * FFI_SIZEOF_ARG) -#endif -#ifdef XTENSA - && (cif->rtype->size > 16) -#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_ANY && !defined S390 && !defined PA -#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 - { - /* Add any padding if necessary */ - if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN(bytes, (*ptr)->alignment); - -#ifdef TILE - if (bytes < 10 * FFI_SIZEOF_ARG && - bytes + STACK_ARG_SIZE((*ptr)->size) > 10 * FFI_SIZEOF_ARG) - { - /* An argument is never split between the 10 parameter - registers and the stack. */ - bytes = 10 * FFI_SIZEOF_ARG; - } -#endif -#ifdef XTENSA - if (bytes <= 6*4 && bytes + STACK_ARG_SIZE((*ptr)->size) > 6*4) - bytes = 6*4; -#endif - - bytes += STACK_ARG_SIZE((*ptr)->size); - } -#endif - } - - cif->bytes = bytes; - - /* Perform machine dependent cif processing */ -#ifdef FFI_TARGET_SPECIFIC_VARIADIC - if (isvariadic) - return ffi_prep_cif_machdep_var(cif, nfixedargs, ntotalargs); -#endif - - return ffi_prep_cif_machdep(cif); -} -#endif /* not __CRIS__ */ - -ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, - ffi_type *rtype, ffi_type **atypes) -{ - return ffi_prep_cif_core(cif, abi, 0, nargs, nargs, rtype, atypes); -} - -ffi_status ffi_prep_cif_var(ffi_cif *cif, - ffi_abi abi, - unsigned int nfixedargs, - unsigned int ntotalargs, - ffi_type *rtype, - ffi_type **atypes) -{ - return ffi_prep_cif_core(cif, abi, 1, nfixedargs, ntotalargs, rtype, atypes); -} - -#if FFI_CLOSURES - -ffi_status -ffi_prep_closure (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data) -{ - return ffi_prep_closure_loc (closure, cif, fun, user_data, closure); -} - -#endif diff --git a/gcc/types.c b/gcc/types.c deleted file mode 100644 index 0a11eb0..0000000 --- a/gcc/types.c +++ /dev/null @@ -1,77 +0,0 @@ -/* ----------------------------------------------------------------------- - 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 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. - ----------------------------------------------------------------------- */ - -/* Hide the basic type definitions from the header file, so that we - can redefine them here as "const". */ -#define LIBFFI_HIDE_BASIC_TYPES - -#include -#include - -/* Type definitions */ - -#define FFI_TYPEDEF(name, type, id) \ -struct struct_align_##name { \ - char c; \ - type x; \ -}; \ -const ffi_type ffi_type_##name = { \ - sizeof(type), \ - offsetof(struct struct_align_##name, x), \ - id, NULL \ -} - -/* Size and alignment are fake here. They must not be 0. */ -const ffi_type ffi_type_void = { - 1, 1, FFI_TYPE_VOID, NULL -}; - -FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8); -FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8); -FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16); -FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16); -FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32); -FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32); -FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64); -FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64); - -FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER); - -FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT); -FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE); - -#ifdef __alpha__ -/* Even if we're not configured to default to 128-bit long double, - maintain binary compatibility, as -mlong-double-128 can be used - at any time. */ -/* Validate the hard-coded number below. */ -# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4 -# error FFI_TYPE_LONGDOUBLE out of date -# endif -const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL }; -#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE); -#endif diff --git a/gcc/win32_asm.asm b/gcc/win32_asm.asm deleted file mode 100644 index ce3c4f3..0000000 --- a/gcc/win32_asm.asm +++ /dev/null @@ -1,759 +0,0 @@ -/* ----------------------------------------------------------------------- - win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc. - Copyright (c) 2001 John Beniton - Copyright (c) 2002 Ranjit Mathew - Copyright (c) 2009 Daniel Witte - - - X86 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- - */ - -#define LIBFFI_ASM -#include -#include -#include - - .text - - // This assumes we are using gas. - .balign 16 - .globl _ffi_call_win32 -#ifndef __OS2__ - .def _ffi_call_win32; .scl 2; .type 32; .endef -#endif -_ffi_call_win32: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - // Make room for all of the new args. - movl 20(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - // Place all of the ffi_prep_args in position - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - // Return stack to previous state and call the function - addl $8,%esp - - // Handle fastcall and thiscall - cmpl $3, 16(%ebp) // FFI_THISCALL - jz .do_thiscall - cmpl $4, 16(%ebp) // FFI_FASTCALL - jnz .do_fncall - movl (%esp), %ecx - movl 4(%esp), %edx - addl $8, %esp - jmp .do_fncall -.do_thiscall: - movl (%esp), %ecx - addl $4, %esp - -.do_fncall: - - // FIXME: Align the stack to a 128-bit boundary to avoid - // potential performance hits. - - call *32(%ebp) - - // stdcall functions pop arguments off the stack themselves - - // Load %ecx with the return type code - movl 24(%ebp),%ecx - - // If the return value pointer is NULL, assume no return value. - cmpl $0,28(%ebp) - jne 0f - - // Even if there is no space for the return value, we are - // obliged to handle floating-point values. - cmpl $FFI_TYPE_FLOAT,%ecx - jne .Lnoretval - fstp %st(0) - - jmp .Lepilogue - -0: - call 1f - // Do not insert anything here between the call and the jump table. -.Lstore_table: - .long .Lnoretval /* FFI_TYPE_VOID */ - .long .Lretint /* FFI_TYPE_INT */ - .long .Lretfloat /* FFI_TYPE_FLOAT */ - .long .Lretdouble /* FFI_TYPE_DOUBLE */ - .long .Lretlongdouble /* FFI_TYPE_LONGDOUBLE */ - .long .Lretuint8 /* FFI_TYPE_UINT8 */ - .long .Lretsint8 /* FFI_TYPE_SINT8 */ - .long .Lretuint16 /* FFI_TYPE_UINT16 */ - .long .Lretsint16 /* FFI_TYPE_SINT16 */ - .long .Lretint /* FFI_TYPE_UINT32 */ - .long .Lretint /* FFI_TYPE_SINT32 */ - .long .Lretint64 /* FFI_TYPE_UINT64 */ - .long .Lretint64 /* FFI_TYPE_SINT64 */ - .long .Lretstruct /* FFI_TYPE_STRUCT */ - .long .Lretint /* FFI_TYPE_POINTER */ - .long .Lretstruct1b /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lretstruct2b /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lretstruct4b /* FFI_TYPE_SMALL_STRUCT_4B */ - .long .Lretstruct /* FFI_TYPE_MS_STRUCT */ -1: - add %ecx, %ecx - add %ecx, %ecx - add (%esp),%ecx - add $4, %esp - jmp *(%ecx) - - /* Sign/zero extend as appropriate. */ -.Lretsint8: - movsbl %al, %eax - jmp .Lretint - -.Lretsint16: - movswl %ax, %eax - jmp .Lretint - -.Lretuint8: - movzbl %al, %eax - jmp .Lretint - -.Lretuint16: - movzwl %ax, %eax - jmp .Lretint - -.Lretint: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lepilogue - -.Lretfloat: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - fstps (%ecx) - jmp .Lepilogue - -.Lretdouble: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - fstpl (%ecx) - jmp .Lepilogue - -.Lretlongdouble: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - fstpt (%ecx) - jmp .Lepilogue - -.Lretint64: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp .Lepilogue - -.Lretstruct1b: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movb %al,0(%ecx) - jmp .Lepilogue - -.Lretstruct2b: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movw %ax,0(%ecx) - jmp .Lepilogue - -.Lretstruct4b: - // Load %ecx with the pointer to storage for the return value - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lepilogue - -.Lretstruct: - // Nothing to do! - -.Lnoretval: -.Lepilogue: - movl %ebp,%esp - popl %ebp - ret -.ffi_call_win32_end: - .balign 16 - .globl _ffi_closure_THISCALL -#ifndef __OS2__ - .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef -#endif -_ffi_closure_THISCALL: - pushl %ebp - movl %esp, %ebp - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 12(%ebp), %edx /* account for stub return address on stack */ - jmp .stub -.LFE1: - - // This assumes we are using gas. - .balign 16 - .globl _ffi_closure_SYSV -#ifndef __OS2__ - .def _ffi_closure_SYSV; .scl 2; .type 32; .endef -#endif -_ffi_closure_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx -.stub: - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ - call _ffi_closure_SYSV_inner - movl -12(%ebp), %ecx - -0: - call 1f - // Do not insert anything here between the call and the jump table. -.Lcls_store_table: - .long .Lcls_noretval /* FFI_TYPE_VOID */ - .long .Lcls_retint /* FFI_TYPE_INT */ - .long .Lcls_retfloat /* FFI_TYPE_FLOAT */ - .long .Lcls_retdouble /* FFI_TYPE_DOUBLE */ - .long .Lcls_retldouble /* FFI_TYPE_LONGDOUBLE */ - .long .Lcls_retuint8 /* FFI_TYPE_UINT8 */ - .long .Lcls_retsint8 /* FFI_TYPE_SINT8 */ - .long .Lcls_retuint16 /* FFI_TYPE_UINT16 */ - .long .Lcls_retsint16 /* FFI_TYPE_SINT16 */ - .long .Lcls_retint /* FFI_TYPE_UINT32 */ - .long .Lcls_retint /* FFI_TYPE_SINT32 */ - .long .Lcls_retllong /* FFI_TYPE_UINT64 */ - .long .Lcls_retllong /* FFI_TYPE_SINT64 */ - .long .Lcls_retstruct /* FFI_TYPE_STRUCT */ - .long .Lcls_retint /* FFI_TYPE_POINTER */ - .long .Lcls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lcls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lcls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */ - .long .Lcls_retmsstruct /* FFI_TYPE_MS_STRUCT */ - -1: - add %eax, %eax - add %eax, %eax - add (%esp),%eax - add $4, %esp - jmp *(%eax) - - /* Sign/zero extend as appropriate. */ -.Lcls_retsint8: - movsbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retsint16: - movswl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retuint8: - movzbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retuint16: - movzwl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue - -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue - -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue - -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue - -.Lcls_retstruct1: - movsbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct2: - movswl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct4: - movl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct: - // Caller expects us to pop struct return value pointer hidden arg. - movl %ebp, %esp - popl %ebp - ret $0x4 - -.Lcls_retmsstruct: - // Caller expects us to return a pointer to the real return value. - mov %ecx, %eax - // Caller doesn't expects us to pop struct return value pointer hidden arg. - jmp .Lcls_epilogue - -.Lcls_noretval: -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.ffi_closure_SYSV_end: -.LFE3: - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#define CIF_FLAGS_OFFSET 20 - .balign 16 - .globl _ffi_closure_raw_THISCALL -#ifndef __OS2__ - .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef -#endif -_ffi_closure_raw_THISCALL: - pushl %ebp - movl %esp, %ebp - pushl %esi - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 12(%ebp), %edx /* __builtin_dwarf_cfa () */ - jmp .stubraw - // This assumes we are using gas. - .balign 16 - .globl _ffi_closure_raw_SYSV -#ifndef __OS2__ - .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef -#endif -_ffi_closure_raw_SYSV: -.LFB4: - pushl %ebp -.LCFI6: - movl %esp, %ebp -.LCFI7: - pushl %esi -.LCFI8: - 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 8(%ebp), %edx /* __builtin_dwarf_cfa () */ -.stubraw: - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ -0: - call 1f - // Do not insert anything here between the call and the jump table. -.Lrcls_store_table: - .long .Lrcls_noretval /* FFI_TYPE_VOID */ - .long .Lrcls_retint /* FFI_TYPE_INT */ - .long .Lrcls_retfloat /* FFI_TYPE_FLOAT */ - .long .Lrcls_retdouble /* FFI_TYPE_DOUBLE */ - .long .Lrcls_retldouble /* FFI_TYPE_LONGDOUBLE */ - .long .Lrcls_retuint8 /* FFI_TYPE_UINT8 */ - .long .Lrcls_retsint8 /* FFI_TYPE_SINT8 */ - .long .Lrcls_retuint16 /* FFI_TYPE_UINT16 */ - .long .Lrcls_retsint16 /* FFI_TYPE_SINT16 */ - .long .Lrcls_retint /* FFI_TYPE_UINT32 */ - .long .Lrcls_retint /* FFI_TYPE_SINT32 */ - .long .Lrcls_retllong /* FFI_TYPE_UINT64 */ - .long .Lrcls_retllong /* FFI_TYPE_SINT64 */ - .long .Lrcls_retstruct /* FFI_TYPE_STRUCT */ - .long .Lrcls_retint /* FFI_TYPE_POINTER */ - .long .Lrcls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lrcls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lrcls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */ - .long .Lrcls_retstruct /* FFI_TYPE_MS_STRUCT */ -1: - add %eax, %eax - add %eax, %eax - add (%esp),%eax - add $4, %esp - jmp *(%eax) - - /* Sign/zero extend as appropriate. */ -.Lrcls_retsint8: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retsint16: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retuint8: - movzbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retuint16: - movzwl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue - -.Lrcls_retstruct1: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct2: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct4: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct: - // Nothing to do! - -.Lrcls_noretval: -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.ffi_closure_raw_SYSV_end: -.LFE4: - -#endif /* !FFI_NO_RAW_API */ - - // This assumes we are using gas. - .balign 16 - .globl _ffi_closure_STDCALL -#ifndef __OS2__ - .def _ffi_closure_STDCALL; .scl 2; .type 32; .endef -#endif -_ffi_closure_STDCALL: -.LFB5: - pushl %ebp -.LCFI9: - movl %esp, %ebp -.LCFI10: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 12(%ebp), %edx /* account for stub return address on stack */ - movl %edx, 4(%esp) /* args */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ - call _ffi_closure_SYSV_inner - movl -12(%ebp), %ecx -0: - call 1f - // Do not insert anything here between the call and the jump table. -.Lscls_store_table: - .long .Lscls_noretval /* FFI_TYPE_VOID */ - .long .Lscls_retint /* FFI_TYPE_INT */ - .long .Lscls_retfloat /* FFI_TYPE_FLOAT */ - .long .Lscls_retdouble /* FFI_TYPE_DOUBLE */ - .long .Lscls_retldouble /* FFI_TYPE_LONGDOUBLE */ - .long .Lscls_retuint8 /* FFI_TYPE_UINT8 */ - .long .Lscls_retsint8 /* FFI_TYPE_SINT8 */ - .long .Lscls_retuint16 /* FFI_TYPE_UINT16 */ - .long .Lscls_retsint16 /* FFI_TYPE_SINT16 */ - .long .Lscls_retint /* FFI_TYPE_UINT32 */ - .long .Lscls_retint /* FFI_TYPE_SINT32 */ - .long .Lscls_retllong /* FFI_TYPE_UINT64 */ - .long .Lscls_retllong /* FFI_TYPE_SINT64 */ - .long .Lscls_retstruct /* FFI_TYPE_STRUCT */ - .long .Lscls_retint /* FFI_TYPE_POINTER */ - .long .Lscls_retstruct1 /* FFI_TYPE_SMALL_STRUCT_1B */ - .long .Lscls_retstruct2 /* FFI_TYPE_SMALL_STRUCT_2B */ - .long .Lscls_retstruct4 /* FFI_TYPE_SMALL_STRUCT_4B */ -1: - add %eax, %eax - add %eax, %eax - add (%esp),%eax - add $4, %esp - jmp *(%eax) - - /* Sign/zero extend as appropriate. */ -.Lscls_retsint8: - movsbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retsint16: - movswl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retuint8: - movzbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retuint16: - movzwl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retint: - movl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retfloat: - flds (%ecx) - jmp .Lscls_epilogue - -.Lscls_retdouble: - fldl (%ecx) - jmp .Lscls_epilogue - -.Lscls_retldouble: - fldt (%ecx) - jmp .Lscls_epilogue - -.Lscls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lscls_epilogue - -.Lscls_retstruct1: - movsbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct2: - movswl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct4: - movl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct: - // Nothing to do! - -.Lscls_noretval: -.Lscls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.ffi_closure_STDCALL_end: -.LFE5: - -#ifndef __OS2__ - .section .eh_frame,"w" -#endif -.Lframe1: -.LSCIE1: - .long .LECIE1-.LASCIE1 /* Length of Common Information Entry */ -.LASCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef __PIC__ - .ascii "zR\0" /* CIE Augmentation */ -#else - .ascii "\0" /* CIE Augmentation */ -#endif - .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ - .byte 0x8 /* CIE RA Column */ -#ifdef __PIC__ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ -#endif - .byte 0xc /* DW_CFA_def_cfa CFA = r4 + 4 = 4(%esp) */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 %eip at CFA + 1 * -4 */ - .byte 0x1 /* .uleb128 0x1 */ - .align 4 -.LECIE1: - -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB1-. /* FDE initial location */ -#else - .long .LFB1 -#endif - .long .LFE1-.LFB1 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE1: - - -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB3-. /* FDE initial location */ -#else - .long .LFB3 -#endif - .long .LFE3-.LFB3 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI4-.LFB3 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI5-.LCFI4 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE3: - -#if !FFI_NO_RAW_API - -.LSFDE4: - .long .LEFDE4-.LASFDE4 /* FDE Length */ -.LASFDE4: - .long .LASFDE4-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB4-. /* FDE initial location */ -#else - .long .LFB4 -#endif - .long .LFE4-.LFB4 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI6-.LFB4 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI7-.LCFI6 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI8-.LCFI7 - .byte 0x86 /* DW_CFA_offset, column 0x6 %esi at CFA + 3 * -4 */ - .byte 0x3 /* .uleb128 0x3 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE4: - -#endif /* !FFI_NO_RAW_API */ - -.LSFDE5: - .long .LEFDE5-.LASFDE5 /* FDE Length */ -.LASFDE5: - .long .LASFDE5-.Lframe1 /* FDE CIE offset */ -#if defined __PIC__ && defined HAVE_AS_X86_PCREL - .long .LFB5-. /* FDE initial location */ -#else - .long .LFB5 -#endif - .long .LFE5-.LFB5 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - /* DW_CFA_xxx CFI instructions go here. */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI9-.LFB5 - .byte 0xe /* DW_CFA_def_cfa_offset CFA = r4 + 8 = 8(%esp) */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 %ebp at CFA + 2 * -4 */ - .byte 0x2 /* .uleb128 0x2 */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI10-.LCFI9 - .byte 0xd /* DW_CFA_def_cfa_register CFA = r5 = %ebp */ - .byte 0x5 /* .uleb128 0x5 */ - - /* End of DW_CFA_xxx CFI instructions. */ - .align 4 -.LEFDE5: diff --git a/gcc/win32_asm.s b/gcc/win32_asm.s deleted file mode 100644 index 7a3e7f1..0000000 --- a/gcc/win32_asm.s +++ /dev/null @@ -1,736 +0,0 @@ -# 1 "gcc\\win32_asm.asm" -# 1 "" -# 1 "gcc\\win32_asm.asm" -# 33 "gcc\\win32_asm.asm" -# 1 "common/fficonfig.h" 1 -# 34 "gcc\\win32_asm.asm" 2 -# 1 "common/ffi.h" 1 -# 63 "common/ffi.h" -# 1 "common/ffitarget.h" 1 -# 64 "common/ffi.h" 2 -# 35 "gcc\\win32_asm.asm" 2 - - - .text - - - .balign 16 - .globl _ffi_call_win32 - - .def _ffi_call_win32; .scl 2; .type 32; .endef - -_ffi_call_win32: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - - movl 20(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - - addl $8,%esp - - - cmpl $3, 16(%ebp) - jz .do_thiscall - cmpl $4, 16(%ebp) - jnz .do_fncall - movl (%esp), %ecx - movl 4(%esp), %edx - addl $8, %esp - jmp .do_fncall -.do_thiscall: - movl (%esp), %ecx - addl $4, %esp - -.do_fncall: - - - - - call *32(%ebp) - - - - - movl 24(%ebp),%ecx - - - cmpl $0,28(%ebp) - jne 0f - - - - cmpl $2,%ecx - jne .Lnoretval - fstp %st(0) - - jmp .Lepilogue - -0: - call 1f - -.Lstore_table: - .long .Lnoretval - .long .Lretint - .long .Lretfloat - .long .Lretdouble - .long .Lretlongdouble - .long .Lretuint8 - .long .Lretsint8 - .long .Lretuint16 - .long .Lretsint16 - .long .Lretint - .long .Lretint - .long .Lretint64 - .long .Lretint64 - .long .Lretstruct - .long .Lretint - .long .Lretstruct1b - .long .Lretstruct2b - .long .Lretstruct4b - .long .Lretstruct -1: - add %ecx, %ecx - add %ecx, %ecx - add (%esp),%ecx - add $4, %esp - jmp *(%ecx) - - -.Lretsint8: - movsbl %al, %eax - jmp .Lretint - -.Lretsint16: - movswl %ax, %eax - jmp .Lretint - -.Lretuint8: - movzbl %al, %eax - jmp .Lretint - -.Lretuint16: - movzwl %ax, %eax - jmp .Lretint - -.Lretint: - - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lepilogue - -.Lretfloat: - - movl 28(%ebp),%ecx - fstps (%ecx) - jmp .Lepilogue - -.Lretdouble: - - movl 28(%ebp),%ecx - fstpl (%ecx) - jmp .Lepilogue - -.Lretlongdouble: - - movl 28(%ebp),%ecx - fstpt (%ecx) - jmp .Lepilogue - -.Lretint64: - - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp .Lepilogue - -.Lretstruct1b: - - movl 28(%ebp),%ecx - movb %al,0(%ecx) - jmp .Lepilogue - -.Lretstruct2b: - - movl 28(%ebp),%ecx - movw %ax,0(%ecx) - jmp .Lepilogue - -.Lretstruct4b: - - movl 28(%ebp),%ecx - movl %eax,0(%ecx) - jmp .Lepilogue - -.Lretstruct: - - -.Lnoretval: -.Lepilogue: - movl %ebp,%esp - popl %ebp - ret -.ffi_call_win32_end: - .balign 16 - .globl _ffi_closure_THISCALL - - .def _ffi_closure_THISCALL; .scl 2; .type 32; .endef - -_ffi_closure_THISCALL: - pushl %ebp - movl %esp, %ebp - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) - leal 12(%ebp), %edx - jmp .stub -.LFE1: - - - .balign 16 - .globl _ffi_closure_SYSV - - .def _ffi_closure_SYSV; .scl 2; .type 32; .endef - -_ffi_closure_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) - leal 8(%ebp), %edx -.stub: - movl %edx, 4(%esp) - leal -12(%ebp), %edx - movl %edx, (%esp) - call _ffi_closure_SYSV_inner - movl -12(%ebp), %ecx - -0: - call 1f - -.Lcls_store_table: - .long .Lcls_noretval - .long .Lcls_retint - .long .Lcls_retfloat - .long .Lcls_retdouble - .long .Lcls_retldouble - .long .Lcls_retuint8 - .long .Lcls_retsint8 - .long .Lcls_retuint16 - .long .Lcls_retsint16 - .long .Lcls_retint - .long .Lcls_retint - .long .Lcls_retllong - .long .Lcls_retllong - .long .Lcls_retstruct - .long .Lcls_retint - .long .Lcls_retstruct1 - .long .Lcls_retstruct2 - .long .Lcls_retstruct4 - .long .Lcls_retmsstruct - -1: - add %eax, %eax - add %eax, %eax - add (%esp),%eax - add $4, %esp - jmp *(%eax) - - -.Lcls_retsint8: - movsbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retsint16: - movswl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retuint8: - movzbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retuint16: - movzwl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue - -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue - -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue - -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue - -.Lcls_retstruct1: - movsbl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct2: - movswl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct4: - movl (%ecx), %eax - jmp .Lcls_epilogue - -.Lcls_retstruct: - - movl %ebp, %esp - popl %ebp - ret $0x4 - -.Lcls_retmsstruct: - - mov %ecx, %eax - - jmp .Lcls_epilogue - -.Lcls_noretval: -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.ffi_closure_SYSV_end: -.LFE3: - - - - - - - - .balign 16 - .globl _ffi_closure_raw_THISCALL - - .def _ffi_closure_raw_THISCALL; .scl 2; .type 32; .endef - -_ffi_closure_raw_THISCALL: - pushl %ebp - movl %esp, %ebp - pushl %esi - subl $36, %esp - movl ((52 + 3) & ~3)(%eax), %esi - movl ((((52 + 3) & ~3) + 4) + 4)(%eax), %edx - movl %edx, 12(%esp) - leal 12(%ebp), %edx - jmp .stubraw - - .balign 16 - .globl _ffi_closure_raw_SYSV - - .def _ffi_closure_raw_SYSV; .scl 2; .type 32; .endef - -_ffi_closure_raw_SYSV: -.LFB4: - pushl %ebp -.LCFI6: - movl %esp, %ebp -.LCFI7: - pushl %esi -.LCFI8: - subl $36, %esp - movl ((52 + 3) & ~3)(%eax), %esi - movl ((((52 + 3) & ~3) + 4) + 4)(%eax), %edx - movl %edx, 12(%esp) - leal 8(%ebp), %edx -.stubraw: - movl %edx, 8(%esp) - leal -24(%ebp), %edx - movl %edx, 4(%esp) - movl %esi, (%esp) - call *(((52 + 3) & ~3) + 4)(%eax) - movl 20(%esi), %eax -0: - call 1f - -.Lrcls_store_table: - .long .Lrcls_noretval - .long .Lrcls_retint - .long .Lrcls_retfloat - .long .Lrcls_retdouble - .long .Lrcls_retldouble - .long .Lrcls_retuint8 - .long .Lrcls_retsint8 - .long .Lrcls_retuint16 - .long .Lrcls_retsint16 - .long .Lrcls_retint - .long .Lrcls_retint - .long .Lrcls_retllong - .long .Lrcls_retllong - .long .Lrcls_retstruct - .long .Lrcls_retint - .long .Lrcls_retstruct1 - .long .Lrcls_retstruct2 - .long .Lrcls_retstruct4 - .long .Lrcls_retstruct -1: - add %eax, %eax - add %eax, %eax - add (%esp),%eax - add $4, %esp - jmp *(%eax) - - -.Lrcls_retsint8: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retsint16: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retuint8: - movzbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retuint16: - movzwl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue - -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue - -.Lrcls_retstruct1: - movsbl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct2: - movswl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct4: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue - -.Lrcls_retstruct: - - -.Lrcls_noretval: -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.ffi_closure_raw_SYSV_end: -.LFE4: - - - - - .balign 16 - .globl _ffi_closure_STDCALL - - .def _ffi_closure_STDCALL; .scl 2; .type 32; .endef - -_ffi_closure_STDCALL: -.LFB5: - pushl %ebp -.LCFI9: - movl %esp, %ebp -.LCFI10: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) - leal 12(%ebp), %edx - movl %edx, 4(%esp) - leal -12(%ebp), %edx - movl %edx, (%esp) - call _ffi_closure_SYSV_inner - movl -12(%ebp), %ecx -0: - call 1f - -.Lscls_store_table: - .long .Lscls_noretval - .long .Lscls_retint - .long .Lscls_retfloat - .long .Lscls_retdouble - .long .Lscls_retldouble - .long .Lscls_retuint8 - .long .Lscls_retsint8 - .long .Lscls_retuint16 - .long .Lscls_retsint16 - .long .Lscls_retint - .long .Lscls_retint - .long .Lscls_retllong - .long .Lscls_retllong - .long .Lscls_retstruct - .long .Lscls_retint - .long .Lscls_retstruct1 - .long .Lscls_retstruct2 - .long .Lscls_retstruct4 -1: - add %eax, %eax - add %eax, %eax - add (%esp),%eax - add $4, %esp - jmp *(%eax) - - -.Lscls_retsint8: - movsbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retsint16: - movswl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retuint8: - movzbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retuint16: - movzwl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retint: - movl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retfloat: - flds (%ecx) - jmp .Lscls_epilogue - -.Lscls_retdouble: - fldl (%ecx) - jmp .Lscls_epilogue - -.Lscls_retldouble: - fldt (%ecx) - jmp .Lscls_epilogue - -.Lscls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lscls_epilogue - -.Lscls_retstruct1: - movsbl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct2: - movswl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct4: - movl (%ecx), %eax - jmp .Lscls_epilogue - -.Lscls_retstruct: - - -.Lscls_noretval: -.Lscls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.ffi_closure_STDCALL_end: -.LFE5: - - - .section .eh_frame,"w" - -.Lframe1: -.LSCIE1: - .long .LECIE1-.LASCIE1 -.LASCIE1: - .long 0x0 - .byte 0x1 - - - - .ascii "\0" - - .byte 0x1 - .byte 0x7c - .byte 0x8 - - - - - .byte 0xc - .byte 0x4 - .byte 0x4 - .byte 0x88 - .byte 0x1 - .align 4 -.LECIE1: - -.LSFDE1: - .long .LEFDE1-.LASFDE1 -.LASFDE1: - .long .LASFDE1-.Lframe1 - - - - .long .LFB1 - - .long .LFE1-.LFB1 - - - - - - .byte 0x4 - .long .LCFI0-.LFB1 - .byte 0xe - .byte 0x8 - .byte 0x85 - .byte 0x2 - - .byte 0x4 - .long .LCFI1-.LCFI0 - .byte 0xd - .byte 0x5 - - - .align 4 -.LEFDE1: - - -.LSFDE3: - .long .LEFDE3-.LASFDE3 -.LASFDE3: - .long .LASFDE3-.Lframe1 - - - - .long .LFB3 - - .long .LFE3-.LFB3 - - - - - - .byte 0x4 - .long .LCFI4-.LFB3 - .byte 0xe - .byte 0x8 - .byte 0x85 - .byte 0x2 - - .byte 0x4 - .long .LCFI5-.LCFI4 - .byte 0xd - .byte 0x5 - - - .align 4 -.LEFDE3: - - - -.LSFDE4: - .long .LEFDE4-.LASFDE4 -.LASFDE4: - .long .LASFDE4-.Lframe1 - - - - .long .LFB4 - - .long .LFE4-.LFB4 - - - - - - .byte 0x4 - .long .LCFI6-.LFB4 - .byte 0xe - .byte 0x8 - .byte 0x85 - .byte 0x2 - - .byte 0x4 - .long .LCFI7-.LCFI6 - .byte 0xd - .byte 0x5 - - .byte 0x4 - .long .LCFI8-.LCFI7 - .byte 0x86 - .byte 0x3 - - - .align 4 -.LEFDE4: - - - -.LSFDE5: - .long .LEFDE5-.LASFDE5 -.LASFDE5: - .long .LASFDE5-.Lframe1 - - - - .long .LFB5 - - .long .LFE5-.LFB5 - - - - - - .byte 0x4 - .long .LCFI9-.LFB5 - .byte 0xe - .byte 0x8 - .byte 0x85 - .byte 0x2 - - .byte 0x4 - .long .LCFI10-.LCFI9 - .byte 0xd - .byte 0x5 - - - .align 4 -.LEFDE5: diff --git a/gcc/win64_asm.asm b/gcc/win64_asm.asm deleted file mode 100644 index 1dc98f9..0000000 --- a/gcc/win64_asm.asm +++ /dev/null @@ -1,467 +0,0 @@ -#define LIBFFI_ASM -#include -#include - -/* Constants for ffi_call_win64 */ -#define STACK 0 -#define PREP_ARGS_FN 32 -#define ECIF 40 -#define CIF_BYTES 48 -#define CIF_FLAGS 56 -#define RVALUE 64 -#define FN 72 - -/* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *), - extended_cif *ecif, unsigned bytes, unsigned flags, - unsigned *rvalue, void (*fn)()); - */ - -#ifdef _MSC_VER -PUBLIC ffi_call_win64 - -EXTRN __chkstk:NEAR -EXTRN ffi_closure_win64_inner:NEAR - -_TEXT SEGMENT - -;;; ffi_closure_win64 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_win64_inner for the actual work, then return the result. -;;; -ffi_closure_win64 PROC FRAME - ;; copy register arguments onto stack - 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 fourth -third_is_float: - movlpd QWORD PTR [rsp+24], xmm2 - -fourth: - test r11, 8 - jne fourth_is_float - mov QWORD PTR [rsp+32], r9 - jmp done -fourth_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, 48 ; point to start of arguments - mov rax, ffi_closure_win64_inner - call rax ; call the real closure function - add rsp, 40 - movd xmm0, rax ; If the closure returned a float, - ; ffi_closure_win64_inner wrote it to rax - ret 0 -ffi_closure_win64 ENDP - -ffi_call_win64 PROC FRAME - ;; copy registers onto stack - 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 CIF_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 PREP_ARGS_FN[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_struct4b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B - jne ret_struct2b$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov DWORD PTR [rcx], eax - jmp ret_void$ - -ret_struct2b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B - jne ret_struct1b$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov WORD PTR [rcx], ax - jmp ret_void$ - -ret_struct1b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B - jne ret_uint8$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov BYTE PTR [rcx], al - jmp ret_void$ - -ret_uint8$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8 - jne ret_sint8$ - - mov rcx, QWORD PTR RVALUE[rbp] - movzx rax, al - mov QWORD PTR [rcx], rax - jmp ret_void$ - -ret_sint8$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8 - jne ret_uint16$ - - mov rcx, QWORD PTR RVALUE[rbp] - movsx rax, al - mov QWORD PTR [rcx], rax - jmp ret_void$ - -ret_uint16$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16 - jne ret_sint16$ - - mov rcx, QWORD PTR RVALUE[rbp] - movzx rax, ax - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_sint16$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16 - jne ret_uint32$ - - mov rcx, QWORD PTR RVALUE[rbp] - movsx rax, ax - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_uint32$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32 - jne ret_sint32$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov eax, eax - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_sint32$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32 - jne ret_float$ - - mov rcx, QWORD PTR RVALUE[rbp] - cdqe - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_float$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT - jne SHORT ret_double$ - - mov rax, QWORD PTR RVALUE[rbp] - movss DWORD PTR [rax], xmm0 - jmp SHORT ret_void$ - -ret_double$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE - jne SHORT ret_sint64$ - - mov rax, QWORD PTR RVALUE[rbp] - movlpd QWORD PTR [rax], xmm0 - jmp SHORT ret_void$ - -ret_sint64$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 - jne ret_void$ - - mov rcx, QWORD PTR RVALUE[rbp] - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ - -ret_void$: - xor rax, rax - - lea rsp, QWORD PTR [rbp+16] - pop rbp - ret 0 -ffi_call_win64 ENDP -_TEXT ENDS -END - -#else - -#ifdef SYMBOL_UNDERSCORE -#define SYMBOL_NAME(name) _##name -#else -#define SYMBOL_NAME(name) name -#endif - -.text - -.extern SYMBOL_NAME(ffi_closure_win64_inner) - -// ffi_closure_win64 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_win64_inner for the actual work, then return the result. -// - .balign 16 - .globl SYMBOL_NAME(ffi_closure_win64) -SYMBOL_NAME(ffi_closure_win64): - // copy register arguments onto stack - test $1,%r11 - jne .Lfirst_is_float - mov %rcx, 8(%rsp) - jmp .Lsecond -.Lfirst_is_float: - movlpd %xmm0, 8(%rsp) - -.Lsecond: - test $2, %r11 - jne .Lsecond_is_float - mov %rdx, 16(%rsp) - jmp .Lthird -.Lsecond_is_float: - movlpd %xmm1, 16(%rsp) - -.Lthird: - test $4, %r11 - jne .Lthird_is_float - mov %r8,24(%rsp) - jmp .Lfourth -.Lthird_is_float: - movlpd %xmm2, 24(%rsp) - -.Lfourth: - test $8, %r11 - jne .Lfourth_is_float - mov %r9, 32(%rsp) - jmp .Ldone -.Lfourth_is_float: - movlpd %xmm3, 32(%rsp) - -.Ldone: -// ALLOCSTACK 40 - sub $40, %rsp -// ENDPROLOG - mov %rax, %rcx // context is first parameter - mov %rsp, %rdx // stack is second parameter - add $48, %rdx // point to start of arguments - mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax - callq *%rax // call the real closure function - add $40, %rsp - movq %rax, %xmm0 // If the closure returned a float, - // ffi_closure_win64_inner wrote it to rax - retq -.ffi_closure_win64_end: - - .balign 16 - .globl SYMBOL_NAME(ffi_call_win64) -SYMBOL_NAME(ffi_call_win64): - // copy registers onto stack - mov %r9,32(%rsp) - mov %r8,24(%rsp) - mov %rdx,16(%rsp) - mov %rcx,8(%rsp) - // PUSHREG rbp - push %rbp - // ALLOCSTACK 48 - sub $48,%rsp - // SETFRAME rbp, 32 - lea 32(%rsp),%rbp - // ENDPROLOG - - mov CIF_BYTES(%rbp),%eax - add $15, %rax - and $-16, %rax - cmpq $0x1000, %rax - jb Lch_done -Lch_probe: - subq $0x1000,%rsp - orl $0x0, (%rsp) - subq $0x1000,%rax - cmpq $0x1000,%rax - ja Lch_probe -Lch_done: - subq %rax, %rsp - orl $0x0, (%rsp) - lea 32(%rsp), %rax - mov %rax, STACK(%rbp) - - mov ECIF(%rbp), %rdx - mov STACK(%rbp), %rcx - callq *PREP_ARGS_FN(%rbp) - - mov STACK(%rbp), %rsp - - movlpd 24(%rsp), %xmm3 - movd %xmm3, %r9 - - movlpd 16(%rsp), %xmm2 - movd %xmm2, %r8 - - movlpd 8(%rsp), %xmm1 - movd %xmm1, %rdx - - movlpd (%rsp), %xmm0 - movd %xmm0, %rcx - - callq *FN(%rbp) -.Lret_struct4b: - cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp) - jne .Lret_struct2b - - mov RVALUE(%rbp), %rcx - mov %eax, (%rcx) - jmp .Lret_void - -.Lret_struct2b: - cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp) - jne .Lret_struct1b - - mov RVALUE(%rbp), %rcx - mov %ax, (%rcx) - jmp .Lret_void - -.Lret_struct1b: - cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp) - jne .Lret_uint8 - - mov RVALUE(%rbp), %rcx - mov %al, (%rcx) - jmp .Lret_void - -.Lret_uint8: - cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp) - jne .Lret_sint8 - - mov RVALUE(%rbp), %rcx - movzbq %al, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint8: - cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp) - jne .Lret_uint16 - - mov RVALUE(%rbp), %rcx - movsbq %al, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_uint16: - cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp) - jne .Lret_sint16 - - mov RVALUE(%rbp), %rcx - movzwq %ax, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint16: - cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp) - jne .Lret_uint32 - - mov RVALUE(%rbp), %rcx - movswq %ax, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_uint32: - cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp) - jne .Lret_sint32 - - mov RVALUE(%rbp), %rcx - movl %eax, %eax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint32: - cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp) - jne .Lret_float - - mov RVALUE(%rbp), %rcx - cltq - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_float: - cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp) - jne .Lret_double - - mov RVALUE(%rbp), %rax - movss %xmm0, (%rax) - jmp .Lret_void - -.Lret_double: - cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp) - jne .Lret_sint64 - - mov RVALUE(%rbp), %rax - movlpd %xmm0, (%rax) - jmp .Lret_void - -.Lret_sint64: - cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp) - jne .Lret_void - - mov RVALUE(%rbp), %rcx - mov %rax, (%rcx) - jmp .Lret_void - -.Lret_void: - xor %rax, %rax - - lea 16(%rbp), %rsp - pop %rbp - retq -.ffi_call_win64_end: -#endif /* !_MSC_VER */ - diff --git a/gcc/win64_asm.s b/gcc/win64_asm.s deleted file mode 100644 index f2c2df1..0000000 --- a/gcc/win64_asm.s +++ /dev/null @@ -1,227 +0,0 @@ -# 1 "gcc\\win64_asm.asm" -# 1 "" -# 1 "gcc\\win64_asm.asm" - -# 1 "common/fficonfig.h" 1 -# 3 "gcc\\win64_asm.asm" 2 -# 1 "common/ffi.h" 1 -# 63 "common/ffi.h" -# 1 "common/ffitarget.h" 1 -# 64 "common/ffi.h" 2 -# 4 "gcc\\win64_asm.asm" 2 -# 244 "gcc\\win64_asm.asm" -.text - -.extern ffi_closure_win64_inner -# 255 "gcc\\win64_asm.asm" - .balign 16 - .globl ffi_closure_win64 -ffi_closure_win64: - - test $1,%r11 - jne .Lfirst_is_float - mov %rcx, 8(%rsp) - jmp .Lsecond -.Lfirst_is_float: - movlpd %xmm0, 8(%rsp) - -.Lsecond: - test $2, %r11 - jne .Lsecond_is_float - mov %rdx, 16(%rsp) - jmp .Lthird -.Lsecond_is_float: - movlpd %xmm1, 16(%rsp) - -.Lthird: - test $4, %r11 - jne .Lthird_is_float - mov %r8,24(%rsp) - jmp .Lfourth -.Lthird_is_float: - movlpd %xmm2, 24(%rsp) - -.Lfourth: - test $8, %r11 - jne .Lfourth_is_float - mov %r9, 32(%rsp) - jmp .Ldone -.Lfourth_is_float: - movlpd %xmm3, 32(%rsp) - -.Ldone: - - sub $40, %rsp - - mov %rax, %rcx - mov %rsp, %rdx - add $48, %rdx - mov $SYMBOL_NAME(ffi_closure_win64_inner), %rax - callq *%rax - add $40, %rsp - movq %rax, %xmm0 - - retq -.ffi_closure_win64_end: - - .balign 16 - .globl ffi_call_win64 -ffi_call_win64: - - mov %r9,32(%rsp) - mov %r8,24(%rsp) - mov %rdx,16(%rsp) - mov %rcx,8(%rsp) - - push %rbp - - sub $48,%rsp - - lea 32(%rsp),%rbp - - - mov 48(%rbp),%eax - add $15, %rax - and $-16, %rax - cmpq $0x1000, %rax - jb Lch_done -Lch_probe: - subq $0x1000,%rsp - orl $0x0, (%rsp) - subq $0x1000,%rax - cmpq $0x1000,%rax - ja Lch_probe -Lch_done: - subq %rax, %rsp - orl $0x0, (%rsp) - lea 32(%rsp), %rax - mov %rax, 0(%rbp) - - mov 40(%rbp), %rdx - mov 0(%rbp), %rcx - callq *32(%rbp) - - mov 0(%rbp), %rsp - - movlpd 24(%rsp), %xmm3 - movd %xmm3, %r9 - - movlpd 16(%rsp), %xmm2 - movd %xmm2, %r8 - - movlpd 8(%rsp), %xmm1 - movd %xmm1, %rdx - - movlpd (%rsp), %xmm0 - movd %xmm0, %rcx - - callq *72(%rbp) -.Lret_struct4b: - cmpl $FFI_TYPE_SMALL_STRUCT_4B, 56(%rbp) - jne .Lret_struct2b - - mov 64(%rbp), %rcx - mov %eax, (%rcx) - jmp .Lret_void - -.Lret_struct2b: - cmpl $FFI_TYPE_SMALL_STRUCT_2B, 56(%rbp) - jne .Lret_struct1b - - mov 64(%rbp), %rcx - mov %ax, (%rcx) - jmp .Lret_void - -.Lret_struct1b: - cmpl $FFI_TYPE_SMALL_STRUCT_1B, 56(%rbp) - jne .Lret_uint8 - - mov 64(%rbp), %rcx - mov %al, (%rcx) - jmp .Lret_void - -.Lret_uint8: - cmpl $FFI_TYPE_UINT8, 56(%rbp) - jne .Lret_sint8 - - mov 64(%rbp), %rcx - movzbq %al, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint8: - cmpl $FFI_TYPE_SINT8, 56(%rbp) - jne .Lret_uint16 - - mov 64(%rbp), %rcx - movsbq %al, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_uint16: - cmpl $FFI_TYPE_UINT16, 56(%rbp) - jne .Lret_sint16 - - mov 64(%rbp), %rcx - movzwq %ax, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint16: - cmpl $FFI_TYPE_SINT16, 56(%rbp) - jne .Lret_uint32 - - mov 64(%rbp), %rcx - movswq %ax, %rax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_uint32: - cmpl $9, 56(%rbp) - jne .Lret_sint32 - - mov 64(%rbp), %rcx - movl %eax, %eax - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_sint32: - cmpl $10, 56(%rbp) - jne .Lret_float - - mov 64(%rbp), %rcx - cltq - movq %rax, (%rcx) - jmp .Lret_void - -.Lret_float: - cmpl $2, 56(%rbp) - jne .Lret_double - - mov 64(%rbp), %rax - movss %xmm0, (%rax) - jmp .Lret_void - -.Lret_double: - cmpl $3, 56(%rbp) - jne .Lret_sint64 - - mov 64(%rbp), %rax - movlpd %xmm0, (%rax) - jmp .Lret_void - -.Lret_sint64: - cmpl $12, 56(%rbp) - jne .Lret_void - - mov 64(%rbp), %rcx - mov %rax, (%rcx) - jmp .Lret_void - -.Lret_void: - xor %rax, %rax - - lea 16(%rbp), %rsp - pop %rbp - retq -.ffi_call_win64_end: diff --git a/libffi.nim b/libffi.nim index 0e9b69e..1284774 100644 --- a/libffi.nim +++ b/libffi.nim @@ -11,36 +11,15 @@ when defined(windows): import os - # on Windows we don't use a DLL but instead embed libffi directly: - const thisPath = currentSourcePath.parentDir - const flag = "-I" & (thisPath / "common") & " -I" & thisPath - {.passc: flag.} + const libPath = currentSourcePath.parentDir / "libs" - {.pragma: mylib, header: r"common/ffi.h".} - - #{.compile: r"common\malloc_closure.c".} - {.compile: r"common\raw_api.c".} - when defined(vcc): - {.compile: r"msvc\ffi.c".} - {.compile: r"msvc\prep_cif.c".} - {.compile: r"msvc\win32.c".} - {.compile: r"msvc\types.c".} - when defined(cpu64): - {.compile: r"msvc\win64_asm.asm".} - else: - {.compile: r"msvc\win32_asm.asm".} + when defined(cpu64): + const arch = "win64" else: - {.compile: r"gcc\ffi.c".} - {.compile: r"gcc\prep_cif.c".} - {.compile: r"gcc\types.c".} - {.compile: r"gcc\closures.c".} - when defined(cpu64): - {.compile: r"gcc\ffi64.c".} - {.compile: r"gcc\win64_asm.S".} - else: - {.compile: r"gcc\win32_asm.S".} + const arch = "win32" + {.pragma: mylib, dynlib: libPath / arch / "libffi-7.dll".} elif defined(macosx): {.pragma: mylib, dynlib: "libffi.dylib".} else: diff --git a/libs/win32/libffi-7.dll b/libs/win32/libffi-7.dll new file mode 100644 index 0000000000000000000000000000000000000000..d6d2085d73d5115714464f11cee115acb162f08c GIT binary patch literal 70845 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
    !q&V<_h>|;`)st(vlg8oZ0!q} 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 -#include - -#include - -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -extern void Py_FatalError(const char *msg); - -/*@-exportheader@*/ -void ffi_prep_args(char *stack, extended_cif *ecif) -/*@=exportheader@*/ -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) - { - *(void **) argp = ecif->rvalue; - argp += sizeof(void *); - } - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; - i != 0; - i--, p_arg++) - { - size_t z; - - /* Align if necessary */ - if ((sizeof(void *) - 1) & (size_t) argp) - argp = (char *) ALIGN(argp, sizeof(void *)); - - z = (*p_arg)->size; - if (z < sizeof(int)) - { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - break; - - case FFI_TYPE_STRUCT: - *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else - { - memcpy(argp, *p_argv, z); - } - p_argv++; - argp += z; - } - - if (argp >= stack && (unsigned)(argp - stack) > ecif->cif->bytes) - { - Py_FatalError("FFI BUG: not enough stack space for arguments"); - } - return; -} - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) -{ - /* Set the return type flag */ - switch (cif->rtype->type) - { - case FFI_TYPE_VOID: - case FFI_TYPE_STRUCT: - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - case FFI_TYPE_LONGDOUBLE: - cif->flags = (unsigned) cif->rtype->type; - break; - - case FFI_TYPE_UINT64: -#ifdef _WIN64 - case FFI_TYPE_POINTER: -#endif - cif->flags = FFI_TYPE_SINT64; - break; - - default: - cif->flags = FFI_TYPE_INT; - break; - } - - return FFI_OK; -} - -#ifdef _WIN32 -extern int -ffi_call_x86(void (*)(char *, extended_cif *), - /*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)()); -#endif - -#ifdef _WIN64 -extern int -ffi_call_AMD64(void (*)(char *, extended_cif *), - /*@out@*/ extended_cif *, - unsigned, unsigned, - /*@out@*/ unsigned *, - void (*fn)()); -#endif - -int -ffi_call(/*@dependent@*/ ffi_cif *cif, - void (*fn)(), - /*@out@*/ void *rvalue, - /*@dependent@*/ void **avalue) -{ - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if ((rvalue == NULL) && - (cif->rtype->type == FFI_TYPE_STRUCT)) - { - /*@-sysunrecog@*/ - ecif.rvalue = alloca(cif->rtype->size); - /*@=sysunrecog@*/ - } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) - { -#if !defined(_WIN64) - case FFI_SYSV: - case FFI_STDCALL: - return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); - break; -#else - case FFI_SYSV: - /*@-usedef@*/ - /* Function call needs at least 40 bytes stack size, on win64 AMD64 */ - return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes ? cif->bytes : 40, - cif->flags, ecif.rvalue, fn); - /*@=usedef@*/ - break; -#endif - - default: - FFI_ASSERT(0); - break; - } - return -1; /* theller: Hrm. */ -} - - -/** private members **/ - -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif); -/* This function is jumped to by the trampoline */ - -#ifdef _WIN64 -void * -#else -static void __fastcall -#endif -ffi_closure_SYSV (ffi_closure *closure, int *argp) -{ - // this is our return value storage - long double res; - - // our various things... - ffi_cif *cif; - void **arg_area; - unsigned short rtype; - void *resp = (void*)&res; - void *args = &argp[1]; - - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); - - /* this call will initialize ARG_AREA, such that each - * element in that array points to the corresponding - * value on the stack; and if the function returns - * a structure, it will re-set RESP to point to the - * structure return address. */ - - ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif); - - (closure->fun) (cif, resp, arg_area, closure->user_data); - - rtype = cif->flags; - -#if defined(_WIN32) && !defined(_WIN64) -#ifdef _MSC_VER - /* now, do a generic return based on the value of rtype */ - if (rtype == FFI_TYPE_INT) - { - _asm mov eax, resp ; - _asm mov eax, [eax] ; - } - else if (rtype == FFI_TYPE_FLOAT) - { - _asm mov eax, resp ; - _asm fld DWORD PTR [eax] ; -// asm ("flds (%0)" : : "r" (resp) : "st" ); - } - else if (rtype == FFI_TYPE_DOUBLE) - { - _asm mov eax, resp ; - _asm fld QWORD PTR [eax] ; -// asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); - } - else if (rtype == FFI_TYPE_LONGDOUBLE) - { -// asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); - } - else if (rtype == FFI_TYPE_SINT64) - { - _asm mov edx, resp ; - _asm mov eax, [edx] ; - _asm mov edx, [edx + 4] ; -// asm ("movl 0(%0),%%eax;" -// "movl 4(%0),%%edx" -// : : "r"(resp) -// : "eax", "edx"); - } -#else - /* now, do a generic return based on the value of rtype */ - if (rtype == FFI_TYPE_INT) - { - asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); - } - else if (rtype == FFI_TYPE_FLOAT) - { - asm ("flds (%0)" : : "r" (resp) : "st" ); - } - else if (rtype == FFI_TYPE_DOUBLE) - { - asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); - } - else if (rtype == FFI_TYPE_LONGDOUBLE) - { - asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); - } - else if (rtype == FFI_TYPE_SINT64) - { - asm ("movl 0(%0),%%eax;" - "movl 4(%0),%%edx" - : : "r"(resp) - : "eax", "edx"); - } -#endif -#endif - -#ifdef _WIN64 - /* The result is returned in rax. This does the right thing for - result types except for floats; we have to 'mov xmm0, rax' in the - caller to correct this. - */ - return *(void **)resp; -#endif -} - -/*@-exportheader@*/ -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, - void **avalue, ffi_cif *cif) -/*@=exportheader@*/ -{ - register unsigned int i; - register void **p_argv; - register char *argp; - register ffi_type **p_arg; - - argp = stack; - - if ( cif->rtype->type == FFI_TYPE_STRUCT ) { - *rvalue = *(void **) argp; - argp += 4; - } - - p_argv = avalue; - - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) - { - size_t z; - - /* Align if necessary */ - if ((sizeof(char *) - 1) & (size_t) argp) { - argp = (char *) ALIGN(argp, sizeof(char*)); - } - - z = (*p_arg)->size; - - /* because we're little endian, this is what it turns into. */ - - *p_argv = (void*) argp; - - p_argv++; - argp += z; - } - - return; -} - -/* the cif must already be prep'ed */ -extern void ffi_closure_OUTER(); - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) -{ - short bytes; - char *tramp; -#ifdef _WIN64 - int mask = 0; -#endif - FFI_ASSERT (cif->abi == FFI_SYSV); - - if (cif->abi == FFI_SYSV) - bytes = 0; -#if !defined(_WIN64) - else if (cif->abi == FFI_STDCALL) - bytes = cif->bytes; -#endif - else - return FFI_BAD_ABI; - - tramp = &closure->tramp[0]; - -#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1 -#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*) -#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short) -#define INT(x) *(int*)tramp = x, tramp += sizeof(int) - -#ifdef _WIN64 - if (cif->nargs >= 1 && - (cif->arg_types[0]->type == FFI_TYPE_FLOAT - || cif->arg_types[0]->type == FFI_TYPE_DOUBLE)) - mask |= 1; - if (cif->nargs >= 2 && - (cif->arg_types[1]->type == FFI_TYPE_FLOAT - || cif->arg_types[1]->type == FFI_TYPE_DOUBLE)) - mask |= 2; - if (cif->nargs >= 3 && - (cif->arg_types[2]->type == FFI_TYPE_FLOAT - || cif->arg_types[2]->type == FFI_TYPE_DOUBLE)) - mask |= 4; - if (cif->nargs >= 4 && - (cif->arg_types[3]->type == FFI_TYPE_FLOAT - || cif->arg_types[3]->type == FFI_TYPE_DOUBLE)) - mask |= 8; - - /* 41 BB ---- mov r11d,mask */ - BYTES("\x41\xBB"); INT(mask); - - /* 48 B8 -------- mov rax, closure */ - BYTES("\x48\xB8"); POINTER(closure); - - /* 49 BA -------- mov r10, ffi_closure_OUTER */ - BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER); - - /* 41 FF E2 jmp r10 */ - BYTES("\x41\xFF\xE2"); - -#else - - /* mov ecx, closure */ - BYTES("\xb9"); POINTER(closure); - - /* mov edx, esp */ - BYTES("\x8b\xd4"); - - /* call ffi_closure_SYSV */ - BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4)); - - /* ret bytes */ - BYTES("\xc2"); - SHORT(bytes); - -#endif - - if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE) - Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__); - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; - return FFI_OK; -} diff --git a/msvc/prep_cif.c b/msvc/prep_cif.c deleted file mode 100644 index 2650fa0..0000000 --- a/msvc/prep_cif.c +++ /dev/null @@ -1,175 +0,0 @@ -/* ----------------------------------------------------------------------- - 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 -#include -#include - - -/* 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 += STACK_ARG_SIZE((*ptr)->size); - } -#endif - } - - cif->bytes = bytes; - - /* Perform machine dependent cif processing */ - return ffi_prep_cif_machdep(cif); -} diff --git a/msvc/types.c b/msvc/types.c deleted file mode 100644 index df32190..0000000 --- a/msvc/types.c +++ /dev/null @@ -1,104 +0,0 @@ -/* ----------------------------------------------------------------------- - 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 -#include - -/* 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 - diff --git a/msvc/win32.c b/msvc/win32.c deleted file mode 100644 index 2754fd3..0000000 --- a/msvc/win32.c +++ /dev/null @@ -1,162 +0,0 @@ -/* ----------------------------------------------------------------------- - 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 -#include - -__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 explicitly 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 - } -} diff --git a/msvc/win32_asm.asm b/msvc/win32_asm.asm deleted file mode 100644 index 407185e..0000000 --- a/msvc/win32_asm.asm +++ /dev/null @@ -1,470 +0,0 @@ -/* ----------------------------------------------------------------------- - win32.S - Copyright (c) 1996, 1998, 2001, 2002, 2009 Red Hat, Inc. - Copyright (c) 2001 John Beniton - Copyright (c) 2002 Ranjit Mathew - Copyright (c) 2009 Daniel Witte - - - X86 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- - */ - -#define LIBFFI_ASM -#include -#include - -.386 -.MODEL FLAT, C - -EXTRN ffi_closure_SYSV_inner:NEAR - -_TEXT SEGMENT - -ffi_call_win32 PROC NEAR, - ffi_prep_args : NEAR PTR DWORD, - ecif : NEAR PTR DWORD, - cif_abi : DWORD, - cif_bytes : DWORD, - cif_flags : DWORD, - rvalue : NEAR PTR DWORD, - fn : NEAR PTR DWORD - - ;; Make room for all of the new args. - mov ecx, cif_bytes - sub esp, ecx - - mov eax, esp - - ;; Place all of the ffi_prep_args in position - push ecif - push eax - call ffi_prep_args - - ;; Return stack to previous state and call the function - add esp, 8 - - ;; Handle thiscall and fastcall - cmp cif_abi, 3 ;; FFI_THISCALL - jz do_thiscall - cmp cif_abi, 4 ;; FFI_FASTCALL - jnz do_stdcall - mov ecx, DWORD PTR [esp] - mov edx, DWORD PTR [esp+4] - add esp, 8 - jmp do_stdcall -do_thiscall: - mov ecx, DWORD PTR [esp] - add esp, 4 -do_stdcall: - call fn - - ;; cdecl: we restore esp in the epilogue, so there's no need to - ;; remove the space we pushed for the args. - ;; stdcall: the callee has already cleaned the stack. - - ;; Load ecx with the return type code - mov ecx, cif_flags - - ;; If the return value pointer is NULL, assume no return value. - cmp rvalue, 0 - jne ca_jumptable - - ;; Even if there is no space for the return value, we are - ;; obliged to handle floating-point values. - cmp ecx, FFI_TYPE_FLOAT - jne ca_epilogue - fstp st(0) - - jmp ca_epilogue - -ca_jumptable: - jmp [ca_jumpdata + 4 * ecx] -ca_jumpdata: - ;; Do not insert anything here between label and jump table. - dd offset ca_epilogue ;; FFI_TYPE_VOID - dd offset ca_retint ;; FFI_TYPE_INT - dd offset ca_retfloat ;; FFI_TYPE_FLOAT - dd offset ca_retdouble ;; FFI_TYPE_DOUBLE - dd offset ca_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset ca_retuint8 ;; FFI_TYPE_UINT8 - dd offset ca_retsint8 ;; FFI_TYPE_SINT8 - dd offset ca_retuint16 ;; FFI_TYPE_UINT16 - dd offset ca_retsint16 ;; FFI_TYPE_SINT16 - dd offset ca_retint ;; FFI_TYPE_UINT32 - dd offset ca_retint ;; FFI_TYPE_SINT32 - dd offset ca_retint64 ;; FFI_TYPE_UINT64 - dd offset ca_retint64 ;; FFI_TYPE_SINT64 - dd offset ca_epilogue ;; FFI_TYPE_STRUCT - dd offset ca_retint ;; FFI_TYPE_POINTER - dd offset ca_retstruct1b ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset ca_retstruct2b ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset ca_retint ;; FFI_TYPE_SMALL_STRUCT_4B - dd offset ca_epilogue ;; FFI_TYPE_MS_STRUCT - - /* Sign/zero extend as appropriate. */ -ca_retuint8: - movzx eax, al - jmp ca_retint - -ca_retsint8: - movsx eax, al - jmp ca_retint - -ca_retuint16: - movzx eax, ax - jmp ca_retint - -ca_retsint16: - movsx eax, ax - jmp ca_retint - -ca_retint: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], eax - jmp ca_epilogue - -ca_retint64: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], eax - mov [ecx + 4], edx - jmp ca_epilogue - -ca_retfloat: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - fstp DWORD PTR [ecx] - jmp ca_epilogue - -ca_retdouble: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - fstp QWORD PTR [ecx] - jmp ca_epilogue - -ca_retlongdouble: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - fstp TBYTE PTR [ecx] - jmp ca_epilogue - -ca_retstruct1b: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], al - jmp ca_epilogue - -ca_retstruct2b: - ;; Load %ecx with the pointer to storage for the return value - mov ecx, rvalue - mov [ecx + 0], ax - jmp ca_epilogue - -ca_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_call_win32 ENDP - -ffi_closure_THISCALL PROC NEAR FORCEFRAME - sub esp, 40 - lea edx, [ebp -24] - mov [ebp - 12], edx /* resp */ - lea edx, [ebp + 12] /* account for stub return address on stack */ - jmp stub -ffi_closure_THISCALL ENDP - -ffi_closure_SYSV PROC NEAR FORCEFRAME - ;; the ffi_closure ctx is passed in eax by the trampoline. - - sub esp, 40 - lea edx, [ebp - 24] - mov [ebp - 12], edx ;; resp - lea edx, [ebp + 8] -stub:: - mov [esp + 8], edx ;; args - lea edx, [ebp - 12] - mov [esp + 4], edx ;; &resp - mov [esp], eax ;; closure - call ffi_closure_SYSV_inner - mov ecx, [ebp - 12] - -cs_jumptable: - jmp [cs_jumpdata + 4 * eax] -cs_jumpdata: - ;; Do not insert anything here between the label and jump table. - dd offset cs_epilogue ;; FFI_TYPE_VOID - dd offset cs_retint ;; FFI_TYPE_INT - dd offset cs_retfloat ;; FFI_TYPE_FLOAT - dd offset cs_retdouble ;; FFI_TYPE_DOUBLE - dd offset cs_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset cs_retuint8 ;; FFI_TYPE_UINT8 - dd offset cs_retsint8 ;; FFI_TYPE_SINT8 - dd offset cs_retuint16 ;; FFI_TYPE_UINT16 - dd offset cs_retsint16 ;; FFI_TYPE_SINT16 - dd offset cs_retint ;; FFI_TYPE_UINT32 - dd offset cs_retint ;; FFI_TYPE_SINT32 - dd offset cs_retint64 ;; FFI_TYPE_UINT64 - dd offset cs_retint64 ;; FFI_TYPE_SINT64 - dd offset cs_retstruct ;; FFI_TYPE_STRUCT - dd offset cs_retint ;; FFI_TYPE_POINTER - dd offset cs_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset cs_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset cs_retint ;; FFI_TYPE_SMALL_STRUCT_4B - dd offset cs_retmsstruct ;; FFI_TYPE_MS_STRUCT - -cs_retuint8: - movzx eax, BYTE PTR [ecx] - jmp cs_epilogue - -cs_retsint8: - movsx eax, BYTE PTR [ecx] - jmp cs_epilogue - -cs_retuint16: - movzx eax, WORD PTR [ecx] - jmp cs_epilogue - -cs_retsint16: - movsx eax, WORD PTR [ecx] - jmp cs_epilogue - -cs_retint: - mov eax, [ecx] - jmp cs_epilogue - -cs_retint64: - mov eax, [ecx + 0] - mov edx, [ecx + 4] - jmp cs_epilogue - -cs_retfloat: - fld DWORD PTR [ecx] - jmp cs_epilogue - -cs_retdouble: - fld QWORD PTR [ecx] - jmp cs_epilogue - -cs_retlongdouble: - fld TBYTE PTR [ecx] - jmp cs_epilogue - -cs_retstruct: - ;; Caller expects us to pop struct return value pointer hidden arg. - ;; Epilogue code is autogenerated. - ret 4 - -cs_retmsstruct: - ;; Caller expects us to return a pointer to the real return value. - mov eax, ecx - ;; Caller doesn't expects us to pop struct return value pointer hidden arg. - jmp cs_epilogue - -cs_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_closure_SYSV ENDP - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) AND NOT 3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#define CIF_FLAGS_OFFSET 20 - -ffi_closure_raw_THISCALL PROC NEAR USES esi FORCEFRAME - 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] - jmp stubraw -ffi_closure_raw_THISCALL ENDP - -ffi_closure_raw_SYSV PROC NEAR USES esi FORCEFRAME - ;; the ffi_closure ctx is passed in eax by the trampoline. - - sub esp, 40 - mov esi, [eax + RAW_CLOSURE_CIF_OFFSET] ;; closure->cif - mov edx, [eax + RAW_CLOSURE_USER_DATA_OFFSET] ;; closure->user_data - mov [esp + 12], edx ;; user_data - lea edx, [ebp + 8] -stubraw:: - mov [esp + 8], edx ;; raw_args - lea edx, [ebp - 24] - mov [esp + 4], edx ;; &res - mov [esp], esi ;; cif - call DWORD PTR [eax + RAW_CLOSURE_FUN_OFFSET] ;; closure->fun - mov eax, [esi + CIF_FLAGS_OFFSET] ;; cif->flags - lea ecx, [ebp - 24] - -cr_jumptable: - jmp [cr_jumpdata + 4 * eax] -cr_jumpdata: - ;; Do not insert anything here between the label and jump table. - dd offset cr_epilogue ;; FFI_TYPE_VOID - dd offset cr_retint ;; FFI_TYPE_INT - dd offset cr_retfloat ;; FFI_TYPE_FLOAT - dd offset cr_retdouble ;; FFI_TYPE_DOUBLE - dd offset cr_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset cr_retuint8 ;; FFI_TYPE_UINT8 - dd offset cr_retsint8 ;; FFI_TYPE_SINT8 - dd offset cr_retuint16 ;; FFI_TYPE_UINT16 - dd offset cr_retsint16 ;; FFI_TYPE_SINT16 - dd offset cr_retint ;; FFI_TYPE_UINT32 - dd offset cr_retint ;; FFI_TYPE_SINT32 - dd offset cr_retint64 ;; FFI_TYPE_UINT64 - dd offset cr_retint64 ;; FFI_TYPE_SINT64 - dd offset cr_epilogue ;; FFI_TYPE_STRUCT - dd offset cr_retint ;; FFI_TYPE_POINTER - dd offset cr_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset cr_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset cr_retint ;; FFI_TYPE_SMALL_STRUCT_4B - dd offset cr_epilogue ;; FFI_TYPE_MS_STRUCT - -cr_retuint8: - movzx eax, BYTE PTR [ecx] - jmp cr_epilogue - -cr_retsint8: - movsx eax, BYTE PTR [ecx] - jmp cr_epilogue - -cr_retuint16: - movzx eax, WORD PTR [ecx] - jmp cr_epilogue - -cr_retsint16: - movsx eax, WORD PTR [ecx] - jmp cr_epilogue - -cr_retint: - mov eax, [ecx] - jmp cr_epilogue - -cr_retint64: - mov eax, [ecx + 0] - mov edx, [ecx + 4] - jmp cr_epilogue - -cr_retfloat: - fld DWORD PTR [ecx] - jmp cr_epilogue - -cr_retdouble: - fld QWORD PTR [ecx] - jmp cr_epilogue - -cr_retlongdouble: - fld TBYTE PTR [ecx] - jmp cr_epilogue - -cr_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_closure_raw_SYSV ENDP - -#endif /* !FFI_NO_RAW_API */ - -ffi_closure_STDCALL PROC NEAR FORCEFRAME - ;; the ffi_closure ctx is passed in eax by the trampoline. - - sub esp, 40 - lea edx, [ebp - 24] - mov [ebp - 12], edx ;; resp - lea edx, [ebp + 12] ;; account for stub return address on stack - mov [esp + 8], edx ;; args - lea edx, [ebp - 12] - mov [esp + 4], edx ;; &resp - mov [esp], eax ;; closure - call ffi_closure_SYSV_inner - mov ecx, [ebp - 12] - -cd_jumptable: - jmp [cd_jumpdata + 4 * eax] -cd_jumpdata: - ;; Do not insert anything here between the label and jump table. - dd offset cd_epilogue ;; FFI_TYPE_VOID - dd offset cd_retint ;; FFI_TYPE_INT - dd offset cd_retfloat ;; FFI_TYPE_FLOAT - dd offset cd_retdouble ;; FFI_TYPE_DOUBLE - dd offset cd_retlongdouble ;; FFI_TYPE_LONGDOUBLE - dd offset cd_retuint8 ;; FFI_TYPE_UINT8 - dd offset cd_retsint8 ;; FFI_TYPE_SINT8 - dd offset cd_retuint16 ;; FFI_TYPE_UINT16 - dd offset cd_retsint16 ;; FFI_TYPE_SINT16 - dd offset cd_retint ;; FFI_TYPE_UINT32 - dd offset cd_retint ;; FFI_TYPE_SINT32 - dd offset cd_retint64 ;; FFI_TYPE_UINT64 - dd offset cd_retint64 ;; FFI_TYPE_SINT64 - dd offset cd_epilogue ;; FFI_TYPE_STRUCT - dd offset cd_retint ;; FFI_TYPE_POINTER - dd offset cd_retsint8 ;; FFI_TYPE_SMALL_STRUCT_1B - dd offset cd_retsint16 ;; FFI_TYPE_SMALL_STRUCT_2B - dd offset cd_retint ;; FFI_TYPE_SMALL_STRUCT_4B - -cd_retuint8: - movzx eax, BYTE PTR [ecx] - jmp cd_epilogue - -cd_retsint8: - movsx eax, BYTE PTR [ecx] - jmp cd_epilogue - -cd_retuint16: - movzx eax, WORD PTR [ecx] - jmp cd_epilogue - -cd_retsint16: - movsx eax, WORD PTR [ecx] - jmp cd_epilogue - -cd_retint: - mov eax, [ecx] - jmp cd_epilogue - -cd_retint64: - mov eax, [ecx + 0] - mov edx, [ecx + 4] - jmp cd_epilogue - -cd_retfloat: - fld DWORD PTR [ecx] - jmp cd_epilogue - -cd_retdouble: - fld QWORD PTR [ecx] - jmp cd_epilogue - -cd_retlongdouble: - fld TBYTE PTR [ecx] - jmp cd_epilogue - -cd_epilogue: - ;; Epilogue code is autogenerated. - ret -ffi_closure_STDCALL ENDP - -_TEXT ENDS -END diff --git a/msvc/win64_asm.asm b/msvc/win64_asm.asm deleted file mode 100644 index 301188b..0000000 --- a/msvc/win64_asm.asm +++ /dev/null @@ -1,156 +0,0 @@ -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