1/* -----------------------------------------------------------------*-C-*- 2 libffi @VERSION@ - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. 3 4 Permission is hereby granted, free of charge, to any person obtaining 5 a copy of this software and associated documentation files (the 6 ``Software''), to deal in the Software without restriction, including 7 without limitation the rights to use, copy, modify, merge, publish, 8 distribute, sublicense, and/or sell copies of the Software, and to 9 permit persons to whom the Software is furnished to do so, subject to 10 the following conditions: 11 12 The above copyright notice and this permission notice shall be included 13 in all copies or substantial portions of the Software. 14 15 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 DEALINGS IN THE SOFTWARE. 23 24 ----------------------------------------------------------------------- */ 25 26/* ------------------------------------------------------------------- 27 The basic API is described in the README file. 28 29 The raw API is designed to bypass some of the argument packing 30 and unpacking on architectures for which it can be avoided. 31 32 The closure API allows interpreted functions to be packaged up 33 inside a C function pointer, so that they can be called as C functions, 34 with no understanding on the client side that they are interpreted. 35 It can also be used in other cases in which it is necessary to package 36 up a user specified parameter and a function pointer as a single 37 function pointer. 38 39 The closure API must be implemented in order to get its functionality, 40 e.g. for use by gij. Routines are provided to emulate the raw API 41 if the underlying platform doesn't allow faster implementation. 42 43 More details on the raw and cloure API can be found in: 44 45 http://gcc.gnu.org/ml/java/1999-q3/msg00138.html 46 47 and 48 49 http://gcc.gnu.org/ml/java/1999-q3/msg00174.html 50 -------------------------------------------------------------------- */ 51 52#ifndef LIBFFI_H 53#define LIBFFI_H 54 55#ifdef __cplusplus 56extern "C" { 57#endif 58 59/* Specify which architecture libffi is configured for. */ 60#ifndef @TARGET@ 61#define @TARGET@ 62#endif 63 64/* ---- System configuration information --------------------------------- */ 65 66#include <ffitarget.h> 67 68#ifndef LIBFFI_ASM 69 70#include <stddef.h> 71#include <limits.h> 72 73/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). 74 But we can find it either under the correct ANSI name, or under GNU 75 C's internal name. */ 76#ifdef LONG_LONG_MAX 77# define FFI_LONG_LONG_MAX LONG_LONG_MAX 78#else 79# ifdef LLONG_MAX 80# define FFI_LONG_LONG_MAX LLONG_MAX 81# else 82# ifdef __GNUC__ 83# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ 84# endif 85# endif 86#endif 87 88/* The closure code assumes that this works on pointers, i.e. a size_t */ 89/* can hold a pointer. */ 90 91typedef struct _ffi_type 92{ 93 size_t size; 94 unsigned short alignment; 95 unsigned short type; 96 struct _ffi_type **elements; 97} ffi_type; 98 99#ifndef LIBFFI_HIDE_BASIC_TYPES 100#if SCHAR_MAX == 127 101# define ffi_type_uchar ffi_type_uint8 102# define ffi_type_schar ffi_type_sint8 103#else 104 #error "char size not supported" 105#endif 106 107#if SHRT_MAX == 32767 108# define ffi_type_ushort ffi_type_uint16 109# define ffi_type_sshort ffi_type_sint16 110#elif SHRT_MAX == 2147483647 111# define ffi_type_ushort ffi_type_uint32 112# define ffi_type_sshort ffi_type_sint32 113#else 114 #error "short size not supported" 115#endif 116 117#if INT_MAX == 32767 118# define ffi_type_uint ffi_type_uint16 119# define ffi_type_sint ffi_type_sint16 120#elif INT_MAX == 2147483647 121# define ffi_type_uint ffi_type_uint32 122# define ffi_type_sint ffi_type_sint32 123#elif INT_MAX == 9223372036854775807 124# define ffi_type_uint ffi_type_uint64 125# define ffi_type_sint ffi_type_sint64 126#else 127 #error "int size not supported" 128#endif 129 130#if LONG_MAX == 2147483647 131# if FFI_LONG_LONG_MAX != 9223372036854775807 132 #error "no 64-bit data type supported" 133# endif 134#elif LONG_MAX != 9223372036854775807 135 #error "long size not supported" 136#endif 137 138#if LONG_MAX == 2147483647 139# define ffi_type_ulong ffi_type_uint32 140# define ffi_type_slong ffi_type_sint32 141#elif LONG_MAX == 9223372036854775807 142# define ffi_type_ulong ffi_type_uint64 143# define ffi_type_slong ffi_type_sint64 144#else 145 #error "long size not supported" 146#endif 147 148/* These are defined in types.c */ 149extern ffi_type ffi_type_void; 150extern ffi_type ffi_type_uint8; 151extern ffi_type ffi_type_sint8; 152extern ffi_type ffi_type_uint16; 153extern ffi_type ffi_type_sint16; 154extern ffi_type ffi_type_uint32; 155extern ffi_type ffi_type_sint32; 156extern ffi_type ffi_type_uint64; 157extern ffi_type ffi_type_sint64; 158extern ffi_type ffi_type_float; 159extern ffi_type ffi_type_double; 160extern ffi_type ffi_type_pointer; 161 162#if @HAVE_LONG_DOUBLE@ 163extern ffi_type ffi_type_longdouble; 164#else 165#define ffi_type_longdouble ffi_type_double 166#endif 167#endif /* LIBFFI_HIDE_BASIC_TYPES */ 168 169typedef enum { 170 FFI_OK = 0, 171 FFI_BAD_TYPEDEF, 172 FFI_BAD_ABI 173} ffi_status; 174 175typedef unsigned FFI_TYPE; 176 177typedef struct { 178 ffi_abi abi; 179 unsigned nargs; 180 ffi_type **arg_types; 181 ffi_type *rtype; 182 unsigned bytes; 183 unsigned flags; 184#ifdef FFI_EXTRA_CIF_FIELDS 185 FFI_EXTRA_CIF_FIELDS; 186#endif 187} ffi_cif; 188 189/* ---- Definitions for the raw API -------------------------------------- */ 190 191#ifndef FFI_SIZEOF_ARG 192# if LONG_MAX == 2147483647 193# define FFI_SIZEOF_ARG 4 194# elif LONG_MAX == 9223372036854775807 195# define FFI_SIZEOF_ARG 8 196# endif 197#endif 198 199#ifndef FFI_SIZEOF_JAVA_RAW 200# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG 201#endif 202 203typedef union { 204 ffi_sarg sint; 205 ffi_arg uint; 206 float flt; 207 char data[FFI_SIZEOF_ARG]; 208 void* ptr; 209} ffi_raw; 210 211#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 212/* This is a special case for mips64/n32 ABI (and perhaps others) where 213 sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ 214typedef union { 215 signed int sint; 216 unsigned int uint; 217 float flt; 218 char data[FFI_SIZEOF_JAVA_RAW]; 219 void* ptr; 220} ffi_java_raw; 221#else 222typedef ffi_raw ffi_java_raw; 223#endif 224 225 226void ffi_raw_call (ffi_cif *cif, 227 void (*fn)(void), 228 void *rvalue, 229 ffi_raw *avalue); 230 231void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); 232void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); 233size_t ffi_raw_size (ffi_cif *cif); 234 235/* This is analogous to the raw API, except it uses Java parameter */ 236/* packing, even on 64-bit machines. I.e. on 64-bit machines */ 237/* longs and doubles are followed by an empty 64-bit word. */ 238 239void ffi_java_raw_call (ffi_cif *cif, 240 void (*fn)(void), 241 void *rvalue, 242 ffi_java_raw *avalue); 243 244void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); 245void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); 246size_t ffi_java_raw_size (ffi_cif *cif); 247 248/* ---- Definitions for closures ----------------------------------------- */ 249 250#if FFI_CLOSURES 251 252typedef struct { 253 char tramp[FFI_TRAMPOLINE_SIZE]; 254 ffi_cif *cif; 255 void (*fun)(ffi_cif*,void*,void**,void*); 256 void *user_data; 257} ffi_closure __attribute__((aligned (8))); 258 259void *ffi_closure_alloc (size_t size, void **code); 260void ffi_closure_free (void *); 261 262ffi_status 263ffi_prep_closure (ffi_closure*, 264 ffi_cif *, 265 void (*fun)(ffi_cif*,void*,void**,void*), 266 void *user_data); 267 268ffi_status 269ffi_prep_closure_loc (ffi_closure*, 270 ffi_cif *, 271 void (*fun)(ffi_cif*,void*,void**,void*), 272 void *user_data, 273 void*codeloc); 274 275typedef struct { 276 char tramp[FFI_TRAMPOLINE_SIZE]; 277 278 ffi_cif *cif; 279 280#if !FFI_NATIVE_RAW_API 281 282 /* if this is enabled, then a raw closure has the same layout 283 as a regular closure. We use this to install an intermediate 284 handler to do the transaltion, void** -> ffi_raw*. */ 285 286 void (*translate_args)(ffi_cif*,void*,void**,void*); 287 void *this_closure; 288 289#endif 290 291 void (*fun)(ffi_cif*,void*,ffi_raw*,void*); 292 void *user_data; 293 294} ffi_raw_closure; 295 296typedef struct { 297 char tramp[FFI_TRAMPOLINE_SIZE]; 298 299 ffi_cif *cif; 300 301#if !FFI_NATIVE_RAW_API 302 303 /* if this is enabled, then a raw closure has the same layout 304 as a regular closure. We use this to install an intermediate 305 handler to do the transaltion, void** -> ffi_raw*. */ 306 307 void (*translate_args)(ffi_cif*,void*,void**,void*); 308 void *this_closure; 309 310#endif 311 312 void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*); 313 void *user_data; 314 315} ffi_java_raw_closure; 316 317ffi_status 318ffi_prep_raw_closure (ffi_raw_closure*, 319 ffi_cif *cif, 320 void (*fun)(ffi_cif*,void*,ffi_raw*,void*), 321 void *user_data); 322 323ffi_status 324ffi_prep_raw_closure_loc (ffi_raw_closure*, 325 ffi_cif *cif, 326 void (*fun)(ffi_cif*,void*,ffi_raw*,void*), 327 void *user_data, 328 void *codeloc); 329 330ffi_status 331ffi_prep_java_raw_closure (ffi_java_raw_closure*, 332 ffi_cif *cif, 333 void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), 334 void *user_data); 335 336ffi_status 337ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, 338 ffi_cif *cif, 339 void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), 340 void *user_data, 341 void *codeloc); 342 343#endif /* FFI_CLOSURES */ 344 345/* ---- Public interface definition -------------------------------------- */ 346 347ffi_status ffi_prep_cif(ffi_cif *cif, 348 ffi_abi abi, 349 unsigned int nargs, 350 ffi_type *rtype, 351 ffi_type **atypes); 352 353void ffi_call(ffi_cif *cif, 354 void (*fn)(void), 355 void *rvalue, 356 void **avalue); 357 358/* Useful for eliminating compiler warnings */ 359#define FFI_FN(f) ((void (*)(void))f) 360 361/* ---- Definitions shared with assembly code ---------------------------- */ 362 363#endif 364 365/* If these change, update src/mips/ffitarget.h. */ 366#define FFI_TYPE_VOID 0 367#define FFI_TYPE_INT 1 368#define FFI_TYPE_FLOAT 2 369#define FFI_TYPE_DOUBLE 3 370#if @HAVE_LONG_DOUBLE@ 371#define FFI_TYPE_LONGDOUBLE 4 372#else 373#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE 374#endif 375#define FFI_TYPE_UINT8 5 376#define FFI_TYPE_SINT8 6 377#define FFI_TYPE_UINT16 7 378#define FFI_TYPE_SINT16 8 379#define FFI_TYPE_UINT32 9 380#define FFI_TYPE_SINT32 10 381#define FFI_TYPE_UINT64 11 382#define FFI_TYPE_SINT64 12 383#define FFI_TYPE_STRUCT 13 384#define FFI_TYPE_POINTER 14 385 386/* This should always refer to the last type code (for sanity checks) */ 387#define FFI_TYPE_LAST FFI_TYPE_POINTER 388 389#ifdef __cplusplus 390} 391#endif 392 393#endif 394