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, 2010 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>
43 /* ffi_prep_args is called by the assembly routine once stack space
44 has been allocated for the function's arguments */
46 void ffi_prep_args(char *stack, extended_cif *ecif);
47 void ffi_prep_args(char *stack, extended_cif *ecif)
49 register unsigned int i;
50 register void **p_argv;
52 register ffi_type **p_arg;
54 size_t p_stack_args[2];
55 void *p_stack_data[2];
57 int stack_args_count = 0;
58 int cabi = ecif->cif->abi;
63 if ((ecif->cif->flags == FFI_TYPE_STRUCT
64 || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
66 && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
67 && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
71 *(void **) argp = ecif->rvalue;
73 /* For fastcall/thiscall this is first register-passed
75 if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
77 p_stack_args[stack_args_count] = sizeof (void*);
78 p_stack_data[stack_args_count] = argp;
82 argp += sizeof(void*);
85 p_argv = ecif->avalue;
87 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
93 /* Align if necessary */
94 if ((sizeof(void*) - 1) & (size_t) argp)
95 argp = (char *) ALIGN(argp, sizeof(void*));
99 if (z > sizeof(ffi_arg)
100 || ((*p_arg)->type == FFI_TYPE_STRUCT
101 && (z != 1 && z != 2 && z != 4 && z != 8))
102 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
103 || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
108 *(void **)argp = *p_argv;
110 else if ((*p_arg)->type == FFI_TYPE_FLOAT)
112 memcpy(argp, *p_argv, z);
116 if (z < sizeof(ffi_arg))
119 switch ((*p_arg)->type)
122 *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
126 *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
129 case FFI_TYPE_SINT16:
130 *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
133 case FFI_TYPE_UINT16:
134 *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
137 case FFI_TYPE_SINT32:
138 *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
141 case FFI_TYPE_UINT32:
142 *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
145 case FFI_TYPE_STRUCT:
146 *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
155 memcpy(argp, *p_argv, z);
159 /* For thiscall/fastcall convention register-passed arguments
160 are the first two none-floating-point arguments with a size
161 smaller or equal to sizeof (void*). */
162 if ((cabi == FFI_THISCALL && stack_args_count < 1)
163 || (cabi == FFI_FASTCALL && stack_args_count < 2))
166 && ((*p_arg)->type != FFI_TYPE_FLOAT
167 && (*p_arg)->type != FFI_TYPE_STRUCT))
169 p_stack_args[stack_args_count] = z;
170 p_stack_data[stack_args_count] = argp;
177 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
184 /* We need to move the register-passed arguments for thiscall/fastcall
185 on top of stack, so that those can be moved to registers ecx/edx by
187 if (stack_args_count > 0)
189 size_t zz = (p_stack_args[0] + 3) & ~3;
192 /* Move first argument to top-stack position. */
193 if (p_stack_data[0] != argp2)
196 memcpy (h, p_stack_data[0], zz);
197 memmove (argp2 + zz, argp2,
198 (size_t) ((char *) p_stack_data[0] - (char*)argp2));
199 memcpy (argp2, h, zz);
205 stack_args_count = 0;
207 /* If we have a second argument, then move it on top
208 after the first one. */
209 if (stack_args_count > 0 && p_stack_data[1] != argp2)
211 zz = p_stack_args[1];
215 memcpy (h, p_stack_data[1], zz);
216 memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
217 memcpy (argp2, h, zz);
224 /* Perform machine dependent cif processing */
225 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
230 /* Set the return type flag */
231 switch (cif->rtype->type)
235 case FFI_TYPE_UINT16:
237 case FFI_TYPE_SINT16:
239 case FFI_TYPE_UINT32:
240 case FFI_TYPE_SINT32:
242 case FFI_TYPE_SINT64:
244 case FFI_TYPE_DOUBLE:
246 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
247 case FFI_TYPE_LONGDOUBLE:
250 cif->flags = (unsigned) cif->rtype->type;
253 case FFI_TYPE_UINT64:
255 case FFI_TYPE_POINTER:
257 cif->flags = FFI_TYPE_SINT64;
260 case FFI_TYPE_STRUCT:
262 if (cif->rtype->size == 1)
264 cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
266 else if (cif->rtype->size == 2)
268 cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
270 else if (cif->rtype->size == 4)
273 cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
275 cif->flags = FFI_TYPE_INT; /* same as int type */
278 else if (cif->rtype->size == 8)
280 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
286 if (cif->abi == FFI_MS_CDECL)
287 cif->flags = FFI_TYPE_MS_STRUCT;
290 cif->flags = FFI_TYPE_STRUCT;
291 /* allocate space for return value pointer */
292 cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
298 cif->flags = FFI_TYPE_SINT64;
301 cif->flags = FFI_TYPE_SINT32;
303 cif->flags = FFI_TYPE_INT;
308 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
310 if (((*ptr)->alignment - 1) & cif->bytes)
311 cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
312 cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
316 /* ensure space for storing four registers */
317 cif->bytes += 4 * sizeof(ffi_arg);
322 if (cif->abi != FFI_STDCALL && cif->abi != FFI_THISCALL && cif->abi != FFI_FASTCALL)
324 cif->bytes = (cif->bytes + 15) & ~0xF;
332 ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
333 unsigned, unsigned, unsigned *, void (*fn)(void));
336 ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
337 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
338 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
339 unsigned, unsigned, unsigned *, void (*fn)(void));
342 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
347 ecif.avalue = avalue;
349 /* If the return value is a struct and we don't have a return */
350 /* value address then we need to make one */
354 && cif->flags == FFI_TYPE_STRUCT
355 && cif->rtype->size != 1 && cif->rtype->size != 2
356 && cif->rtype->size != 4 && cif->rtype->size != 8)
358 ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
362 && (cif->flags == FFI_TYPE_STRUCT
363 || cif->flags == FFI_TYPE_MS_STRUCT))
365 ecif.rvalue = alloca(cif->rtype->size);
369 ecif.rvalue = rvalue;
376 ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
377 cif->flags, ecif.rvalue, fn);
382 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
390 ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
396 unsigned int abi = cif->abi;
397 unsigned int i, passed_regs = 0;
399 if (cif->flags == FFI_TYPE_STRUCT)
402 for (i=0; i < cif->nargs && passed_regs < 2;i++)
406 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
407 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
409 sz = (cif->arg_types[i]->size + 3) & ~3;
410 if (sz == 0 || sz > 4)
414 if (passed_regs < 2 && abi == FFI_FASTCALL)
416 if (passed_regs < 1 && abi == FFI_THISCALL)
418 ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
430 /** private members **/
432 /* The following __attribute__((regparm(1))) decorations will have no effect
433 on MSVC or SUNPRO_C -- standard conventions apply. */
434 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
435 void** args, ffi_cif* cif);
436 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
437 __attribute__ ((regparm(1)));
438 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
439 __attribute__ ((regparm(1)));
440 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
441 __attribute__ ((regparm(1)));
443 void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
444 __attribute__ ((regparm(1)));
447 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
448 __attribute__ ((regparm(1)));
449 void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
450 __attribute__ ((regparm(1)));
452 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
455 /* This function is jumped to by the trampoline */
459 ffi_closure_win64_inner (ffi_closure *closure, void *args) {
463 void *resp = &result;
466 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
468 /* this call will initialize ARG_AREA, such that each
469 * element in that array points to the corresponding
470 * value on the stack; and if the function returns
471 * a structure, it will change RESP to point to the
472 * structure return address. */
474 ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
476 (closure->fun) (cif, resp, arg_area, closure->user_data);
478 /* The result is returned in rax. This does the right thing for
479 result types except for floats; we have to 'mov xmm0, rax' in the
480 caller to correct this.
481 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
483 return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
487 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
488 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
490 /* our various things... */
495 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
497 /* this call will initialize ARG_AREA, such that each
498 * element in that array points to the corresponding
499 * value on the stack; and if the function returns
500 * a structure, it will change RESP to point to the
501 * structure return address. */
503 ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
505 (closure->fun) (cif, *respp, arg_area, closure->user_data);
509 #endif /* !X86_WIN64 */
512 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
515 register unsigned int i;
516 register void **p_argv;
518 register ffi_type **p_arg;
523 if (cif->rtype->size > sizeof(ffi_arg)
524 || (cif->flags == FFI_TYPE_STRUCT
525 && (cif->rtype->size != 1 && cif->rtype->size != 2
526 && cif->rtype->size != 4 && cif->rtype->size != 8))) {
527 *rvalue = *(void **) argp;
528 argp += sizeof(void *);
531 if ( cif->flags == FFI_TYPE_STRUCT
532 || cif->flags == FFI_TYPE_MS_STRUCT ) {
533 *rvalue = *(void **) argp;
534 argp += sizeof(void *);
540 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
544 /* Align if necessary */
545 if ((sizeof(void*) - 1) & (size_t) argp) {
546 argp = (char *) ALIGN(argp, sizeof(void*));
550 if ((*p_arg)->size > sizeof(ffi_arg)
551 || ((*p_arg)->type == FFI_TYPE_STRUCT
552 && ((*p_arg)->size != 1 && (*p_arg)->size != 2
553 && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
556 *p_argv = *(void **)argp;
563 /* because we're little endian, this is what it turns into. */
565 *p_argv = (void*) argp;
570 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
579 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
580 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
581 void* __fun = (void*)(FUN); \
582 void* __ctx = (void*)(CTX); \
583 *(unsigned char*) &__tramp[0] = 0x41; \
584 *(unsigned char*) &__tramp[1] = 0xbb; \
585 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
586 *(unsigned char*) &__tramp[6] = 0x48; \
587 *(unsigned char*) &__tramp[7] = 0xb8; \
588 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
589 *(unsigned char *) &__tramp[16] = 0x49; \
590 *(unsigned char *) &__tramp[17] = 0xba; \
591 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
592 *(unsigned char *) &__tramp[26] = 0x41; \
593 *(unsigned char *) &__tramp[27] = 0xff; \
594 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
597 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
599 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
600 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
601 unsigned int __fun = (unsigned int)(FUN); \
602 unsigned int __ctx = (unsigned int)(CTX); \
603 unsigned int __dis = __fun - (__ctx + 10); \
604 *(unsigned char*) &__tramp[0] = 0xb8; \
605 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
606 *(unsigned char *) &__tramp[5] = 0xe9; \
607 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
610 #define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \
611 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
612 unsigned int __fun = (unsigned int)(FUN); \
613 unsigned int __ctx = (unsigned int)(CTX); \
614 unsigned int __dis = __fun - (__ctx + 49); \
615 unsigned short __size = (unsigned short)(SIZE); \
616 *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
617 *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
618 *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
619 *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
620 *(unsigned char*) &__tramp[13] = 0xb8; \
621 *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
622 *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
623 *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
624 *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
625 *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
626 *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
627 *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
628 *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
629 *(unsigned char*) &__tramp[39] = 0xb8; \
630 *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
631 *(unsigned char *) &__tramp[44] = 0xe8; \
632 *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
633 *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
634 *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
637 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX) \
638 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
639 unsigned int __fun = (unsigned int)(FUN); \
640 unsigned int __ctx = (unsigned int)(CTX); \
641 unsigned int __dis = __fun - (__ctx + 10); \
642 *(unsigned char*) &__tramp[0] = 0xb8; \
643 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
644 *(unsigned char *) &__tramp[5] = 0xe8; \
645 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
648 /* the cif must already be prep'ed */
651 ffi_prep_closure_loc (ffi_closure* closure,
653 void (*fun)(ffi_cif*,void*,void**,void*),
658 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
659 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
660 if (cif->abi == FFI_WIN64)
662 int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
663 FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
666 /* make sure we can execute here */
669 if (cif->abi == FFI_SYSV)
671 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
675 else if (cif->abi == FFI_THISCALL)
677 FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
678 &ffi_closure_THISCALL,
681 else if (cif->abi == FFI_STDCALL)
683 FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
684 &ffi_closure_STDCALL,
688 else if (cif->abi == FFI_MS_CDECL)
690 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
694 #endif /* X86_WIN32 */
695 #endif /* !X86_WIN64 */
702 closure->user_data = user_data;
708 /* ------- Native raw API support -------------------------------- */
713 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
715 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
721 if (cif->abi != FFI_SYSV
723 && cif->abi != FFI_THISCALL
728 /* we currently don't support certain kinds of arguments for raw
729 closures. This should be implemented by a separate assembly
730 language routine, since it would require argument processing,
731 something we don't do now for performance. */
733 for (i = cif->nargs-1; i >= 0; i--)
735 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
736 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
740 if (cif->abi == FFI_SYSV)
743 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
747 else if (cif->abi == FFI_THISCALL)
749 FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, codeloc);
753 closure->user_data = user_data;
760 ffi_prep_args_raw(char *stack, extended_cif *ecif)
762 memcpy (stack, ecif->avalue, ecif->cif->bytes);
765 /* we borrow this routine from libffi (it must be changed, though, to
766 * actually call the function passed in the first argument. as of
767 * libffi-1.20, this is not the case.)
771 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
774 void **avalue = (void **)fake_avalue;
777 ecif.avalue = avalue;
779 /* If the return value is a struct and we don't have a return */
780 /* value address then we need to make one */
783 && (cif->flags == FFI_TYPE_STRUCT
784 || cif->flags == FFI_TYPE_MS_STRUCT))
786 ecif.rvalue = alloca(cif->rtype->size);
789 ecif.rvalue = rvalue;
796 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
805 ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
811 unsigned int abi = cif->abi;
812 unsigned int i, passed_regs = 0;
814 if (cif->flags == FFI_TYPE_STRUCT)
817 for (i=0; i < cif->nargs && passed_regs < 2;i++)
821 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
822 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
824 sz = (cif->arg_types[i]->size + 3) & ~3;
825 if (sz == 0 || sz > 4)
829 if (passed_regs < 2 && abi == FFI_FASTCALL)
830 cif->abi = abi = FFI_THISCALL;
831 if (passed_regs < 1 && abi == FFI_THISCALL)
832 cif->abi = abi = FFI_STDCALL;
833 ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
846 #endif /* !__x86_64__ || X86_WIN64 */