jpayne@69: /* -----------------------------------------------------------------*-C-*- jpayne@69: libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green jpayne@69: - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. jpayne@69: jpayne@69: Permission is hereby granted, free of charge, to any person jpayne@69: obtaining a copy of this software and associated documentation jpayne@69: files (the ``Software''), to deal in the Software without jpayne@69: restriction, including without limitation the rights to use, copy, jpayne@69: modify, merge, publish, distribute, sublicense, and/or sell copies jpayne@69: of the Software, and to permit persons to whom the Software is jpayne@69: furnished to do so, subject to the following conditions: jpayne@69: jpayne@69: The above copyright notice and this permission notice shall be jpayne@69: included in all copies or substantial portions of the Software. jpayne@69: jpayne@69: THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, jpayne@69: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF jpayne@69: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND jpayne@69: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT jpayne@69: HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, jpayne@69: WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, jpayne@69: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER jpayne@69: DEALINGS IN THE SOFTWARE. jpayne@69: jpayne@69: ----------------------------------------------------------------------- */ jpayne@69: jpayne@69: /* ------------------------------------------------------------------- jpayne@69: The basic API is described in the README file. jpayne@69: jpayne@69: The raw API is designed to bypass some of the argument packing jpayne@69: and unpacking on architectures for which it can be avoided. jpayne@69: jpayne@69: The closure API allows interpreted functions to be packaged up jpayne@69: inside a C function pointer, so that they can be called as C functions, jpayne@69: with no understanding on the client side that they are interpreted. jpayne@69: It can also be used in other cases in which it is necessary to package jpayne@69: up a user specified parameter and a function pointer as a single jpayne@69: function pointer. jpayne@69: jpayne@69: The closure API must be implemented in order to get its functionality, jpayne@69: e.g. for use by gij. Routines are provided to emulate the raw API jpayne@69: if the underlying platform doesn't allow faster implementation. jpayne@69: jpayne@69: More details on the raw and cloure API can be found in: jpayne@69: jpayne@69: http://gcc.gnu.org/ml/java/1999-q3/msg00138.html jpayne@69: jpayne@69: and jpayne@69: jpayne@69: http://gcc.gnu.org/ml/java/1999-q3/msg00174.html jpayne@69: -------------------------------------------------------------------- */ jpayne@69: jpayne@69: #ifndef LIBFFI_H jpayne@69: #define LIBFFI_H jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: extern "C" { jpayne@69: #endif jpayne@69: jpayne@69: /* Specify which architecture libffi is configured for. */ jpayne@69: #ifndef X86_64 jpayne@69: #define X86_64 jpayne@69: #endif jpayne@69: jpayne@69: /* ---- System configuration information --------------------------------- */ jpayne@69: jpayne@69: #include jpayne@69: jpayne@69: #ifndef LIBFFI_ASM jpayne@69: jpayne@69: #if defined(_MSC_VER) && !defined(__clang__) jpayne@69: #define __attribute__(X) jpayne@69: #endif jpayne@69: jpayne@69: #include jpayne@69: #include jpayne@69: jpayne@69: /* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). jpayne@69: But we can find it either under the correct ANSI name, or under GNU jpayne@69: C's internal name. */ jpayne@69: jpayne@69: #define FFI_64_BIT_MAX 9223372036854775807 jpayne@69: jpayne@69: #ifdef LONG_LONG_MAX jpayne@69: # define FFI_LONG_LONG_MAX LONG_LONG_MAX jpayne@69: #else jpayne@69: # ifdef LLONG_MAX jpayne@69: # define FFI_LONG_LONG_MAX LLONG_MAX jpayne@69: # ifdef _AIX52 /* or newer has C99 LLONG_MAX */ jpayne@69: # undef FFI_64_BIT_MAX jpayne@69: # define FFI_64_BIT_MAX 9223372036854775807LL jpayne@69: # endif /* _AIX52 or newer */ jpayne@69: # else jpayne@69: # ifdef __GNUC__ jpayne@69: # define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ jpayne@69: # endif jpayne@69: # ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */ jpayne@69: # ifndef __PPC64__ jpayne@69: # if defined (__IBMC__) || defined (__IBMCPP__) jpayne@69: # define FFI_LONG_LONG_MAX LONGLONG_MAX jpayne@69: # endif jpayne@69: # endif /* __PPC64__ */ jpayne@69: # undef FFI_64_BIT_MAX jpayne@69: # define FFI_64_BIT_MAX 9223372036854775807LL jpayne@69: # endif jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: /* The closure code assumes that this works on pointers, i.e. a size_t */ jpayne@69: /* can hold a pointer. */ jpayne@69: jpayne@69: typedef struct _ffi_type jpayne@69: { jpayne@69: size_t size; jpayne@69: unsigned short alignment; jpayne@69: unsigned short type; jpayne@69: struct _ffi_type **elements; jpayne@69: } ffi_type; jpayne@69: jpayne@69: #ifndef LIBFFI_HIDE_BASIC_TYPES jpayne@69: #if SCHAR_MAX == 127 jpayne@69: # define ffi_type_uchar ffi_type_uint8 jpayne@69: # define ffi_type_schar ffi_type_sint8 jpayne@69: #else jpayne@69: #error "char size not supported" jpayne@69: #endif jpayne@69: jpayne@69: #if SHRT_MAX == 32767 jpayne@69: # define ffi_type_ushort ffi_type_uint16 jpayne@69: # define ffi_type_sshort ffi_type_sint16 jpayne@69: #elif SHRT_MAX == 2147483647 jpayne@69: # define ffi_type_ushort ffi_type_uint32 jpayne@69: # define ffi_type_sshort ffi_type_sint32 jpayne@69: #else jpayne@69: #error "short size not supported" jpayne@69: #endif jpayne@69: jpayne@69: #if INT_MAX == 32767 jpayne@69: # define ffi_type_uint ffi_type_uint16 jpayne@69: # define ffi_type_sint ffi_type_sint16 jpayne@69: #elif INT_MAX == 2147483647 jpayne@69: # define ffi_type_uint ffi_type_uint32 jpayne@69: # define ffi_type_sint ffi_type_sint32 jpayne@69: #elif INT_MAX == 9223372036854775807 jpayne@69: # define ffi_type_uint ffi_type_uint64 jpayne@69: # define ffi_type_sint ffi_type_sint64 jpayne@69: #else jpayne@69: #error "int size not supported" jpayne@69: #endif jpayne@69: jpayne@69: #if LONG_MAX == 2147483647 jpayne@69: # if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX jpayne@69: #error "no 64-bit data type supported" jpayne@69: # endif jpayne@69: #elif LONG_MAX != FFI_64_BIT_MAX jpayne@69: #error "long size not supported" jpayne@69: #endif jpayne@69: jpayne@69: #if LONG_MAX == 2147483647 jpayne@69: # define ffi_type_ulong ffi_type_uint32 jpayne@69: # define ffi_type_slong ffi_type_sint32 jpayne@69: #elif LONG_MAX == FFI_64_BIT_MAX jpayne@69: # define ffi_type_ulong ffi_type_uint64 jpayne@69: # define ffi_type_slong ffi_type_sint64 jpayne@69: #else jpayne@69: #error "long size not supported" jpayne@69: #endif jpayne@69: jpayne@69: /* Need minimal decorations for DLLs to works on Windows. */ jpayne@69: /* GCC has autoimport and autoexport. Rely on Libtool to */ jpayne@69: /* help MSVC export from a DLL, but always declare data */ jpayne@69: /* to be imported for MSVC clients. This costs an extra */ jpayne@69: /* indirection for MSVC clients using the static version */ jpayne@69: /* of the library, but don't worry about that. Besides, */ jpayne@69: /* as a workaround, they can define FFI_BUILDING if they */ jpayne@69: /* *know* they are going to link with the static library. */ jpayne@69: #if defined _MSC_VER && !defined FFI_BUILDING jpayne@69: #define FFI_EXTERN extern __declspec(dllimport) jpayne@69: #else jpayne@69: #define FFI_EXTERN extern jpayne@69: #endif jpayne@69: jpayne@69: /* These are defined in types.c */ jpayne@69: FFI_EXTERN ffi_type ffi_type_void; jpayne@69: FFI_EXTERN ffi_type ffi_type_uint8; jpayne@69: FFI_EXTERN ffi_type ffi_type_sint8; jpayne@69: FFI_EXTERN ffi_type ffi_type_uint16; jpayne@69: FFI_EXTERN ffi_type ffi_type_sint16; jpayne@69: FFI_EXTERN ffi_type ffi_type_uint32; jpayne@69: FFI_EXTERN ffi_type ffi_type_sint32; jpayne@69: FFI_EXTERN ffi_type ffi_type_uint64; jpayne@69: FFI_EXTERN ffi_type ffi_type_sint64; jpayne@69: FFI_EXTERN ffi_type ffi_type_float; jpayne@69: FFI_EXTERN ffi_type ffi_type_double; jpayne@69: FFI_EXTERN ffi_type ffi_type_pointer; jpayne@69: jpayne@69: #if 1 jpayne@69: FFI_EXTERN ffi_type ffi_type_longdouble; jpayne@69: #else jpayne@69: #define ffi_type_longdouble ffi_type_double jpayne@69: #endif jpayne@69: jpayne@69: #ifdef FFI_TARGET_HAS_COMPLEX_TYPE jpayne@69: FFI_EXTERN ffi_type ffi_type_complex_float; jpayne@69: FFI_EXTERN ffi_type ffi_type_complex_double; jpayne@69: #if 1 jpayne@69: FFI_EXTERN ffi_type ffi_type_complex_longdouble; jpayne@69: #else jpayne@69: #define ffi_type_complex_longdouble ffi_type_complex_double jpayne@69: #endif jpayne@69: #endif jpayne@69: #endif /* LIBFFI_HIDE_BASIC_TYPES */ jpayne@69: jpayne@69: typedef enum { jpayne@69: FFI_OK = 0, jpayne@69: FFI_BAD_TYPEDEF, jpayne@69: FFI_BAD_ABI jpayne@69: } ffi_status; jpayne@69: jpayne@69: typedef unsigned FFI_TYPE; jpayne@69: jpayne@69: typedef struct { jpayne@69: ffi_abi abi; jpayne@69: unsigned nargs; jpayne@69: ffi_type **arg_types; jpayne@69: ffi_type *rtype; jpayne@69: unsigned bytes; jpayne@69: unsigned flags; jpayne@69: #ifdef FFI_EXTRA_CIF_FIELDS jpayne@69: FFI_EXTRA_CIF_FIELDS; jpayne@69: #endif jpayne@69: } ffi_cif; jpayne@69: jpayne@69: #if 0 jpayne@69: /* Used to adjust size/alignment of ffi types. */ jpayne@69: void ffi_prep_types (ffi_abi abi); jpayne@69: #endif jpayne@69: jpayne@69: /* Used internally, but overridden by some architectures */ jpayne@69: ffi_status ffi_prep_cif_core(ffi_cif *cif, jpayne@69: ffi_abi abi, jpayne@69: unsigned int isvariadic, jpayne@69: unsigned int nfixedargs, jpayne@69: unsigned int ntotalargs, jpayne@69: ffi_type *rtype, jpayne@69: ffi_type **atypes); jpayne@69: jpayne@69: /* ---- Definitions for the raw API -------------------------------------- */ jpayne@69: jpayne@69: #ifndef FFI_SIZEOF_ARG jpayne@69: # if LONG_MAX == 2147483647 jpayne@69: # define FFI_SIZEOF_ARG 4 jpayne@69: # elif LONG_MAX == FFI_64_BIT_MAX jpayne@69: # define FFI_SIZEOF_ARG 8 jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: #ifndef FFI_SIZEOF_JAVA_RAW jpayne@69: # define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG jpayne@69: #endif jpayne@69: jpayne@69: typedef union { jpayne@69: ffi_sarg sint; jpayne@69: ffi_arg uint; jpayne@69: float flt; jpayne@69: char data[FFI_SIZEOF_ARG]; jpayne@69: void* ptr; jpayne@69: } ffi_raw; jpayne@69: jpayne@69: #if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 jpayne@69: /* This is a special case for mips64/n32 ABI (and perhaps others) where jpayne@69: sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ jpayne@69: typedef union { jpayne@69: signed int sint; jpayne@69: unsigned int uint; jpayne@69: float flt; jpayne@69: char data[FFI_SIZEOF_JAVA_RAW]; jpayne@69: void* ptr; jpayne@69: } ffi_java_raw; jpayne@69: #else jpayne@69: typedef ffi_raw ffi_java_raw; jpayne@69: #endif jpayne@69: jpayne@69: jpayne@69: void ffi_raw_call (ffi_cif *cif, jpayne@69: void (*fn)(void), jpayne@69: void *rvalue, jpayne@69: ffi_raw *avalue); jpayne@69: jpayne@69: void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); jpayne@69: void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); jpayne@69: size_t ffi_raw_size (ffi_cif *cif); jpayne@69: jpayne@69: /* This is analogous to the raw API, except it uses Java parameter */ jpayne@69: /* packing, even on 64-bit machines. I.e. on 64-bit machines */ jpayne@69: /* longs and doubles are followed by an empty 64-bit word. */ jpayne@69: jpayne@69: void ffi_java_raw_call (ffi_cif *cif, jpayne@69: void (*fn)(void), jpayne@69: void *rvalue, jpayne@69: ffi_java_raw *avalue); jpayne@69: jpayne@69: void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); jpayne@69: void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); jpayne@69: size_t ffi_java_raw_size (ffi_cif *cif); jpayne@69: jpayne@69: /* ---- Definitions for closures ----------------------------------------- */ jpayne@69: jpayne@69: #if FFI_CLOSURES jpayne@69: jpayne@69: #ifdef _MSC_VER jpayne@69: __declspec(align(8)) jpayne@69: #endif jpayne@69: typedef struct { jpayne@69: #if 0 jpayne@69: void *trampoline_table; jpayne@69: void *trampoline_table_entry; jpayne@69: #else jpayne@69: char tramp[FFI_TRAMPOLINE_SIZE]; jpayne@69: #endif jpayne@69: ffi_cif *cif; jpayne@69: void (*fun)(ffi_cif*,void*,void**,void*); jpayne@69: void *user_data; jpayne@69: #ifdef __GNUC__ jpayne@69: } ffi_closure __attribute__((aligned (8))); jpayne@69: #else jpayne@69: } ffi_closure; jpayne@69: # ifdef __sgi jpayne@69: # pragma pack 0 jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: void *ffi_closure_alloc (size_t size, void **code); jpayne@69: void ffi_closure_free (void *); jpayne@69: jpayne@69: ffi_status jpayne@69: ffi_prep_closure (ffi_closure*, jpayne@69: ffi_cif *, jpayne@69: void (*fun)(ffi_cif*,void*,void**,void*), jpayne@69: void *user_data); jpayne@69: jpayne@69: ffi_status jpayne@69: ffi_prep_closure_loc (ffi_closure*, jpayne@69: ffi_cif *, jpayne@69: void (*fun)(ffi_cif*,void*,void**,void*), jpayne@69: void *user_data, jpayne@69: void*codeloc); jpayne@69: jpayne@69: #ifdef __sgi jpayne@69: # pragma pack 8 jpayne@69: #endif jpayne@69: typedef struct { jpayne@69: #if 0 jpayne@69: void *trampoline_table; jpayne@69: void *trampoline_table_entry; jpayne@69: #else jpayne@69: char tramp[FFI_TRAMPOLINE_SIZE]; jpayne@69: #endif jpayne@69: ffi_cif *cif; jpayne@69: jpayne@69: #if !FFI_NATIVE_RAW_API jpayne@69: jpayne@69: /* if this is enabled, then a raw closure has the same layout jpayne@69: as a regular closure. We use this to install an intermediate jpayne@69: handler to do the transaltion, void** -> ffi_raw*. */ jpayne@69: jpayne@69: void (*translate_args)(ffi_cif*,void*,void**,void*); jpayne@69: void *this_closure; jpayne@69: jpayne@69: #endif jpayne@69: jpayne@69: void (*fun)(ffi_cif*,void*,ffi_raw*,void*); jpayne@69: void *user_data; jpayne@69: jpayne@69: } ffi_raw_closure; jpayne@69: jpayne@69: typedef struct { jpayne@69: #if 0 jpayne@69: void *trampoline_table; jpayne@69: void *trampoline_table_entry; jpayne@69: #else jpayne@69: char tramp[FFI_TRAMPOLINE_SIZE]; jpayne@69: #endif jpayne@69: jpayne@69: ffi_cif *cif; jpayne@69: jpayne@69: #if !FFI_NATIVE_RAW_API jpayne@69: jpayne@69: /* if this is enabled, then a raw closure has the same layout jpayne@69: as a regular closure. We use this to install an intermediate jpayne@69: handler to do the transaltion, void** -> ffi_raw*. */ jpayne@69: jpayne@69: void (*translate_args)(ffi_cif*,void*,void**,void*); jpayne@69: void *this_closure; jpayne@69: jpayne@69: #endif jpayne@69: jpayne@69: void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*); jpayne@69: void *user_data; jpayne@69: jpayne@69: } ffi_java_raw_closure; jpayne@69: jpayne@69: ffi_status jpayne@69: ffi_prep_raw_closure (ffi_raw_closure*, jpayne@69: ffi_cif *cif, jpayne@69: void (*fun)(ffi_cif*,void*,ffi_raw*,void*), jpayne@69: void *user_data); jpayne@69: jpayne@69: ffi_status jpayne@69: ffi_prep_raw_closure_loc (ffi_raw_closure*, jpayne@69: ffi_cif *cif, jpayne@69: void (*fun)(ffi_cif*,void*,ffi_raw*,void*), jpayne@69: void *user_data, jpayne@69: void *codeloc); jpayne@69: jpayne@69: ffi_status jpayne@69: ffi_prep_java_raw_closure (ffi_java_raw_closure*, jpayne@69: ffi_cif *cif, jpayne@69: void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), jpayne@69: void *user_data); jpayne@69: jpayne@69: ffi_status jpayne@69: ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, jpayne@69: ffi_cif *cif, jpayne@69: void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), jpayne@69: void *user_data, jpayne@69: void *codeloc); jpayne@69: jpayne@69: #endif /* FFI_CLOSURES */ jpayne@69: jpayne@69: /* ---- Public interface definition -------------------------------------- */ jpayne@69: jpayne@69: ffi_status ffi_prep_cif(ffi_cif *cif, jpayne@69: ffi_abi abi, jpayne@69: unsigned int nargs, jpayne@69: ffi_type *rtype, jpayne@69: ffi_type **atypes); jpayne@69: jpayne@69: ffi_status ffi_prep_cif_var(ffi_cif *cif, jpayne@69: ffi_abi abi, jpayne@69: unsigned int nfixedargs, jpayne@69: unsigned int ntotalargs, jpayne@69: ffi_type *rtype, jpayne@69: ffi_type **atypes); jpayne@69: jpayne@69: void ffi_call(ffi_cif *cif, jpayne@69: void (*fn)(void), jpayne@69: void *rvalue, jpayne@69: void **avalue); jpayne@69: jpayne@69: /* Useful for eliminating compiler warnings */ jpayne@69: #define FFI_FN(f) ((void (*)(void))f) jpayne@69: jpayne@69: /* ---- Definitions shared with assembly code ---------------------------- */ jpayne@69: jpayne@69: #endif jpayne@69: jpayne@69: /* If these change, update src/mips/ffitarget.h. */ jpayne@69: #define FFI_TYPE_VOID 0 jpayne@69: #define FFI_TYPE_INT 1 jpayne@69: #define FFI_TYPE_FLOAT 2 jpayne@69: #define FFI_TYPE_DOUBLE 3 jpayne@69: #if 1 jpayne@69: #define FFI_TYPE_LONGDOUBLE 4 jpayne@69: #else jpayne@69: #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE jpayne@69: #endif jpayne@69: #define FFI_TYPE_UINT8 5 jpayne@69: #define FFI_TYPE_SINT8 6 jpayne@69: #define FFI_TYPE_UINT16 7 jpayne@69: #define FFI_TYPE_SINT16 8 jpayne@69: #define FFI_TYPE_UINT32 9 jpayne@69: #define FFI_TYPE_SINT32 10 jpayne@69: #define FFI_TYPE_UINT64 11 jpayne@69: #define FFI_TYPE_SINT64 12 jpayne@69: #define FFI_TYPE_STRUCT 13 jpayne@69: #define FFI_TYPE_POINTER 14 jpayne@69: #define FFI_TYPE_COMPLEX 15 jpayne@69: jpayne@69: /* This should always refer to the last type code (for sanity checks) */ jpayne@69: #define FFI_TYPE_LAST FFI_TYPE_COMPLEX jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: } jpayne@69: #endif jpayne@69: jpayne@69: #endif