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) || defined(__CYGWIN__)
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
;
52 size_t p_stack_args
[2];
53 void *p_stack_data
[2];
55 int stack_args_count
= 0;
56 int cabi
= ecif
->cif
->abi
;
61 if ((ecif
->cif
->flags
== FFI_TYPE_STRUCT
62 || ecif
->cif
->flags
== FFI_TYPE_MS_STRUCT
)
64 && (ecif
->cif
->rtype
->size
!= 1 && ecif
->cif
->rtype
->size
!= 2
65 && ecif
->cif
->rtype
->size
!= 4 && ecif
->cif
->rtype
->size
!= 8)
69 *(void **) argp
= ecif
->rvalue
;
71 /* For fastcall/thiscall this is first register-passed
73 if (cabi
== FFI_THISCALL
|| cabi
== FFI_FASTCALL
)
75 p_stack_args
[stack_args_count
] = sizeof (void*);
76 p_stack_data
[stack_args_count
] = argp
;
80 argp
+= sizeof(void*);
83 p_argv
= ecif
->avalue
;
85 for (i
= ecif
->cif
->nargs
, p_arg
= ecif
->cif
->arg_types
;
91 /* Align if necessary */
92 if ((sizeof(void*) - 1) & (size_t) argp
)
93 argp
= (char *) ALIGN(argp
, sizeof(void*));
97 if (z
> sizeof(ffi_arg
)
98 || ((*p_arg
)->type
== FFI_TYPE_STRUCT
99 && (z
!= 1 && z
!= 2 && z
!= 4 && z
!= 8))
100 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
101 || ((*p_arg
)->type
== FFI_TYPE_LONGDOUBLE
)
106 *(void **)argp
= *p_argv
;
108 else if ((*p_arg
)->type
== FFI_TYPE_FLOAT
)
110 memcpy(argp
, *p_argv
, z
);
114 if (z
< sizeof(ffi_arg
))
117 switch ((*p_arg
)->type
)
120 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT8
*)(* p_argv
);
124 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT8
*)(* p_argv
);
127 case FFI_TYPE_SINT16
:
128 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT16
*)(* p_argv
);
131 case FFI_TYPE_UINT16
:
132 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT16
*)(* p_argv
);
135 case FFI_TYPE_SINT32
:
136 *(ffi_sarg
*) argp
= (ffi_sarg
)*(SINT32
*)(* p_argv
);
139 case FFI_TYPE_UINT32
:
140 *(ffi_arg
*) argp
= (ffi_arg
)*(UINT32
*)(* p_argv
);
143 case FFI_TYPE_STRUCT
:
144 *(ffi_arg
*) argp
= *(ffi_arg
*)(* p_argv
);
153 memcpy(argp
, *p_argv
, z
);
157 /* For thiscall/fastcall convention register-passed arguments
158 are the first two none-floating-point arguments with a size
159 smaller or equal to sizeof (void*). */
160 if ((cabi
== FFI_THISCALL
&& stack_args_count
< 1)
161 || (cabi
== FFI_FASTCALL
&& stack_args_count
< 2))
164 && ((*p_arg
)->type
!= FFI_TYPE_FLOAT
165 && (*p_arg
)->type
!= FFI_TYPE_STRUCT
))
167 p_stack_args
[stack_args_count
] = z
;
168 p_stack_data
[stack_args_count
] = argp
;
175 argp
+= (z
+ sizeof(void*) - 1) & ~(sizeof(void*) - 1);
182 /* We need to move the register-passed arguments for thiscall/fastcall
183 on top of stack, so that those can be moved to registers ecx/edx by
185 if (stack_args_count
> 0)
187 size_t zz
= (p_stack_args
[0] + 3) & ~3;
190 /* Move first argument to top-stack position. */
191 if (p_stack_data
[0] != argp2
)
194 memcpy (h
, p_stack_data
[0], zz
);
195 memmove (argp2
+ zz
, argp2
,
196 (size_t) ((char *) p_stack_data
[0] - (char*)argp2
));
197 memcpy (argp2
, h
, zz
);
203 stack_args_count
= 0;
205 /* If we have a second argument, then move it on top
206 after the first one. */
207 if (stack_args_count
> 0 && p_stack_data
[1] != argp2
)
209 zz
= p_stack_args
[1];
213 memcpy (h
, p_stack_data
[1], zz
);
214 memmove (argp2
+ zz
, argp2
, (size_t) ((char*) p_stack_data
[1] - (char*)argp2
));
215 memcpy (argp2
, h
, zz
);
222 /* Perform machine dependent cif processing */
223 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
228 /* Set the return type flag */
229 switch (cif
->rtype
->type
)
233 case FFI_TYPE_UINT16
:
235 case FFI_TYPE_SINT16
:
237 case FFI_TYPE_UINT32
:
238 case FFI_TYPE_SINT32
:
240 case FFI_TYPE_SINT64
:
242 case FFI_TYPE_DOUBLE
:
244 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
245 case FFI_TYPE_LONGDOUBLE
:
248 cif
->flags
= (unsigned) cif
->rtype
->type
;
251 case FFI_TYPE_UINT64
:
253 case FFI_TYPE_POINTER
:
255 cif
->flags
= FFI_TYPE_SINT64
;
258 case FFI_TYPE_STRUCT
:
260 if (cif
->rtype
->size
== 1)
262 cif
->flags
= FFI_TYPE_SMALL_STRUCT_1B
; /* same as char size */
264 else if (cif
->rtype
->size
== 2)
266 cif
->flags
= FFI_TYPE_SMALL_STRUCT_2B
; /* same as short size */
268 else if (cif
->rtype
->size
== 4)
271 cif
->flags
= FFI_TYPE_SMALL_STRUCT_4B
;
273 cif
->flags
= FFI_TYPE_INT
; /* same as int type */
276 else if (cif
->rtype
->size
== 8)
278 cif
->flags
= FFI_TYPE_SINT64
; /* same as int64 type */
284 if (cif
->abi
== FFI_MS_CDECL
)
285 cif
->flags
= FFI_TYPE_MS_STRUCT
;
288 cif
->flags
= FFI_TYPE_STRUCT
;
289 /* allocate space for return value pointer */
290 cif
->bytes
+= ALIGN(sizeof(void*), FFI_SIZEOF_ARG
);
296 cif
->flags
= FFI_TYPE_SINT64
;
299 cif
->flags
= FFI_TYPE_SINT32
;
301 cif
->flags
= FFI_TYPE_INT
;
306 for (ptr
= cif
->arg_types
, i
= cif
->nargs
; i
> 0; i
--, ptr
++)
308 if (((*ptr
)->alignment
- 1) & cif
->bytes
)
309 cif
->bytes
= ALIGN(cif
->bytes
, (*ptr
)->alignment
);
310 cif
->bytes
+= ALIGN((*ptr
)->size
, FFI_SIZEOF_ARG
);
314 /* ensure space for storing four registers */
315 cif
->bytes
+= 4 * sizeof(ffi_arg
);
319 cif
->bytes
= (cif
->bytes
+ 15) & ~0xF;
327 ffi_call_win64(void (*)(char *, extended_cif
*), extended_cif
*,
328 unsigned, unsigned, unsigned *, void (*fn
)(void));
329 #elif defined(X86_WIN32)
331 ffi_call_win32(void (*)(char *, extended_cif
*), extended_cif
*,
332 unsigned, unsigned, unsigned, unsigned *, void (*fn
)(void));
334 extern void ffi_call_SYSV(void (*)(char *, extended_cif
*), extended_cif
*,
335 unsigned, unsigned, unsigned *, void (*fn
)(void));
338 void ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
343 ecif
.avalue
= avalue
;
345 /* If the return value is a struct and we don't have a return */
346 /* value address then we need to make one */
350 && cif
->flags
== FFI_TYPE_STRUCT
351 && cif
->rtype
->size
!= 1 && cif
->rtype
->size
!= 2
352 && cif
->rtype
->size
!= 4 && cif
->rtype
->size
!= 8)
354 ecif
.rvalue
= alloca((cif
->rtype
->size
+ 0xF) & ~0xF);
358 && (cif
->flags
== FFI_TYPE_STRUCT
359 || cif
->flags
== FFI_TYPE_MS_STRUCT
))
361 ecif
.rvalue
= alloca(cif
->rtype
->size
);
365 ecif
.rvalue
= rvalue
;
372 ffi_call_win64(ffi_prep_args
, &ecif
, cif
->bytes
,
373 cif
->flags
, ecif
.rvalue
, fn
);
375 #elif defined(X86_WIN32)
379 ffi_call_win32(ffi_prep_args
, &ecif
, cif
->abi
, cif
->bytes
, cif
->flags
,
385 unsigned int abi
= cif
->abi
;
386 unsigned int i
, passed_regs
= 0;
388 if (cif
->flags
== FFI_TYPE_STRUCT
)
391 for (i
=0; i
< cif
->nargs
&& passed_regs
< 2;i
++)
395 if (cif
->arg_types
[i
]->type
== FFI_TYPE_FLOAT
396 || cif
->arg_types
[i
]->type
== FFI_TYPE_STRUCT
)
398 sz
= (cif
->arg_types
[i
]->size
+ 3) & ~3;
399 if (sz
== 0 || sz
> 4)
403 if (passed_regs
< 2 && abi
== FFI_FASTCALL
)
405 if (passed_regs
< 1 && abi
== FFI_THISCALL
)
407 ffi_call_win32(ffi_prep_args
, &ecif
, abi
, cif
->bytes
, cif
->flags
,
413 ffi_call_SYSV(ffi_prep_args
, &ecif
, cif
->bytes
, cif
->flags
, ecif
.rvalue
,
424 /** private members **/
426 /* The following __attribute__((regparm(1))) decorations will have no effect
427 on MSVC - standard cdecl convention applies. */
428 static void ffi_prep_incoming_args_SYSV (char *stack
, void **ret
,
429 void** args
, ffi_cif
* cif
);
430 void FFI_HIDDEN
ffi_closure_SYSV (ffi_closure
*)
431 __attribute__ ((regparm(1)));
432 unsigned int FFI_HIDDEN
ffi_closure_SYSV_inner (ffi_closure
*, void **, void *)
433 __attribute__ ((regparm(1)));
434 void FFI_HIDDEN
ffi_closure_raw_SYSV (ffi_raw_closure
*)
435 __attribute__ ((regparm(1)));
437 void FFI_HIDDEN
ffi_closure_raw_THISCALL (ffi_raw_closure
*)
438 __attribute__ ((regparm(1)));
439 void FFI_HIDDEN
ffi_closure_STDCALL (ffi_closure
*)
440 __attribute__ ((regparm(1)));
441 void FFI_HIDDEN
ffi_closure_THISCALL (ffi_closure
*)
442 __attribute__ ((regparm(1)));
445 void FFI_HIDDEN
ffi_closure_win64 (ffi_closure
*);
448 /* This function is jumped to by the trampoline */
452 ffi_closure_win64_inner (ffi_closure
*closure
, void *args
) {
456 void *resp
= &result
;
459 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
461 /* this call will initialize ARG_AREA, such that each
462 * element in that array points to the corresponding
463 * value on the stack; and if the function returns
464 * a structure, it will change RESP to point to the
465 * structure return address. */
467 ffi_prep_incoming_args_SYSV(args
, &resp
, arg_area
, cif
);
469 (closure
->fun
) (cif
, resp
, arg_area
, closure
->user_data
);
471 /* The result is returned in rax. This does the right thing for
472 result types except for floats; we have to 'mov xmm0, rax' in the
473 caller to correct this.
474 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
476 return cif
->rtype
->size
> sizeof(void *) ? resp
: *(void **)resp
;
480 unsigned int FFI_HIDDEN
__attribute__ ((regparm(1)))
481 ffi_closure_SYSV_inner (ffi_closure
*closure
, void **respp
, void *args
)
483 /* our various things... */
488 arg_area
= (void**) alloca (cif
->nargs
* sizeof (void*));
490 /* this call will initialize ARG_AREA, such that each
491 * element in that array points to the corresponding
492 * value on the stack; and if the function returns
493 * a structure, it will change RESP to point to the
494 * structure return address. */
496 ffi_prep_incoming_args_SYSV(args
, respp
, arg_area
, cif
);
498 (closure
->fun
) (cif
, *respp
, arg_area
, closure
->user_data
);
502 #endif /* !X86_WIN64 */
505 ffi_prep_incoming_args_SYSV(char *stack
, void **rvalue
, void **avalue
,
508 register unsigned int i
;
509 register void **p_argv
;
511 register ffi_type
**p_arg
;
516 if (cif
->rtype
->size
> sizeof(ffi_arg
)
517 || (cif
->flags
== FFI_TYPE_STRUCT
518 && (cif
->rtype
->size
!= 1 && cif
->rtype
->size
!= 2
519 && cif
->rtype
->size
!= 4 && cif
->rtype
->size
!= 8))) {
520 *rvalue
= *(void **) argp
;
521 argp
+= sizeof(void *);
524 if ( cif
->flags
== FFI_TYPE_STRUCT
525 || cif
->flags
== FFI_TYPE_MS_STRUCT
) {
526 *rvalue
= *(void **) argp
;
527 argp
+= sizeof(void *);
533 for (i
= cif
->nargs
, p_arg
= cif
->arg_types
; (i
!= 0); i
--, p_arg
++)
537 /* Align if necessary */
538 if ((sizeof(void*) - 1) & (size_t) argp
) {
539 argp
= (char *) ALIGN(argp
, sizeof(void*));
543 if ((*p_arg
)->size
> sizeof(ffi_arg
)
544 || ((*p_arg
)->type
== FFI_TYPE_STRUCT
545 && ((*p_arg
)->size
!= 1 && (*p_arg
)->size
!= 2
546 && (*p_arg
)->size
!= 4 && (*p_arg
)->size
!= 8)))
549 *p_argv
= *(void **)argp
;
556 /* because we're little endian, this is what it turns into. */
558 *p_argv
= (void*) argp
;
563 argp
+= (z
+ sizeof(void*) - 1) & ~(sizeof(void*) - 1);
572 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
573 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
574 void* __fun = (void*)(FUN); \
575 void* __ctx = (void*)(CTX); \
576 *(unsigned char*) &__tramp[0] = 0x41; \
577 *(unsigned char*) &__tramp[1] = 0xbb; \
578 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
579 *(unsigned char*) &__tramp[6] = 0x48; \
580 *(unsigned char*) &__tramp[7] = 0xb8; \
581 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
582 *(unsigned char *) &__tramp[16] = 0x49; \
583 *(unsigned char *) &__tramp[17] = 0xba; \
584 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
585 *(unsigned char *) &__tramp[26] = 0x41; \
586 *(unsigned char *) &__tramp[27] = 0xff; \
587 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
590 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
592 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
593 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
594 unsigned int __fun = (unsigned int)(FUN); \
595 unsigned int __ctx = (unsigned int)(CTX); \
596 unsigned int __dis = __fun - (__ctx + 10); \
597 *(unsigned char*) &__tramp[0] = 0xb8; \
598 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
599 *(unsigned char *) &__tramp[5] = 0xe9; \
600 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
603 #define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
604 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
605 unsigned int __fun = (unsigned int)(FUN); \
606 unsigned int __ctx = (unsigned int)(CTX); \
607 unsigned int __dis = __fun - (__ctx + 49); \
608 unsigned short __size = (unsigned short)(SIZE); \
609 *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
610 *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
611 *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
612 *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
613 *(unsigned char*) &__tramp[13] = 0xb8; \
614 *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
615 *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
616 *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
617 *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
618 *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
619 *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
620 *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
621 *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
622 *(unsigned char*) &__tramp[39] = 0xb8; \
623 *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
624 *(unsigned char *) &__tramp[44] = 0xe8; \
625 *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
626 *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
627 *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
630 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
631 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
632 unsigned int __fun = (unsigned int)(FUN); \
633 unsigned int __ctx = (unsigned int)(CTX); \
634 unsigned int __dis = __fun - (__ctx + 10); \
635 unsigned short __size = (unsigned short)(SIZE); \
636 *(unsigned char*) &__tramp[0] = 0xb8; \
637 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
638 *(unsigned char *) &__tramp[5] = 0xe8; \
639 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
640 *(unsigned char *) &__tramp[10] = 0xc2; \
641 *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
644 /* the cif must already be prep'ed */
647 ffi_prep_closure_loc (ffi_closure
* closure
,
649 void (*fun
)(ffi_cif
*,void*,void**,void*),
654 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
655 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
656 if (cif
->abi
== FFI_WIN64
)
658 int mask
= FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
659 FFI_INIT_TRAMPOLINE_WIN64 (&closure
->tramp
[0],
662 /* make sure we can execute here */
665 if (cif
->abi
== FFI_SYSV
)
667 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0],
672 else if (cif
->abi
== FFI_THISCALL
)
674 FFI_INIT_TRAMPOLINE_THISCALL (&closure
->tramp
[0],
675 &ffi_closure_THISCALL
,
679 else if (cif
->abi
== FFI_STDCALL
)
681 FFI_INIT_TRAMPOLINE_STDCALL (&closure
->tramp
[0],
682 &ffi_closure_STDCALL
,
683 (void*)codeloc
, cif
->bytes
);
685 else if (cif
->abi
== FFI_MS_CDECL
)
687 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0],
691 #endif /* X86_WIN32 */
692 #endif /* !X86_WIN64 */
699 closure
->user_data
= user_data
;
705 /* ------- Native raw API support -------------------------------- */
710 ffi_prep_raw_closure_loc (ffi_raw_closure
* closure
,
712 void (*fun
)(ffi_cif
*,void*,ffi_raw
*,void*),
718 if (cif
->abi
!= FFI_SYSV
) {
720 if (cif
->abi
!= FFI_THISCALL
)
725 /* we currently don't support certain kinds of arguments for raw
726 closures. This should be implemented by a separate assembly
727 language routine, since it would require argument processing,
728 something we don't do now for performance. */
730 for (i
= cif
->nargs
-1; i
>= 0; i
--)
732 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_STRUCT
);
733 FFI_ASSERT (cif
->arg_types
[i
]->type
!= FFI_TYPE_LONGDOUBLE
);
737 if (cif
->abi
== FFI_SYSV
)
740 FFI_INIT_TRAMPOLINE (&closure
->tramp
[0], &ffi_closure_raw_SYSV
,
744 else if (cif
->abi
== FFI_THISCALL
)
746 FFI_INIT_TRAMPOLINE_THISCALL (&closure
->tramp
[0], &ffi_closure_raw_THISCALL
,
747 codeloc
, cif
->bytes
);
751 closure
->user_data
= user_data
;
758 ffi_prep_args_raw(char *stack
, extended_cif
*ecif
)
760 memcpy (stack
, ecif
->avalue
, ecif
->cif
->bytes
);
763 /* we borrow this routine from libffi (it must be changed, though, to
764 * actually call the function passed in the first argument. as of
765 * libffi-1.20, this is not the case.)
769 ffi_raw_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, ffi_raw
*fake_avalue
)
772 void **avalue
= (void **)fake_avalue
;
775 ecif
.avalue
= avalue
;
777 /* If the return value is a struct and we don't have a return */
778 /* value address then we need to make one */
781 && (cif
->flags
== FFI_TYPE_STRUCT
782 || cif
->flags
== FFI_TYPE_MS_STRUCT
))
784 ecif
.rvalue
= alloca(cif
->rtype
->size
);
787 ecif
.rvalue
= rvalue
;
796 ffi_call_win32(ffi_prep_args_raw
, &ecif
, cif
->abi
, cif
->bytes
, cif
->flags
,
802 unsigned int abi
= cif
->abi
;
803 unsigned int i
, passed_regs
= 0;
805 if (cif
->flags
== FFI_TYPE_STRUCT
)
808 for (i
=0; i
< cif
->nargs
&& passed_regs
< 2;i
++)
812 if (cif
->arg_types
[i
]->type
== FFI_TYPE_FLOAT
813 || cif
->arg_types
[i
]->type
== FFI_TYPE_STRUCT
)
815 sz
= (cif
->arg_types
[i
]->size
+ 3) & ~3;
816 if (sz
== 0 || sz
> 4)
820 if (passed_regs
< 2 && abi
== FFI_FASTCALL
)
821 cif
->abi
= abi
= FFI_THISCALL
;
822 if (passed_regs
< 1 && abi
== FFI_THISCALL
)
823 cif
->abi
= abi
= FFI_STDCALL
;
824 ffi_call_win32(ffi_prep_args_raw
, &ecif
, abi
, cif
->bytes
, cif
->flags
,
830 ffi_call_SYSV(ffi_prep_args_raw
, &ecif
, cif
->bytes
, cif
->flags
,
842 #endif /* !__x86_64__ || X86_WIN64 */