added libffi for win support

This commit is contained in:
Araq 2013-12-19 01:00:51 +01:00
commit e2a4d591e5
22 changed files with 7192 additions and 10 deletions

View file

@ -0,0 +1,331 @@
/* -----------------------------------------------------------------*-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 <ffitarget.h>
#ifndef LIBFFI_ASM
#include <stddef.h>
#include <limits.h>
/* 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

View file

@ -0,0 +1,77 @@
/* -----------------------------------------------------------------------
ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
Common internal definitions and macros. Only necessary for building
libffi.
----------------------------------------------------------------------- */
#ifndef FFI_COMMON_H
#define FFI_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <fficonfig.h>
#include <malloc.h>
/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
#if defined(FFI_DEBUG)
#include <stdio.h>
#endif
#ifdef FFI_DEBUG
/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
void ffi_stop_here(void);
void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
#endif
#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
/* Extended cif, used in callback from assembly routine */
typedef struct
{
/*@dependent@*/ ffi_cif *cif;
/*@dependent@*/ void *rvalue;
/*@dependent@*/ void **avalue;
} extended_cif;
/* Terse sized type definitions. */
typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
typedef signed int SINT8 __attribute__((__mode__(__QI__)));
typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
typedef signed int SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
typedef signed int SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
typedef signed int SINT64 __attribute__((__mode__(__DI__)));
typedef float FLOAT32;
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,96 @@
/* 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 <alloca.h> 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 */

View file

@ -0,0 +1,150 @@
/* -----------------------------------------------------------------*-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

View file

@ -0,0 +1,110 @@
#include <ffi.h>
#ifdef MS_WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
# 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;
}

View file

@ -0,0 +1,254 @@
/* -----------------------------------------------------------------------
raw_api.c - Copyright (c) 1999, 2008 Red Hat, Inc.
Author: Kresten Krab Thorup <krab@gnu.org>
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 <ffi.h>
#include <ffi_common.h>
#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 */