1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 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)(void));
186 extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
187 unsigned, unsigned, unsigned *, void (*fn)(void));
189 #endif /* X86_WIN32 */
191 void ffi_call(ffi_cif *cif, void (*fn)(void), 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 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
241 __attribute__ ((regparm(1)));
244 /* This function is jumped to by the trampoline */
246 unsigned int FFI_HIDDEN
247 ffi_closure_SYSV_inner (closure, respp, args)
248 ffi_closure *closure;
252 /* our various things... */
257 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
259 /* this call will initialize ARG_AREA, such that each
260 * element in that array points to the corresponding
261 * value on the stack; and if the function returns
262 * a structure, it will re-set RESP to point to the
263 * structure return address. */
265 ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
267 (closure->fun) (cif, *respp, arg_area, closure->user_data);
273 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
276 register unsigned int i;
277 register void **p_argv;
279 register ffi_type **p_arg;
283 if ( cif->flags == FFI_TYPE_STRUCT ) {
284 *rvalue = *(void **) argp;
290 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
294 /* Align if necessary */
295 if ((sizeof(int) - 1) & (unsigned) argp) {
296 argp = (char *) ALIGN(argp, sizeof(int));
301 /* because we're little endian, this is what it turns into. */
303 *p_argv = (void*) argp;
312 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
314 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
315 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
316 unsigned int __fun = (unsigned int)(FUN); \
317 unsigned int __ctx = (unsigned int)(CTX); \
318 unsigned int __dis = __fun - (__ctx + 10); \
319 *(unsigned char*) &__tramp[0] = 0xb8; \
320 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
321 *(unsigned char *) &__tramp[5] = 0xe9; \
322 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
325 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
326 ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
327 unsigned int __fun = (unsigned int)(FUN); \
328 unsigned int __ctx = (unsigned int)(CTX); \
329 unsigned int __dis = __fun - (__ctx + 10); \
330 unsigned short __size = (unsigned short)(SIZE); \
331 *(unsigned char*) &__tramp[0] = 0xb8; \
332 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
333 *(unsigned char *) &__tramp[5] = 0xe8; \
334 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
335 *(unsigned char *) &__tramp[10] = 0xc2; \
336 *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
339 /* the cif must already be prep'ed */
342 ffi_prep_closure_loc (ffi_closure* closure,
344 void (*fun)(ffi_cif*,void*,void**,void*),
348 if (cif->abi == FFI_SYSV)
350 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
355 else if (cif->abi == FFI_STDCALL)
357 FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
358 &ffi_closure_STDCALL,
359 (void*)codeloc, cif->bytes);
368 closure->user_data = user_data;
374 /* ------- Native raw API support -------------------------------- */
379 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
381 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
387 if (cif->abi != FFI_SYSV) {
391 // we currently don't support certain kinds of arguments for raw
392 // closures. This should be implemented by a separate assembly language
393 // routine, since it would require argument processing, something we
394 // don't do now for performance.
396 for (i = cif->nargs-1; i >= 0; i--)
398 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
399 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
403 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
407 closure->user_data = user_data;
414 ffi_prep_args_raw(char *stack, extended_cif *ecif)
416 memcpy (stack, ecif->avalue, ecif->cif->bytes);
419 /* we borrow this routine from libffi (it must be changed, though, to
420 * actually call the function passed in the first argument. as of
421 * libffi-1.20, this is not the case.)
425 ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
426 unsigned, unsigned *, void (*fn)(void));
430 ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
431 unsigned, unsigned *, void (*fn)(void));
432 #endif /* X86_WIN32 */
435 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
438 void **avalue = (void **)fake_avalue;
441 ecif.avalue = avalue;
443 /* If the return value is a struct and we don't have a return */
444 /* value address then we need to make one */
446 if ((rvalue == NULL) &&
447 (cif->rtype->type == FFI_TYPE_STRUCT))
449 ecif.rvalue = alloca(cif->rtype->size);
452 ecif.rvalue = rvalue;
458 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
463 ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
466 #endif /* X86_WIN32 */
475 #endif /* __x86_64__ */