1 /* -----------------------------------------------------------------*-C-*-
2 libffi @VERSION@ - Copyright (c) 1996-2003 Cygnus Solutions
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:
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
23 ----------------------------------------------------------------------- */
25 /* -------------------------------------------------------------------
26 The basic API is described in the README file.
28 The raw API is designed to bypass some of the argument packing
29 and unpacking on architectures for which it can be avoided.
31 The closure API allows interpreted functions to be packaged up
32 inside a C function pointer, so that they can be called as C functions,
33 with no understanding on the client side that they are interpreted.
34 It can also be used in other cases in which it is necessary to package
35 up a user specified parameter and a function pointer as a single
38 The closure API must be implemented in order to get its functionality,
39 e.g. for use by gij. Routines are provided to emulate the raw API
40 if the underlying platform doesn't allow faster implementation.
42 More details on the raw and cloure API can be found in:
44 http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
48 http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
49 -------------------------------------------------------------------- */
58 /* Specify which architecture libffi is configured for. */
61 /* ---- System configuration information --------------------------------- */
63 #include <fficonfig.h>
65 #if !defined(LIBFFI_ASM)
67 #if defined(FFI_DEBUG)
72 /* ---- Generic type definitions ----------------------------------------- */
75 #define FLOAT64 double
76 #define FLOAT80 long double
78 #define UINT8 unsigned char
79 #define SINT8 signed char
83 #define UINT16 unsigned int
85 #define ffi_type_uint ffi_type_uint16
86 #define ffi_type_sint ffi_type_sint16
91 #define UINT16 unsigned short
93 #define ffi_type_ushort ffi_type_uint16
94 #define ffi_type_sshort ffi_type_sint16
101 #define UINT32 unsigned int
103 #define ffi_type_uint ffi_type_uint32
104 #define ffi_type_sint ffi_type_sint32
107 #if SIZEOF_SHORT == 4
109 #define UINT32 unsigned short
111 #define ffi_type_ushort ffi_type_uint32
112 #define ffi_type_sshort ffi_type_sint32
117 #define UINT32 unsigned long
119 #define ffi_type_ulong ffi_type_uint32
120 #define ffi_type_slong ffi_type_sint32
128 #define UINT64 unsigned int
130 #define ffi_type_uint ffi_type_uint64
131 #define ffi_type_sint ffi_type_sint64
136 #define UINT64 unsigned long
138 #define ffi_type_ulong ffi_type_uint64
139 #define ffi_type_slong ffi_type_sint64
142 #if SIZEOF_LONG_LONG == 8
144 #define UINT64 unsigned long long
145 #define SINT64 long long
146 #define ffi_type_ulong ffi_type_uint64
147 #define ffi_type_slong ffi_type_sint64
153 /* ---- System specific configurations ----------------------------------- */
156 #include <ffi_mips.h>
158 #define SIZEOF_ARG SIZEOF_VOID_P
162 #if defined (__powerpc64__)
168 #if defined(__arch64__) || defined(__sparcv9)
174 #if defined (__s390x__)
180 #if defined (__i386__)
188 #ifdef HAVE_RO_EH_FRAME
189 #define EH_FRAME_FLAGS "a"
191 #define EH_FRAME_FLAGS "aw"
196 /* ---- Generic type definitions ----------------------------------------- */
198 #define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
199 /* The closure code assumes that this works on pointers, i.e. a size_t */
200 /* can hold a pointer. */
202 typedef enum ffi_abi
{
204 /* Leave this for debugging purposes */
207 /* ---- Sparc -------------------- */
213 FFI_DEFAULT_ABI
= FFI_V9
,
215 FFI_DEFAULT_ABI
= FFI_V8
,
219 /* ---- Intel x86 Win32 ---------- */
223 /* TODO: Add fastcall support for the sake of completeness */
224 FFI_DEFAULT_ABI
= FFI_SYSV
,
227 /* ---- Intel x86 and AMD x86-64 - */
228 #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__))
230 FFI_UNIX64
, /* Unix variants all use the same ABI for x86-64 */
232 FFI_DEFAULT_ABI
= FFI_SYSV
,
234 FFI_DEFAULT_ABI
= FFI_UNIX64
,
238 /* ---- Intel ia64 ---------------- */
240 FFI_UNIX
, /* Linux and all Unix variants use the same conventions */
241 FFI_DEFAULT_ABI
= FFI_UNIX
,
244 /* ---- Mips --------------------- */
251 /* ---- Alpha -------------------- */
254 FFI_DEFAULT_ABI
= FFI_OSF
,
257 /* ---- Motorola m68k ------------ */
260 FFI_DEFAULT_ABI
= FFI_SYSV
,
263 /* ---- PowerPC ------------------ */
269 FFI_DEFAULT_ABI
= FFI_LINUX64
,
271 FFI_DEFAULT_ABI
= FFI_GCC_SYSV
,
278 FFI_DEFAULT_ABI
= FFI_AIX
,
281 #ifdef POWERPC_DARWIN
284 FFI_DEFAULT_ABI
= FFI_DARWIN
,
287 /* ---- ARM --------------------- */
290 FFI_DEFAULT_ABI
= FFI_SYSV
,
293 /* ---- S390 --------------------- */
296 FFI_DEFAULT_ABI
= FFI_SYSV
,
299 /* ---- SuperH ------------------- */
302 FFI_DEFAULT_ABI
= FFI_SYSV
,
305 /* ---- SuperH - SHmedia --------- */
308 FFI_DEFAULT_ABI
= FFI_SYSV
,
311 /* Leave this for debugging purposes */
316 typedef struct _ffi_type
319 unsigned short alignment
;
321 /*@null@*/ struct _ffi_type
**elements
;
324 /* These are defined in types.c */
325 extern ffi_type ffi_type_void
;
326 extern ffi_type ffi_type_uint8
;
327 extern ffi_type ffi_type_sint8
;
328 extern ffi_type ffi_type_uint16
;
329 extern ffi_type ffi_type_sint16
;
330 extern ffi_type ffi_type_uint32
;
331 extern ffi_type ffi_type_sint32
;
332 extern ffi_type ffi_type_uint64
;
333 extern ffi_type ffi_type_sint64
;
334 extern ffi_type ffi_type_float
;
335 extern ffi_type ffi_type_double
;
336 extern ffi_type ffi_type_longdouble
;
337 extern ffi_type ffi_type_pointer
;
339 /* Characters are 8 bit integral types */
340 #define ffi_type_schar ffi_type_sint8
341 #define ffi_type_uchar ffi_type_uint8
349 typedef unsigned FFI_TYPE
;
354 /*@dependent@*/ ffi_type
**arg_types
;
355 /*@dependent@*/ ffi_type
*rtype
;
360 #if _MIPS_SIM == _ABIN32
361 unsigned rstruct_flag
;
372 typedef UINT32 ffi_arg
;
375 typedef UINT64 ffi_arg
;
377 -- unsupported configuration
381 /* ---- Definitions for the raw API -------------------------------------- */
387 #define UINT_ARG UINT32
388 #define SINT_ARG SINT32
394 #define UINT_ARG UINT64
395 #define SINT_ARG SINT64
403 char data
[SIZEOF_ARG
];
407 void ffi_raw_call (/*@dependent@*/ ffi_cif
*cif
,
409 /*@out@*/ void *rvalue
,
410 /*@dependent@*/ ffi_raw
*avalue
);
412 void ffi_ptrarray_to_raw (ffi_cif
*cif
, void **args
, ffi_raw
*raw
);
413 void ffi_raw_to_ptrarray (ffi_cif
*cif
, ffi_raw
*raw
, void **args
);
414 size_t ffi_raw_size (ffi_cif
*cif
);
418 /* This is analogous to the raw API, except it uses Java parameter */
419 /* packing, even on 64-bit machines. I.e. on 64-bit machines */
420 /* longs and doubles are followed by an empty 64-bit word. */
422 void ffi_java_raw_call (/*@dependent@*/ ffi_cif
*cif
,
424 /*@out@*/ void *rvalue
,
425 /*@dependent@*/ ffi_raw
*avalue
);
427 void ffi_java_ptrarray_to_raw (ffi_cif
*cif
, void **args
, ffi_raw
*raw
);
428 void ffi_java_raw_to_ptrarray (ffi_cif
*cif
, ffi_raw
*raw
, void **args
);
429 size_t ffi_java_raw_size (ffi_cif
*cif
);
431 #endif /* !NO_JAVA_RAW_API */
433 #endif /* !FFI_NO_RAW_API */
435 /* ---- Definitions for closures ----------------------------------------- */
439 #define FFI_CLOSURES 1 /* x86 supports closures */
440 #define FFI_TRAMPOLINE_SIZE 10
441 #define FFI_NATIVE_RAW_API 1 /* and has native raw api support */
445 #define FFI_CLOSURES 1
446 #define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */
447 /* can be interpreted as a C function */
450 struct ffi_ia64_trampoline_struct
{
451 void * code_pointer
; /* Pointer to ffi_closure_UNIX */
452 void * fake_gp
; /* Pointer to closure, installed as gp */
453 void * real_gp
; /* Real gp value, reinstalled by */
454 /* ffi_closure_UNIX. */
456 #define FFI_NATIVE_RAW_API 0
460 #define FFI_CLOSURES 1
461 #define FFI_TRAMPOLINE_SIZE 24
462 #define FFI_NATIVE_RAW_API 0
464 #elif defined(POWERPC)
466 #define FFI_CLOSURES 1
468 #define FFI_TRAMPOLINE_SIZE 24
470 #define FFI_TRAMPOLINE_SIZE 40
472 #define FFI_NATIVE_RAW_API 0
474 #elif defined(POWERPC_DARWIN)
476 #define FFI_CLOSURES 1
477 #define FFI_TRAMPOLINE_SIZE 40
478 #define FFI_NATIVE_RAW_API 0
480 #elif defined(POWERPC_AIX)
482 #define FFI_CLOSURES 1
483 #define FFI_TRAMPOLINE_SIZE 24 /* see struct below */
484 #define FFI_NATIVE_RAW_API 0
486 #elif defined(SPARC64)
488 #define FFI_CLOSURES 1
489 #define FFI_TRAMPOLINE_SIZE 24
490 #define FFI_NATIVE_RAW_API 0
494 #define FFI_CLOSURES 1
495 #define FFI_TRAMPOLINE_SIZE 16
496 #define FFI_NATIVE_RAW_API 0
500 #define FFI_CLOSURES 1
502 #define FFI_TRAMPOLINE_SIZE 32
504 #define FFI_TRAMPOLINE_SIZE 16
506 #define FFI_NATIVE_RAW_API 0
510 #define FFI_CLOSURES 1
511 #define FFI_TRAMPOLINE_SIZE 16
512 #define FFI_NATIVE_RAW_API 0
516 #define FFI_CLOSURES 1
517 #define FFI_TRAMPOLINE_SIZE 32
518 #define FFI_NATIVE_RAW_API 0
520 #elif defined(__x86_64__)
522 #define FFI_CLOSURES 1
523 #define FFI_TRAMPOLINE_SIZE 24
524 #define FFI_NATIVE_RAW_API 0
528 #define FFI_CLOSURES 0
529 #define FFI_NATIVE_RAW_API 0
533 #if defined(POWERPC_DARWIN) || defined(POWERPC_AIX)
535 struct ffi_aix_trampoline_struct
{
536 void * code_pointer
; /* Pointer to ffi_closure_ASM */
537 void * toc
; /* TOC */
538 void * static_chain
; /* Pointer to closure */
548 char tramp
[FFI_TRAMPOLINE_SIZE
];
550 void (*fun
)(ffi_cif
*,void*,void**,void*);
555 ffi_prep_closure (ffi_closure
*,
557 void (*fun
)(ffi_cif
*,void*,void**,void*),
563 char tramp
[FFI_TRAMPOLINE_SIZE
];
567 #if !FFI_NATIVE_RAW_API
569 /* if this is enabled, then a raw closure has the same layout
570 as a regular closure. We use this to install an intermediate
571 handler to do the transaltion, void** -> ffi_raw*. */
573 void (*translate_args
)(ffi_cif
*,void*,void**,void*);
578 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*);
584 ffi_prep_raw_closure (ffi_raw_closure
*,
586 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*),
589 #ifndef NO_JAVA_RAW_API
591 ffi_prep_java_raw_closure (ffi_raw_closure
*,
593 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*),
597 #endif /* !FFI_NO_RAW_API */
598 #endif /* FFI_CLOSURES */
600 /* ---- Public interface definition -------------------------------------- */
602 ffi_status
ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif
*cif
,
605 /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type
*rtype
,
606 /*@dependent@*/ ffi_type
**atypes
);
608 void ffi_call(/*@dependent@*/ ffi_cif
*cif
,
610 /*@out@*/ void *rvalue
,
611 /*@dependent@*/ void **avalue
);
613 /* Useful for eliminating compiler warnings */
614 #define FFI_FN(f) ((void (*)())f)
616 /* ---- Definitions shared with assembly code ---------------------------- */
620 #define FFI_TYPE_VOID 0
621 #define FFI_TYPE_INT 1
622 #define FFI_TYPE_FLOAT 2
623 #define FFI_TYPE_DOUBLE 3
624 #if SIZEOF_LONG_DOUBLE == SIZEOF_DOUBLE
625 #define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
627 #define FFI_TYPE_LONGDOUBLE 4
630 #define FFI_TYPE_UINT8 5 /* If this changes, update ffi_mips.h. */
631 #define FFI_TYPE_SINT8 6 /* If this changes, update ffi_mips.h. */
632 #define FFI_TYPE_UINT16 7
633 #define FFI_TYPE_SINT16 8
634 #define FFI_TYPE_UINT32 9
635 #define FFI_TYPE_SINT32 10
636 #define FFI_TYPE_UINT64 11
637 #define FFI_TYPE_SINT64 12
638 #define FFI_TYPE_STRUCT 13 /* If this changes, update ffi_mips.h. */
639 #define FFI_TYPE_POINTER 14
641 /* This should always refer to the last type code (for sanity checks) */
642 #define FFI_TYPE_LAST FFI_TYPE_POINTER