1/* -----------------------------------------------------------------*-C-*-
2   libffi PyOBJC - Copyright (c) 1996-2003  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, 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.
22
23   ----------------------------------------------------------------------- */
24
25/* -------------------------------------------------------------------
26   The basic API is described in the README file.
27
28   The raw API is designed to bypass some of the argument packing
29   and unpacking on architectures for which it can be avoided.
30
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
36   function pointer.
37
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.
41
42   More details on the raw and closure API can be found in:
43
44   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
45
46   and
47
48   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
49   -------------------------------------------------------------------- */
50
51#ifndef LIBFFI_H
52#define LIBFFI_H
53
54#ifdef __cplusplus
55extern "C" {
56#endif
57
58/*	Specify which architecture libffi is configured for. */
59#ifdef MACOSX
60#	if defined(__i386__) || defined(__x86_64__)
61#		define X86_DARWIN
62#	elif defined(__ppc__) || defined(__ppc64__)
63#		define POWERPC_DARWIN
64#	else
65#	error "Unsupported MacOS X CPU type"
66#	endif
67#else
68#error "Unsupported OS type"
69#endif
70
71/* ---- System configuration information --------------------------------- */
72
73#include "ffitarget.h"
74#include "fficonfig.h"
75
76#ifndef LIBFFI_ASM
77
78#include <stddef.h>
79#include <limits.h>
80
81/*	LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
82	But we can find it either under the correct ANSI name, or under GNU
83	C's internal name.  */
84#ifdef LONG_LONG_MAX
85#	define FFI_LONG_LONG_MAX LONG_LONG_MAX
86#else
87#	ifdef LLONG_MAX
88#		define FFI_LONG_LONG_MAX LLONG_MAX
89#	else
90#		ifdef __GNUC__
91#			define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
92#		endif
93#	endif
94#endif
95
96#if SCHAR_MAX == 127
97#	define ffi_type_uchar	ffi_type_uint8
98#	define ffi_type_schar	ffi_type_sint8
99#else
100#error "char size not supported"
101#endif
102
103#if SHRT_MAX == 32767
104#	define ffi_type_ushort	ffi_type_uint16
105#	define ffi_type_sshort	ffi_type_sint16
106#elif SHRT_MAX == 2147483647
107#	define ffi_type_ushort	ffi_type_uint32
108#	define ffi_type_sshort	ffi_type_sint32
109#else
110#error "short size not supported"
111#endif
112
113#if INT_MAX == 32767
114#	define ffi_type_uint	ffi_type_uint16
115#	define ffi_type_sint	ffi_type_sint16
116#elif INT_MAX == 2147483647
117#	define ffi_type_uint	ffi_type_uint32
118#	define ffi_type_sint	ffi_type_sint32
119#elif INT_MAX == 9223372036854775807
120#	define ffi_type_uint	ffi_type_uint64
121#	define ffi_type_sint	ffi_type_sint64
122#else
123#error "int size not supported"
124#endif
125
126#define ffi_type_ulong	ffi_type_uint64
127#define ffi_type_slong	ffi_type_sint64
128
129#if LONG_MAX == 2147483647
130#	if FFI_LONG_LONG_MAX != 9223372036854775807
131#		error "no 64-bit data type supported"
132#	endif
133#elif LONG_MAX != 9223372036854775807
134#error "long size not supported"
135#endif
136
137/*	The closure code assumes that this works on pointers, i.e. a size_t
138	can hold a pointer.	*/
139
140typedef struct _ffi_type {
141			size_t				size;
142			unsigned short		alignment;
143			unsigned short		type;
144/*@null@*/	struct _ffi_type**	elements;
145} ffi_type;
146
147/*	These are defined in types.c */
148extern ffi_type	ffi_type_void;
149extern ffi_type	ffi_type_uint8;
150extern ffi_type	ffi_type_sint8;
151extern ffi_type	ffi_type_uint16;
152extern ffi_type	ffi_type_sint16;
153extern ffi_type	ffi_type_uint32;
154extern ffi_type	ffi_type_sint32;
155extern ffi_type	ffi_type_uint64;
156extern ffi_type	ffi_type_sint64;
157extern ffi_type	ffi_type_float;
158extern ffi_type	ffi_type_double;
159extern ffi_type	ffi_type_longdouble;
160extern ffi_type	ffi_type_pointer;
161
162typedef enum ffi_status {
163	FFI_OK = 0,
164	FFI_BAD_TYPEDEF,
165	FFI_BAD_ABI
166} ffi_status;
167
168typedef unsigned	FFI_TYPE;
169
170typedef struct	ffi_cif {
171				ffi_abi		abi;
172				unsigned	nargs;
173/*@dependent@*/	ffi_type**	arg_types;
174/*@dependent@*/	ffi_type*	rtype;
175				unsigned	bytes;
176				unsigned	flags;
177#ifdef FFI_EXTRA_CIF_FIELDS
178				FFI_EXTRA_CIF_FIELDS;
179#endif
180} ffi_cif;
181
182/* ---- Definitions for the raw API -------------------------------------- */
183
184#ifndef FFI_SIZEOF_ARG
185#	if LONG_MAX == 2147483647
186#		define FFI_SIZEOF_ARG	4
187#	elif LONG_MAX == 9223372036854775807
188#		define FFI_SIZEOF_ARG	8
189#	endif
190#endif
191
192typedef union {
193	ffi_sarg	sint;
194	ffi_arg		uint;
195	float		flt;
196	char		data[FFI_SIZEOF_ARG];
197	void*		ptr;
198} ffi_raw;
199
200void
201ffi_raw_call(
202/*@dependent@*/	ffi_cif*	cif,
203				void		(*fn)(void),
204/*@out@*/		void*		rvalue,
205/*@dependent@*/	ffi_raw*	avalue);
206
207void
208ffi_ptrarray_to_raw(
209	ffi_cif*	cif,
210	void**		args,
211	ffi_raw*	raw);
212
213void
214ffi_raw_to_ptrarray(
215	ffi_cif*	cif,
216	ffi_raw*	raw,
217	void**		args);
218
219size_t
220ffi_raw_size(
221	ffi_cif*	cif);
222
223/*	This is analogous to the raw API, except it uses Java parameter
224	packing, even on 64-bit machines.  I.e. on 64-bit machines
225	longs and doubles are followed by an empty 64-bit word.	*/
226void
227ffi_java_raw_call(
228/*@dependent@*/	ffi_cif*	cif,
229				void		(*fn)(void),
230/*@out@*/		void*		rvalue,
231/*@dependent@*/	ffi_raw*	avalue);
232
233void
234ffi_java_ptrarray_to_raw(
235	ffi_cif*	cif,
236	void**		args,
237	ffi_raw*	raw);
238
239void
240ffi_java_raw_to_ptrarray(
241	ffi_cif*	cif,
242	ffi_raw*	raw,
243	void**		args);
244
245size_t
246ffi_java_raw_size(
247	ffi_cif*	cif);
248
249/* ---- Definitions for closures ----------------------------------------- */
250
251#if FFI_CLOSURES
252
253typedef struct ffi_closure {
254	char		tramp[FFI_TRAMPOLINE_SIZE];
255	ffi_cif*	cif;
256	void		(*fun)(ffi_cif*,void*,void**,void*);
257	void*		user_data;
258} ffi_closure;
259
260ffi_status
261ffi_prep_closure(
262	ffi_closure*	closure,
263	ffi_cif*		cif,
264	void			(*fun)(ffi_cif*,void*,void**,void*),
265	void*			user_data);
266
267typedef struct ffi_raw_closure {
268	char		tramp[FFI_TRAMPOLINE_SIZE];
269	ffi_cif*	cif;
270
271#if !FFI_NATIVE_RAW_API
272	/*	if this is enabled, then a raw closure has the same layout
273		as a regular closure.  We use this to install an intermediate
274		handler to do the transaltion, void** -> ffi_raw*. */
275	void	(*translate_args)(ffi_cif*,void*,void**,void*);
276	void*	this_closure;
277#endif
278
279	void	(*fun)(ffi_cif*,void*,ffi_raw*,void*);
280	void*	user_data;
281} ffi_raw_closure;
282
283ffi_status
284ffi_prep_raw_closure(
285	ffi_raw_closure*	closure,
286	ffi_cif*			cif,
287	void				(*fun)(ffi_cif*,void*,ffi_raw*,void*),
288	void*				user_data);
289
290ffi_status
291ffi_prep_java_raw_closure(
292	ffi_raw_closure*	closure,
293	ffi_cif*			cif,
294	void				(*fun)(ffi_cif*,void*,ffi_raw*,void*),
295	void*				user_data);
296
297#endif	// FFI_CLOSURES
298
299/* ---- Public interface definition -------------------------------------- */
300
301ffi_status
302ffi_prep_cif(
303/*@out@*/ /*@partial@*/					ffi_cif*		cif,
304										ffi_abi			abi,
305										unsigned int	nargs,
306/*@dependent@*/ /*@out@*/ /*@partial@*/	ffi_type*		rtype,
307/*@dependent@*/							ffi_type**		atypes);
308
309void
310ffi_call(
311/*@dependent@*/	ffi_cif*	cif,
312				void		(*fn)(void),
313/*@out@*/		void*		rvalue,
314/*@dependent@*/	void**		avalue);
315
316/* Useful for eliminating compiler warnings */
317#define FFI_FN(f) ((void (*)(void))f)
318
319#endif	// #ifndef LIBFFI_ASM
320/* ---- Definitions shared with assembly code ---------------------------- */
321
322/*	If these change, update src/mips/ffitarget.h. */
323#define FFI_TYPE_VOID       0
324#define FFI_TYPE_INT        1
325#define FFI_TYPE_FLOAT      2
326#define FFI_TYPE_DOUBLE     3
327
328#ifdef HAVE_LONG_DOUBLE
329#	define FFI_TYPE_LONGDOUBLE 4
330#else
331#	define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
332#endif
333
334#define FFI_TYPE_UINT8      5
335#define FFI_TYPE_SINT8      6
336#define FFI_TYPE_UINT16     7
337#define FFI_TYPE_SINT16     8
338#define FFI_TYPE_UINT32     9
339#define FFI_TYPE_SINT32     10
340#define FFI_TYPE_UINT64     11
341#define FFI_TYPE_SINT64     12
342#define FFI_TYPE_STRUCT     13
343#define FFI_TYPE_POINTER    14
344
345/*	This should always refer to the last type code (for sanity checks) */
346#define FFI_TYPE_LAST       FFI_TYPE_POINTER
347
348#ifdef __cplusplus
349}
350#endif
351
352#endif	// #ifndef LIBFFI_H