]> git.ipfire.org Git - thirdparty/gcc.git/blame - libffi/src/x86/darwin_c.c
libffi: Add HOWTO_MERGE, autogen.sh and merge.sh
[thirdparty/gcc.git] / libffi / src / x86 / darwin_c.c
CommitLineData
b1760f7f
RH
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.
7
8 x86 Foreign Function Interface
9
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:
17
18 The above copyright notice and this permission notice shall be included
19 in all copies or substantial portions of the Software.
20
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 ----------------------------------------------------------------------- */
30
31#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__)
32
33#ifdef _WIN64
34#include <windows.h>
35#endif
36
37#include <ffi.h>
38#include <ffi_common.h>
39
40#include <stdlib.h>
41
42/* ffi_prep_args is called by the assembly routine once stack space
43 has been allocated for the function's arguments */
44
45void ffi_prep_args(char *stack, extended_cif *ecif)
46{
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
58
59 argp = stack;
60
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
67 )
68 {
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)
74 {
75 p_stack_args[stack_args_count] = sizeof (void*);
76 p_stack_data[stack_args_count] = argp;
77 ++stack_args_count;
78 }
79#endif
80 argp += sizeof(void*);
81 }
82
83 p_argv = ecif->avalue;
84
85 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
86 i != 0;
87 i--, p_arg++)
88 {
89 size_t z;
90
91 /* Align if necessary */
92 if ((sizeof(void*) - 1) & (size_t) argp)
93 argp = (char *) ALIGN(argp, sizeof(void*));
94
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
103 )
104 {
105 z = sizeof(ffi_arg);
106 *(void **)argp = *p_argv;
107 }
108 else if ((*p_arg)->type == FFI_TYPE_FLOAT)
109 {
110 memcpy(argp, *p_argv, z);
111 }
112 else
113#endif
114 if (z < sizeof(ffi_arg))
115 {
116 z = sizeof(ffi_arg);
117 switch ((*p_arg)->type)
118 {
119 case FFI_TYPE_SINT8:
120 *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
121 break;
122
123 case FFI_TYPE_UINT8:
124 *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
125 break;
126
127 case FFI_TYPE_SINT16:
128 *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
129 break;
130
131 case FFI_TYPE_UINT16:
132 *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
133 break;
134
135 case FFI_TYPE_SINT32:
136 *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
137 break;
138
139 case FFI_TYPE_UINT32:
140 *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
141 break;
142
143 case FFI_TYPE_STRUCT:
144 *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
145 break;
146
147 default:
148 FFI_ASSERT(0);
149 }
150 }
151 else
152 {
153 memcpy(argp, *p_argv, z);
154 }
155
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))
162 {
163 if (z <= 4
164 && ((*p_arg)->type != FFI_TYPE_FLOAT
165 && (*p_arg)->type != FFI_TYPE_STRUCT))
166 {
167 p_stack_args[stack_args_count] = z;
168 p_stack_data[stack_args_count] = argp;
169 ++stack_args_count;
170 }
171 }
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
179 }
180
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)
186 {
187 size_t zz = (p_stack_args[0] + 3) & ~3;
188 char *h;
189
190 /* Move first argument to top-stack position. */
191 if (p_stack_data[0] != argp2)
192 {
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);
198 }
199
200 argp2 += zz;
201 --stack_args_count;
202 if (zz > 4)
203 stack_args_count = 0;
204
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)
208 {
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);
216 }
217 }
218#endif
219 return;
220}
221
222/* Perform machine dependent cif processing */
223ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
224{
225 unsigned int i;
226 ffi_type **ptr;
227
228 /* Set the return type flag */
229 switch (cif->rtype->type)
230 {
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;
250
251 case FFI_TYPE_UINT64:
252#ifdef X86_WIN64
253 case FFI_TYPE_POINTER:
254#endif
255 cif->flags = FFI_TYPE_SINT64;
256 break;
257
258 case FFI_TYPE_STRUCT:
259#ifndef X86
260 if (cif->rtype->size == 1)
261 {
262 cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
263 }
264 else if (cif->rtype->size == 2)
265 {
266 cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
267 }
268 else if (cif->rtype->size == 4)
269 {
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
275 }
276 else if (cif->rtype->size == 8)
277 {
278 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
279 }
280 else
281#endif
282 {
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);
291 }
292 break;
293
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;
304 }
305
306 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
307 {
308 if (((*ptr)->alignment - 1) & cif->bytes)
309 cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
310 cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
311 }
312
313#ifdef X86_WIN64
314 /* ensure space for storing four registers */
315 cif->bytes += 4 * sizeof(ffi_arg);
316#endif
317
318#ifdef X86_DARWIN
319 cif->bytes = (cif->bytes + 15) & ~0xF;
320#endif
321
322 return FFI_OK;
323}
324
325#ifdef X86_WIN64
326extern int
327ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
328 unsigned, unsigned, unsigned *, void (*fn)(void));
329#elif defined(X86_WIN32)
330extern void
331ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
332 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
333#else
334extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
335 unsigned, unsigned, unsigned *, void (*fn)(void));
336#endif
337
338void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
339{
340 extended_cif ecif;
341
342 ecif.cif = cif;
343 ecif.avalue = avalue;
344
345 /* If the return value is a struct and we don't have a return */
346 /* value address then we need to make one */
347
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)
353 {
354 ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
355 }
356#else
357 if (rvalue == NULL
358 && (cif->flags == FFI_TYPE_STRUCT
359 || cif->flags == FFI_TYPE_MS_STRUCT))
360 {
361 ecif.rvalue = alloca(cif->rtype->size);
362 }
363#endif
364 else
365 ecif.rvalue = rvalue;
366
367
368 switch (cif->abi)
369 {
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:
384 {
385 unsigned int abi = cif->abi;
386 unsigned int i, passed_regs = 0;
387
388 if (cif->flags == FFI_TYPE_STRUCT)
389 ++passed_regs;
390
391 for (i=0; i < cif->nargs && passed_regs < 2;i++)
392 {
393 size_t sz;
394
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;
402 }
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);
409 }
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;
420 }
421}
422
423
424/** private members **/
425
426/* The following __attribute__((regparm(1))) decorations will have no effect
427 on MSVC - standard cdecl convention applies. */
428static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
429 void** args, ffi_cif* cif);
430void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
431 __attribute__ ((regparm(1)));
432unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
433 __attribute__ ((regparm(1)));
434void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
435 __attribute__ ((regparm(1)));
436#ifdef X86_WIN32
437void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
438 __attribute__ ((regparm(1)));
439void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
440 __attribute__ ((regparm(1)));
441void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
442 __attribute__ ((regparm(1)));
443#endif
444#ifdef X86_WIN64
445void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
446#endif
447
448/* This function is jumped to by the trampoline */
449
450#ifdef X86_WIN64
451void * FFI_HIDDEN
452ffi_closure_win64_inner (ffi_closure *closure, void *args) {
453 ffi_cif *cif;
454 void **arg_area;
455 void *result;
456 void *resp = &result;
457
458 cif = closure->cif;
459 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
460
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. */
466
467 ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
468
469 (closure->fun) (cif, resp, arg_area, closure->user_data);
470
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!!!
475 */
476 return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
477}
478
479#else
480unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
481ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
482{
483 /* our various things... */
484 ffi_cif *cif;
485 void **arg_area;
486
487 cif = closure->cif;
488 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
489
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. */
495
496 ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
497
498 (closure->fun) (cif, *respp, arg_area, closure->user_data);
499
500 return cif->flags;
501}
502#endif /* !X86_WIN64 */
503
504static void
505ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
506 ffi_cif *cif)
507{
508 register unsigned int i;
509 register void **p_argv;
510 register char *argp;
511 register ffi_type **p_arg;
512
513 argp = stack;
514
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 *);
522 }
523#else
524 if ( cif->flags == FFI_TYPE_STRUCT
525 || cif->flags == FFI_TYPE_MS_STRUCT ) {
526 *rvalue = *(void **) argp;
527 argp += sizeof(void *);
528 }
529#endif
530
531 p_argv = avalue;
532
533 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
534 {
535 size_t z;
536
537 /* Align if necessary */
538 if ((sizeof(void*) - 1) & (size_t) argp) {
539 argp = (char *) ALIGN(argp, sizeof(void*));
540 }
541
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)))
547 {
548 z = sizeof(void *);
549 *p_argv = *(void **)argp;
550 }
551 else
552#endif
553 {
554 z = (*p_arg)->size;
555
556 /* because we're little endian, this is what it turns into. */
557
558 *p_argv = (void*) argp;
559 }
560
561 p_argv++;
562#ifdef X86_WIN64
563 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
564#else
565 argp += z;
566#endif
567 }
568
569 return;
570}
571
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 */ \
588 }
589
590/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
591
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 */ \
601 }
602
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) */ \
628 }
629
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 */ \
642 }
643
644/* the cif must already be prep'ed */
645
646ffi_status
647ffi_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)
652{
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)
657 {
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 */
663 }
664#else
665 if (cif->abi == FFI_SYSV)
666 {
667 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
668 &ffi_closure_SYSV,
669 (void*)codeloc);
670 }
671#ifdef X86_WIN32
672 else if (cif->abi == FFI_THISCALL)
673 {
674 FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
675 &ffi_closure_THISCALL,
676 (void*)codeloc,
677 cif->bytes);
678 }
679 else if (cif->abi == FFI_STDCALL)
680 {
681 FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
682 &ffi_closure_STDCALL,
683 (void*)codeloc, cif->bytes);
684 }
685 else if (cif->abi == FFI_MS_CDECL)
686 {
687 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
688 &ffi_closure_SYSV,
689 (void*)codeloc);
690 }
691#endif /* X86_WIN32 */
692#endif /* !X86_WIN64 */
693 else
694 {
695 return FFI_BAD_ABI;
696 }
697
698 closure->cif = cif;
699 closure->user_data = user_data;
700 closure->fun = fun;
701
702 return FFI_OK;
703}
704
705/* ------- Native raw API support -------------------------------- */
706
707#if !FFI_NO_RAW_API
708
709ffi_status
710ffi_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)
715{
716 int i;
717
718 if (cif->abi != FFI_SYSV) {
719#ifdef X86_WIN32
720 if (cif->abi != FFI_THISCALL)
721#endif
722 return FFI_BAD_ABI;
723 }
724
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. */
729
730 for (i = cif->nargs-1; i >= 0; i--)
731 {
732 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
733 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
734 }
735
736#ifdef X86_WIN32
737 if (cif->abi == FFI_SYSV)
738 {
739#endif
740 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
741 codeloc);
742#ifdef X86_WIN32
743 }
744 else if (cif->abi == FFI_THISCALL)
745 {
746 FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
747 codeloc, cif->bytes);
748 }
749#endif
750 closure->cif = cif;
751 closure->user_data = user_data;
752 closure->fun = fun;
753
754 return FFI_OK;
755}
756
757static void
758ffi_prep_args_raw(char *stack, extended_cif *ecif)
759{
760 memcpy (stack, ecif->avalue, ecif->cif->bytes);
761}
762
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.)
766 */
767
768void
769ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
770{
771 extended_cif ecif;
772 void **avalue = (void **)fake_avalue;
773
774 ecif.cif = cif;
775 ecif.avalue = avalue;
776
777 /* If the return value is a struct and we don't have a return */
778 /* value address then we need to make one */
779
780 if (rvalue == NULL
781 && (cif->flags == FFI_TYPE_STRUCT
782 || cif->flags == FFI_TYPE_MS_STRUCT))
783 {
784 ecif.rvalue = alloca(cif->rtype->size);
785 }
786 else
787 ecif.rvalue = rvalue;
788
789
790 switch (cif->abi)
791 {
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:
801 {
802 unsigned int abi = cif->abi;
803 unsigned int i, passed_regs = 0;
804
805 if (cif->flags == FFI_TYPE_STRUCT)
806 ++passed_regs;
807
808 for (i=0; i < cif->nargs && passed_regs < 2;i++)
809 {
810 size_t sz;
811
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;
819 }
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);
826 }
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;
837 }
838}
839
840#endif
841
842#endif /* !__x86_64__ || X86_WIN64 */
843