Update LOCAL_PATCHES after libsanitizer merge.
[official-gcc.git] / libffi / src / x86 / darwin_c.c
blob6338de2a0f227b261fc6bce737b509c21c4ebe22
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__)
33 #ifdef _WIN64
34 #include <windows.h>
35 #endif
37 #include <ffi.h>
38 #include <ffi_common.h>
40 #include <stdlib.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;
49 register char *argp;
50 register ffi_type **p_arg;
51 #ifdef X86_WIN32
52 size_t p_stack_args[2];
53 void *p_stack_data[2];
54 char *argp2 = stack;
55 int stack_args_count = 0;
56 int cabi = ecif->cif->abi;
57 #endif
59 argp = stack;
61 if ((ecif->cif->flags == FFI_TYPE_STRUCT
62 || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
63 #ifdef X86_WIN64
64 && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
65 && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
66 #endif
69 *(void **) argp = ecif->rvalue;
70 #ifdef X86_WIN32
71 /* For fastcall/thiscall this is first register-passed
72 argument. */
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;
77 ++stack_args_count;
79 #endif
80 argp += sizeof(void*);
83 p_argv = ecif->avalue;
85 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
86 i != 0;
87 i--, p_arg++)
89 size_t z;
91 /* Align if necessary */
92 if ((sizeof(void*) - 1) & (size_t) argp)
93 argp = (char *) ALIGN(argp, sizeof(void*));
95 z = (*p_arg)->size;
96 #ifdef X86_WIN64
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)
102 #endif
105 z = sizeof(ffi_arg);
106 *(void **)argp = *p_argv;
108 else if ((*p_arg)->type == FFI_TYPE_FLOAT)
110 memcpy(argp, *p_argv, z);
112 else
113 #endif
114 if (z < sizeof(ffi_arg))
116 z = sizeof(ffi_arg);
117 switch ((*p_arg)->type)
119 case FFI_TYPE_SINT8:
120 *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
121 break;
123 case FFI_TYPE_UINT8:
124 *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
125 break;
127 case FFI_TYPE_SINT16:
128 *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
129 break;
131 case FFI_TYPE_UINT16:
132 *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
133 break;
135 case FFI_TYPE_SINT32:
136 *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
137 break;
139 case FFI_TYPE_UINT32:
140 *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
141 break;
143 case FFI_TYPE_STRUCT:
144 *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
145 break;
147 default:
148 FFI_ASSERT(0);
151 else
153 memcpy(argp, *p_argv, z);
156 #ifdef X86_WIN32
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))
163 if (z <= 4
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;
169 ++stack_args_count;
172 #endif
173 p_argv++;
174 #ifdef X86_WIN64
175 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
176 #else
177 argp += z;
178 #endif
181 #ifdef X86_WIN32
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
184 call-handler. */
185 if (stack_args_count > 0)
187 size_t zz = (p_stack_args[0] + 3) & ~3;
188 char *h;
190 /* Move first argument to top-stack position. */
191 if (p_stack_data[0] != argp2)
193 h = alloca (zz + 1);
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);
200 argp2 += zz;
201 --stack_args_count;
202 if (zz > 4)
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];
210 zz = (zz + 3) & ~3;
211 h = alloca (zz + 1);
212 h = alloca (zz + 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);
218 #endif
219 return;
222 /* Perform machine dependent cif processing */
223 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
225 unsigned int i;
226 ffi_type **ptr;
228 /* Set the return type flag */
229 switch (cif->rtype->type)
231 case FFI_TYPE_VOID:
232 case FFI_TYPE_UINT8:
233 case FFI_TYPE_UINT16:
234 case FFI_TYPE_SINT8:
235 case FFI_TYPE_SINT16:
236 #ifdef X86_WIN64
237 case FFI_TYPE_UINT32:
238 case FFI_TYPE_SINT32:
239 #endif
240 case FFI_TYPE_SINT64:
241 case FFI_TYPE_FLOAT:
242 case FFI_TYPE_DOUBLE:
243 #ifndef X86_WIN64
244 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
245 case FFI_TYPE_LONGDOUBLE:
246 #endif
247 #endif
248 cif->flags = (unsigned) cif->rtype->type;
249 break;
251 case FFI_TYPE_UINT64:
252 #ifdef X86_WIN64
253 case FFI_TYPE_POINTER:
254 #endif
255 cif->flags = FFI_TYPE_SINT64;
256 break;
258 case FFI_TYPE_STRUCT:
259 #ifndef X86
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)
270 #ifdef X86_WIN64
271 cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
272 #else
273 cif->flags = FFI_TYPE_INT; /* same as int type */
274 #endif
276 else if (cif->rtype->size == 8)
278 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
280 else
281 #endif
283 #ifdef X86_WIN32
284 if (cif->abi == FFI_MS_CDECL)
285 cif->flags = FFI_TYPE_MS_STRUCT;
286 else
287 #endif
288 cif->flags = FFI_TYPE_STRUCT;
289 /* allocate space for return value pointer */
290 cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
292 break;
294 default:
295 #ifdef X86_WIN64
296 cif->flags = FFI_TYPE_SINT64;
297 break;
298 case FFI_TYPE_INT:
299 cif->flags = FFI_TYPE_SINT32;
300 #else
301 cif->flags = FFI_TYPE_INT;
302 #endif
303 break;
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);
313 #ifdef X86_WIN64
314 /* ensure space for storing four registers */
315 cif->bytes += 4 * sizeof(ffi_arg);
316 #endif
318 #ifdef X86_DARWIN
319 cif->bytes = (cif->bytes + 15) & ~0xF;
320 #endif
322 return FFI_OK;
325 #ifdef X86_WIN64
326 extern int
327 ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
328 unsigned, unsigned, unsigned *, void (*fn)(void));
329 #elif defined(X86_WIN32)
330 extern void
331 ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
332 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
333 #else
334 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
335 unsigned, unsigned, unsigned *, void (*fn)(void));
336 #endif
338 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
340 extended_cif ecif;
342 ecif.cif = cif;
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 */
348 #ifdef X86_WIN64
349 if (rvalue == NULL
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);
356 #else
357 if (rvalue == NULL
358 && (cif->flags == FFI_TYPE_STRUCT
359 || cif->flags == FFI_TYPE_MS_STRUCT))
361 ecif.rvalue = alloca(cif->rtype->size);
363 #endif
364 else
365 ecif.rvalue = rvalue;
368 switch (cif->abi)
370 #ifdef X86_WIN64
371 case FFI_WIN64:
372 ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
373 cif->flags, ecif.rvalue, fn);
374 break;
375 #elif defined(X86_WIN32)
376 case FFI_SYSV:
377 case FFI_STDCALL:
378 case FFI_MS_CDECL:
379 ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
380 ecif.rvalue, fn);
381 break;
382 case FFI_THISCALL:
383 case FFI_FASTCALL:
385 unsigned int abi = cif->abi;
386 unsigned int i, passed_regs = 0;
388 if (cif->flags == FFI_TYPE_STRUCT)
389 ++passed_regs;
391 for (i=0; i < cif->nargs && passed_regs < 2;i++)
393 size_t sz;
395 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
396 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
397 continue;
398 sz = (cif->arg_types[i]->size + 3) & ~3;
399 if (sz == 0 || sz > 4)
400 continue;
401 ++passed_regs;
403 if (passed_regs < 2 && abi == FFI_FASTCALL)
404 abi = FFI_THISCALL;
405 if (passed_regs < 1 && abi == FFI_THISCALL)
406 abi = FFI_STDCALL;
407 ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
408 ecif.rvalue, fn);
410 break;
411 #else
412 case FFI_SYSV:
413 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
414 fn);
415 break;
416 #endif
417 default:
418 FFI_ASSERT(0);
419 break;
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)));
436 #ifdef X86_WIN32
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)));
443 #endif
444 #ifdef X86_WIN64
445 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
446 #endif
448 /* This function is jumped to by the trampoline */
450 #ifdef X86_WIN64
451 void * FFI_HIDDEN
452 ffi_closure_win64_inner (ffi_closure *closure, void *args) {
453 ffi_cif *cif;
454 void **arg_area;
455 void *result;
456 void *resp = &result;
458 cif = closure->cif;
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;
479 #else
480 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
481 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
483 /* our various things... */
484 ffi_cif *cif;
485 void **arg_area;
487 cif = closure->cif;
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);
500 return cif->flags;
502 #endif /* !X86_WIN64 */
504 static void
505 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
506 ffi_cif *cif)
508 register unsigned int i;
509 register void **p_argv;
510 register char *argp;
511 register ffi_type **p_arg;
513 argp = stack;
515 #ifdef X86_WIN64
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 *);
523 #else
524 if ( cif->flags == FFI_TYPE_STRUCT
525 || cif->flags == FFI_TYPE_MS_STRUCT ) {
526 *rvalue = *(void **) argp;
527 argp += sizeof(void *);
529 #endif
531 p_argv = avalue;
533 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
535 size_t z;
537 /* Align if necessary */
538 if ((sizeof(void*) - 1) & (size_t) argp) {
539 argp = (char *) ALIGN(argp, sizeof(void*));
542 #ifdef X86_WIN64
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)))
548 z = sizeof(void *);
549 *p_argv = *(void **)argp;
551 else
552 #endif
554 z = (*p_arg)->size;
556 /* because we're little endian, this is what it turns into. */
558 *p_argv = (void*) argp;
561 p_argv++;
562 #ifdef X86_WIN64
563 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
564 #else
565 argp += z;
566 #endif
569 return;
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 */
646 ffi_status
647 ffi_prep_closure_loc (ffi_closure* closure,
648 ffi_cif* cif,
649 void (*fun)(ffi_cif*,void*,void**,void*),
650 void *user_data,
651 void *codeloc)
653 #ifdef X86_WIN64
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],
660 &ffi_closure_win64,
661 codeloc, mask);
662 /* make sure we can execute here */
664 #else
665 if (cif->abi == FFI_SYSV)
667 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
668 &ffi_closure_SYSV,
669 (void*)codeloc);
671 #ifdef X86_WIN32
672 else if (cif->abi == FFI_THISCALL)
674 FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
675 &ffi_closure_THISCALL,
676 (void*)codeloc,
677 cif->bytes);
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],
688 &ffi_closure_SYSV,
689 (void*)codeloc);
691 #endif /* X86_WIN32 */
692 #endif /* !X86_WIN64 */
693 else
695 return FFI_BAD_ABI;
698 closure->cif = cif;
699 closure->user_data = user_data;
700 closure->fun = fun;
702 return FFI_OK;
705 /* ------- Native raw API support -------------------------------- */
707 #if !FFI_NO_RAW_API
709 ffi_status
710 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
711 ffi_cif* cif,
712 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
713 void *user_data,
714 void *codeloc)
716 int i;
718 if (cif->abi != FFI_SYSV) {
719 #ifdef X86_WIN32
720 if (cif->abi != FFI_THISCALL)
721 #endif
722 return FFI_BAD_ABI;
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);
736 #ifdef X86_WIN32
737 if (cif->abi == FFI_SYSV)
739 #endif
740 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
741 codeloc);
742 #ifdef X86_WIN32
744 else if (cif->abi == FFI_THISCALL)
746 FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
747 codeloc, cif->bytes);
749 #endif
750 closure->cif = cif;
751 closure->user_data = user_data;
752 closure->fun = fun;
754 return FFI_OK;
757 static void
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.)
768 void
769 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
771 extended_cif ecif;
772 void **avalue = (void **)fake_avalue;
774 ecif.cif = cif;
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 */
780 if (rvalue == NULL
781 && (cif->flags == FFI_TYPE_STRUCT
782 || cif->flags == FFI_TYPE_MS_STRUCT))
784 ecif.rvalue = alloca(cif->rtype->size);
786 else
787 ecif.rvalue = rvalue;
790 switch (cif->abi)
792 #ifdef X86_WIN32
793 case FFI_SYSV:
794 case FFI_STDCALL:
795 case FFI_MS_CDECL:
796 ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
797 ecif.rvalue, fn);
798 break;
799 case FFI_THISCALL:
800 case FFI_FASTCALL:
802 unsigned int abi = cif->abi;
803 unsigned int i, passed_regs = 0;
805 if (cif->flags == FFI_TYPE_STRUCT)
806 ++passed_regs;
808 for (i=0; i < cif->nargs && passed_regs < 2;i++)
810 size_t sz;
812 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
813 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
814 continue;
815 sz = (cif->arg_types[i]->size + 3) & ~3;
816 if (sz == 0 || sz > 4)
817 continue;
818 ++passed_regs;
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,
825 ecif.rvalue, fn);
827 break;
828 #else
829 case FFI_SYSV:
830 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
831 ecif.rvalue, fn);
832 break;
833 #endif
834 default:
835 FFI_ASSERT(0);
836 break;
840 #endif
842 #endif /* !__x86_64__ || X86_WIN64 */