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 ----------------------------------------------------------------------- */
31 #if !defined(__x86_64__) || defined(_WIN64)
38 #include <ffi_common.h>
42 /* ffi_prep_args is called by the assembly routine once stack space
43 has been allocated for the function's arguments */
45 void ffi_prep_args(char *stack, extended_cif *ecif)
47 register unsigned int i;
48 register void **p_argv;
50 register ffi_type **p_arg;
54 if (ecif->cif->flags == FFI_TYPE_STRUCT
56 && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
57 && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
61 *(void **) argp = ecif->rvalue;
62 argp += sizeof(void*);
65 p_argv = ecif->avalue;
67 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
73 /* Align if necessary */
74 if ((sizeof(void*) - 1) & (size_t) argp)
75 argp = (char *) ALIGN(argp, sizeof(void*));
79 if (z > sizeof(ffi_arg)
80 || ((*p_arg)->type == FFI_TYPE_STRUCT
81 && (z != 1 && z != 2 && z != 4 && z != 8))
82 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
83 || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
88 *(void **)argp = *p_argv;
90 else if ((*p_arg)->type == FFI_TYPE_FLOAT)
92 memcpy(argp, *p_argv, z);
96 if (z < sizeof(ffi_arg))
99 switch ((*p_arg)->type)
102 *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
106 *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
109 case FFI_TYPE_SINT16:
110 *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
113 case FFI_TYPE_UINT16:
114 *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
117 case FFI_TYPE_SINT32:
118 *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
121 case FFI_TYPE_UINT32:
122 *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
125 case FFI_TYPE_STRUCT:
126 *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
135 memcpy(argp, *p_argv, z);
139 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
148 /* Perform machine dependent cif processing */
149 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
154 /* Set the return type flag */
155 switch (cif->rtype->type)
159 case FFI_TYPE_UINT16:
161 case FFI_TYPE_SINT16:
163 case FFI_TYPE_UINT32:
164 case FFI_TYPE_SINT32:
166 case FFI_TYPE_SINT64:
168 case FFI_TYPE_DOUBLE:
170 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
171 case FFI_TYPE_LONGDOUBLE:
174 cif->flags = (unsigned) cif->rtype->type;
177 case FFI_TYPE_UINT64:
179 case FFI_TYPE_POINTER:
181 cif->flags = FFI_TYPE_SINT64;
184 case FFI_TYPE_STRUCT:
186 if (cif->rtype->size == 1)
188 cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
190 else if (cif->rtype->size == 2)
192 cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
194 else if (cif->rtype->size == 4)
197 cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
199 cif->flags = FFI_TYPE_INT; /* same as int type */
202 else if (cif->rtype->size == 8)
204 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
209 cif->flags = FFI_TYPE_STRUCT;
210 /* allocate space for return value pointer */
211 cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
217 cif->flags = FFI_TYPE_SINT64;
220 cif->flags = FFI_TYPE_SINT32;
222 cif->flags = FFI_TYPE_INT;
227 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
229 if (((*ptr)->alignment - 1) & cif->bytes)
230 cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
231 cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
235 /* ensure space for storing four registers */
236 cif->bytes += 4 * sizeof(ffi_arg);
240 cif->bytes = (cif->bytes + 15) & ~0xF;
248 ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
249 unsigned, unsigned, unsigned *, void (*fn)(void));
250 #elif defined(X86_WIN32)
252 ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
253 unsigned, unsigned, unsigned *, void (*fn)(void));
255 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
256 unsigned, unsigned, unsigned *, void (*fn)(void));
259 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
264 ecif.avalue = avalue;
266 /* If the return value is a struct and we don't have a return */
267 /* value address then we need to make one */
271 && cif->flags == FFI_TYPE_STRUCT
272 && cif->rtype->size != 1 && cif->rtype->size != 2
273 && cif->rtype->size != 4 && cif->rtype->size != 8)
275 ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
279 && cif->flags == FFI_TYPE_STRUCT)
281 ecif.rvalue = alloca(cif->rtype->size);
285 ecif.rvalue = rvalue;
292 ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
293 cif->flags, ecif.rvalue, fn);
295 #elif defined(X86_WIN32)
298 ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags,
303 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
314 /** private members **/
316 /* The following __attribute__((regparm(1))) decorations will have no effect
317 on MSVC - standard cdecl convention applies. */
318 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
319 void** args, ffi_cif* cif);
320 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
321 __attribute__ ((regparm(1)));
322 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
323 __attribute__ ((regparm(1)));
324 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
325 __attribute__ ((regparm(1)));
327 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
328 __attribute__ ((regparm(1)));
331 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
334 /* This function is jumped to by the trampoline */
338 ffi_closure_win64_inner (ffi_closure *closure, void *args) {
342 void *resp = &result;
345 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
347 /* this call will initialize ARG_AREA, such that each
348 * element in that array points to the corresponding
349 * value on the stack; and if the function returns
350 * a structure, it will change RESP to point to the
351 * structure return address. */
353 ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
355 (closure->fun) (cif, resp, arg_area, closure->user_data);
357 /* The result is returned in rax. This does the right thing for
358 result types except for floats; we have to 'mov xmm0, rax' in the
359 caller to correct this.
360 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
362 return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
366 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
367 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
369 /* our various things... */
374 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
376 /* this call will initialize ARG_AREA, such that each
377 * element in that array points to the corresponding
378 * value on the stack; and if the function returns
379 * a structure, it will change RESP to point to the
380 * structure return address. */
382 ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
384 (closure->fun) (cif, *respp, arg_area, closure->user_data);
388 #endif /* !X86_WIN64 */
391 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
394 register unsigned int i;
395 register void **p_argv;
397 register ffi_type **p_arg;
402 if (cif->rtype->size > sizeof(ffi_arg)
403 || (cif->flags == FFI_TYPE_STRUCT
404 && (cif->rtype->size != 1 && cif->rtype->size != 2
405 && cif->rtype->size != 4 && cif->rtype->size != 8))) {
406 *rvalue = *(void **) argp;
407 argp += sizeof(void *);
410 if ( cif->flags == FFI_TYPE_STRUCT ) {
411 *rvalue = *(void **) argp;
412 argp += sizeof(void *);
418 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
422 /* Align if necessary */
423 if ((sizeof(void*) - 1) & (size_t) argp) {
424 argp = (char *) ALIGN(argp, sizeof(void*));
428 if ((*p_arg)->size > sizeof(ffi_arg)
429 || ((*p_arg)->type == FFI_TYPE_STRUCT
430 && ((*p_arg)->size != 1 && (*p_arg)->size != 2
431 && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
434 *p_argv = *(void **)argp;
441 /* because we're little endian, this is what it turns into. */
443 *p_argv = (void*) argp;
448 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
457 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
458 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
459 void* __fun = (void*)(FUN); \
460 void* __ctx = (void*)(CTX); \
461 *(unsigned char*) &__tramp[0] = 0x41; \
462 *(unsigned char*) &__tramp[1] = 0xbb; \
463 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
464 *(unsigned char*) &__tramp[6] = 0x48; \
465 *(unsigned char*) &__tramp[7] = 0xb8; \
466 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
467 *(unsigned char *) &__tramp[16] = 0x49; \
468 *(unsigned char *) &__tramp[17] = 0xba; \
469 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
470 *(unsigned char *) &__tramp[26] = 0x41; \
471 *(unsigned char *) &__tramp[27] = 0xff; \
472 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
475 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
477 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
478 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
479 unsigned int __fun = (unsigned int)(FUN); \
480 unsigned int __ctx = (unsigned int)(CTX); \
481 unsigned int __dis = __fun - (__ctx + 10); \
482 *(unsigned char*) &__tramp[0] = 0xb8; \
483 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
484 *(unsigned char *) &__tramp[5] = 0xe9; \
485 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
488 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
489 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
490 unsigned int __fun = (unsigned int)(FUN); \
491 unsigned int __ctx = (unsigned int)(CTX); \
492 unsigned int __dis = __fun - (__ctx + 10); \
493 unsigned short __size = (unsigned short)(SIZE); \
494 *(unsigned char*) &__tramp[0] = 0xb8; \
495 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
496 *(unsigned char *) &__tramp[5] = 0xe8; \
497 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
498 *(unsigned char *) &__tramp[10] = 0xc2; \
499 *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
502 /* the cif must already be prep'ed */
505 ffi_prep_closure_loc (ffi_closure* closure,
507 void (*fun)(ffi_cif*,void*,void**,void*),
512 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
513 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
514 if (cif->abi == FFI_WIN64)
516 int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
517 FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
520 /* make sure we can execute here */
523 if (cif->abi == FFI_SYSV)
525 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
530 else if (cif->abi == FFI_STDCALL)
532 FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
533 &ffi_closure_STDCALL,
534 (void*)codeloc, cif->bytes);
536 #endif /* X86_WIN32 */
537 #endif /* !X86_WIN64 */
544 closure->user_data = user_data;
550 /* ------- Native raw API support -------------------------------- */
555 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
557 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
563 if (cif->abi != FFI_SYSV) {
567 /* we currently don't support certain kinds of arguments for raw
568 closures. This should be implemented by a separate assembly
569 language routine, since it would require argument processing,
570 something we don't do now for performance. */
572 for (i = cif->nargs-1; i >= 0; i--)
574 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
575 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
579 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
583 closure->user_data = user_data;
590 ffi_prep_args_raw(char *stack, extended_cif *ecif)
592 memcpy (stack, ecif->avalue, ecif->cif->bytes);
595 /* we borrow this routine from libffi (it must be changed, though, to
596 * actually call the function passed in the first argument. as of
597 * libffi-1.20, this is not the case.)
601 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
604 void **avalue = (void **)fake_avalue;
607 ecif.avalue = avalue;
609 /* If the return value is a struct and we don't have a return */
610 /* value address then we need to make one */
612 if ((rvalue == NULL) &&
613 (cif->rtype->type == FFI_TYPE_STRUCT))
615 ecif.rvalue = alloca(cif->rtype->size);
618 ecif.rvalue = rvalue;
626 ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
631 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
643 #endif /* !__x86_64__ || X86_WIN64 */