1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007 Red Hat, Inc.
3 Copyright (c) 2002 Ranjit Mathew
4 Copyright (c) 2002 Bo Thorsen
5 Copyright (c) 2002 Roger Sayle
6 Copyright (C) 2008 Free Software Foundation, Inc.
8 x86 Foreign Function Interface
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 ``Software''), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice shall be included
19 in all copies or substantial portions of the Software.
21 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 ----------------------------------------------------------------------- */
34 #include <ffi_common.h>
38 /* ffi_prep_args is called by the assembly routine once stack space
39 has been allocated for the function's arguments */
41 void ffi_prep_args(char *stack
, extended_cif
*ecif
)
43 register unsigned int i
;
44 register void **p_argv
;
46 register ffi_type
**p_arg
;
50 if (ecif
->cif
->flags
== FFI_TYPE_STRUCT
)
52 *(void **) argp
= ecif
->rvalue
;
56 p_argv
= ecif
->avalue
;
58 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
;
64 /* Align if necessary */
65 if ((sizeof(int) - 1) & (unsigned) argp
)
66 argp
= (char *) ALIGN(argp
, sizeof(int));
72 switch ((*p_arg
)->type
)
75 *(signed int *) argp
= (signed int)*(SINT8
*)(* p_argv
);
79 *(unsigned int *) argp
= (unsigned int)*(UINT8
*)(* p_argv
);
83 *(signed int *) argp
= (signed int)*(SINT16
*)(* p_argv
);
87 *(unsigned int *) argp
= (unsigned int)*(UINT16
*)(* p_argv
);
91 *(signed int *) argp
= (signed int)*(SINT32
*)(* p_argv
);
95 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
99 *(unsigned int *) argp
= (unsigned int)*(UINT32
*)(* p_argv
);
108 memcpy(argp
, *p_argv
, z
);
117 /* Perform machine dependent cif processing */
118 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
120 /* Set the return type flag */
121 switch (cif
->rtype
->type
)
125 case FFI_TYPE_STRUCT
:
127 #if defined(X86) || defined(X86_DARWIN)
129 case FFI_TYPE_UINT16
:
131 case FFI_TYPE_SINT16
:
134 case FFI_TYPE_SINT64
:
136 case FFI_TYPE_DOUBLE
:
137 case FFI_TYPE_LONGDOUBLE
:
138 cif
->flags
= (unsigned) cif
->rtype
->type
;
141 case FFI_TYPE_UINT64
:
142 cif
->flags
= FFI_TYPE_SINT64
;
146 case FFI_TYPE_STRUCT
:
147 if (cif
->rtype
->size
== 1)
149 cif
->flags
= FFI_TYPE_SMALL_STRUCT_1B
; /* same as char size */
151 else if (cif
->rtype
->size
== 2)
153 cif
->flags
= FFI_TYPE_SMALL_STRUCT_2B
; /* same as short size */
155 else if (cif
->rtype
->size
== 4)
157 cif
->flags
= FFI_TYPE_INT
; /* same as int type */
159 else if (cif
->rtype
->size
== 8)
161 cif
->flags
= FFI_TYPE_SINT64
; /* same as int64 type */
165 cif
->flags
= FFI_TYPE_STRUCT
;
171 cif
->flags
= FFI_TYPE_INT
;
176 cif
->bytes
= (cif
->bytes
+ 15) & ~0xF;
182 extern void ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*,
183 unsigned, unsigned, unsigned *, void (*fn
)());
186 extern void ffi_call_STDCALL(void (*)(char *, extended_cif
*), extended_cif
*,
187 unsigned, unsigned, unsigned *, void (*fn
)());
189 #endif /* X86_WIN32 */
191 void ffi_call(ffi_cif
*cif
, void (*fn
)(), void *rvalue
, void **avalue
)
196 ecif
.avalue
= avalue
;
198 /* If the return value is a struct and we don't have a return */
199 /* value address then we need to make one */
201 if ((rvalue
== NULL
) &&
202 (cif
->flags
== FFI_TYPE_STRUCT
))
204 ecif
.rvalue
= alloca(cif
->rtype
->size
);
207 ecif
.rvalue
= rvalue
;
213 ffi_call_SYSV(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
,
218 ffi_call_STDCALL(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
,
221 #endif /* X86_WIN32 */
229 /** private members **/
231 static void ffi_prep_incoming_args_SYSV (char *stack
, void **ret
,
232 void** args
, ffi_cif
* cif
);
233 void FFI_HIDDEN
ffi_closure_SYSV (ffi_closure
*)
234 __attribute__ ((regparm(1)));
235 unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (ffi_closure
*, void **, void *)
236 __attribute__ ((regparm(1)));
237 void FFI_HIDDEN
ffi_closure_raw_SYSV (ffi_raw_closure
*)
238 __attribute__ ((regparm(1)));
240 /* This function is jumped to by the trampoline */
242 unsigned int FFI_HIDDEN
243 ffi_closure_SYSV_inner (closure
, respp
, args
)
244 ffi_closure
*closure
;
248 // our various things...
253 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
255 /* this call will initialize ARG_AREA, such that each
256 * element in that array points to the corresponding
257 * value on the stack; and if the function returns
258 * a structure, it will re-set RESP to point to the
259 * structure return address. */
261 ffi_prep_incoming_args_SYSV(args
, respp
, arg_area
, cif
);
263 (closure
->fun
) (cif
, *respp
, arg_area
, closure
->user_data
);
269 ffi_prep_incoming_args_SYSV(char *stack
, void **rvalue
, void **avalue
,
272 register unsigned int i
;
273 register void **p_argv
;
275 register ffi_type
**p_arg
;
279 if ( cif
->flags
== FFI_TYPE_STRUCT
) {
280 *rvalue
= *(void **) argp
;
286 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; (i
!= 0); i
--, p_arg
++)
290 /* Align if necessary */
291 if ((sizeof(int) - 1) & (unsigned) argp
) {
292 argp
= (char *) ALIGN(argp
, sizeof(int));
297 /* because we're little endian, this is what it turns into. */
299 *p_argv
= (void*) argp
;
308 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
310 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
311 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
312 unsigned int __fun = (unsigned int)(FUN); \
313 unsigned int __ctx = (unsigned int)(CTX); \
314 unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
315 *(unsigned char*) &__tramp[0] = 0xb8; \
316 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
317 *(unsigned char *) &__tramp[5] = 0xe9; \
318 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
322 /* the cif must already be prep'ed */
325 ffi_prep_closure_loc (ffi_closure
* closure
,
327 void (*fun
)(ffi_cif
*,void*,void**,void*),
331 FFI_ASSERT (cif
->abi
== FFI_SYSV
);
333 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0], \
338 closure
->user_data
= user_data
;
344 /* ------- Native raw API support -------------------------------- */
349 ffi_prep_raw_closure_loc (ffi_raw_closure
* closure
,
351 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*),
357 FFI_ASSERT (cif
->abi
== FFI_SYSV
);
359 // we currently don't support certain kinds of arguments for raw
360 // closures. This should be implemented by a separate assembly language
361 // routine, since it would require argument processing, something we
362 // don't do now for performance.
364 for (i
= cif
->nargs
-1; i
>= 0; i
--)
366 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_STRUCT
);
367 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_LONGDOUBLE
);
371 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0], &ffi_closure_raw_SYSV
,
375 closure
->user_data
= user_data
;
382 ffi_prep_args_raw(char *stack
, extended_cif
*ecif
)
384 memcpy (stack
, ecif
->avalue
, ecif
->cif
->bytes
);
387 /* we borrow this routine from libffi (it must be changed, though, to
388 * actually call the function passed in the first argument. as of
389 * libffi-1.20, this is not the case.)
393 ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*, unsigned,
394 unsigned, unsigned *, void (*fn
)());
398 ffi_call_STDCALL(void (*)(char *, extended_cif
*), extended_cif
*, unsigned,
399 unsigned, unsigned *, void (*fn
)());
400 #endif /* X86_WIN32 */
403 ffi_raw_call(ffi_cif
*cif
, void (*fn
)(), void *rvalue
, ffi_raw
*fake_avalue
)
406 void **avalue
= (void **)fake_avalue
;
409 ecif
.avalue
= avalue
;
411 /* If the return value is a struct and we don't have a return */
412 /* value address then we need to make one */
414 if ((rvalue
== NULL
) &&
415 (cif
->rtype
->type
== FFI_TYPE_STRUCT
))
417 ecif
.rvalue
= alloca(cif
->rtype
->size
);
420 ecif
.rvalue
= rvalue
;
426 ffi_call_SYSV(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
431 ffi_call_STDCALL(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
434 #endif /* X86_WIN32 */
443 #endif /* __x86_64__ */