c5f962c8cd9cad20c9c840c0cfb1a5a73d7f25e7
[libffi.git] / src / x86 / ffi.c
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)
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
45 void 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 #ifdef X86_WIN64
63 && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
64 && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
65 #endif
66 )
67 {
68 *(void **) argp = ecif->rvalue;
69 #ifdef X86_WIN32
70 /* For fastcall/thiscall this is first register-passed
71 argument. */
72 if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
73 {
74 p_stack_args[stack_args_count] = sizeof (void*);
75 p_stack_data[stack_args_count] = argp;
76 ++stack_args_count;
77 }
78 #endif
79 argp += sizeof(void*);
80 }
81
82 p_argv = ecif->avalue;
83
84 for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
85 i != 0;
86 i--, p_arg++)
87 {
88 size_t z;
89
90 /* Align if necessary */
91 if ((sizeof(void*) - 1) & (size_t) argp)
92 argp = (char *) ALIGN(argp, sizeof(void*));
93
94 z = (*p_arg)->size;
95 #ifdef X86_WIN64
96 if (z > sizeof(ffi_arg)
97 || ((*p_arg)->type == FFI_TYPE_STRUCT
98 && (z != 1 && z != 2 && z != 4 && z != 8))
99 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
100 || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
101 #endif
102 )
103 {
104 z = sizeof(ffi_arg);
105 *(void **)argp = *p_argv;
106 }
107 else if ((*p_arg)->type == FFI_TYPE_FLOAT)
108 {
109 memcpy(argp, *p_argv, z);
110 }
111 else
112 #endif
113 if (z < sizeof(ffi_arg))
114 {
115 z = sizeof(ffi_arg);
116 switch ((*p_arg)->type)
117 {
118 case FFI_TYPE_SINT8:
119 *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
120 break;
121
122 case FFI_TYPE_UINT8:
123 *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
124 break;
125
126 case FFI_TYPE_SINT16:
127 *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
128 break;
129
130 case FFI_TYPE_UINT16:
131 *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
132 break;
133
134 case FFI_TYPE_SINT32:
135 *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
136 break;
137
138 case FFI_TYPE_UINT32:
139 *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
140 break;
141
142 case FFI_TYPE_STRUCT:
143 *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
144 break;
145
146 default:
147 FFI_ASSERT(0);
148 }
149 }
150 else
151 {
152 memcpy(argp, *p_argv, z);
153 }
154
155 #ifdef X86_WIN32
156 /* For thiscall/fastcall convention register-passed arguments
157 are the first two none-floating-point arguments with a size
158 smaller or equal to sizeof (void*). */
159 if ((cabi == FFI_THISCALL && stack_args_count < 1)
160 || (cabi == FFI_FASTCALL && stack_args_count < 2))
161 {
162 if (z <= 4
163 && ((*p_arg)->type != FFI_TYPE_FLOAT
164 && (*p_arg)->type != FFI_TYPE_STRUCT))
165 {
166 p_stack_args[stack_args_count] = z;
167 p_stack_data[stack_args_count] = argp;
168 ++stack_args_count;
169 }
170 }
171 #endif
172 p_argv++;
173 #ifdef X86_WIN64
174 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
175 #else
176 argp += z;
177 #endif
178 }
179
180 #ifdef X86_WIN32
181 /* We need to move the register-passed arguments for thiscall/fastcall
182 on top of stack, so that those can be moved to registers ecx/edx by
183 call-handler. */
184 if (stack_args_count > 0)
185 {
186 size_t zz = (p_stack_args[0] + 3) & ~3;
187 char *h;
188
189 /* Move first argument to top-stack position. */
190 if (p_stack_data[0] != argp2)
191 {
192 h = alloca (zz + 1);
193 memcpy (h, p_stack_data[0], zz);
194 memmove (argp2 + zz, argp2,
195 (size_t) ((char *) p_stack_data[0] - (char*)argp2));
196 memcpy (argp2, h, zz);
197 }
198
199 argp2 += zz;
200 --stack_args_count;
201 if (zz > 4)
202 stack_args_count = 0;
203
204 /* If we have a second argument, then move it on top
205 after the first one. */
206 if (stack_args_count > 0 && p_stack_data[1] != argp2)
207 {
208 zz = p_stack_args[1];
209 zz = (zz + 3) & ~3;
210 h = alloca (zz + 1);
211 h = alloca (zz + 1);
212 memcpy (h, p_stack_data[1], zz);
213 memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
214 memcpy (argp2, h, zz);
215 }
216 }
217 #endif
218 return;
219 }
220
221 /* Perform machine dependent cif processing */
222 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
223 {
224 unsigned int i;
225 ffi_type **ptr;
226
227 /* Set the return type flag */
228 switch (cif->rtype->type)
229 {
230 case FFI_TYPE_VOID:
231 case FFI_TYPE_UINT8:
232 case FFI_TYPE_UINT16:
233 case FFI_TYPE_SINT8:
234 case FFI_TYPE_SINT16:
235 #ifdef X86_WIN64
236 case FFI_TYPE_UINT32:
237 case FFI_TYPE_SINT32:
238 #endif
239 case FFI_TYPE_SINT64:
240 case FFI_TYPE_FLOAT:
241 case FFI_TYPE_DOUBLE:
242 #ifndef X86_WIN64
243 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
244 case FFI_TYPE_LONGDOUBLE:
245 #endif
246 #endif
247 cif->flags = (unsigned) cif->rtype->type;
248 break;
249
250 case FFI_TYPE_UINT64:
251 #ifdef X86_WIN64
252 case FFI_TYPE_POINTER:
253 #endif
254 cif->flags = FFI_TYPE_SINT64;
255 break;
256
257 case FFI_TYPE_STRUCT:
258 #ifndef X86
259 if (cif->rtype->size == 1)
260 {
261 cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
262 }
263 else if (cif->rtype->size == 2)
264 {
265 cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
266 }
267 else if (cif->rtype->size == 4)
268 {
269 #ifdef X86_WIN64
270 cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
271 #else
272 cif->flags = FFI_TYPE_INT; /* same as int type */
273 #endif
274 }
275 else if (cif->rtype->size == 8)
276 {
277 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
278 }
279 else
280 #endif
281 {
282 cif->flags = FFI_TYPE_STRUCT;
283 /* allocate space for return value pointer */
284 cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
285 }
286 break;
287
288 default:
289 #ifdef X86_WIN64
290 cif->flags = FFI_TYPE_SINT64;
291 break;
292 case FFI_TYPE_INT:
293 cif->flags = FFI_TYPE_SINT32;
294 #else
295 cif->flags = FFI_TYPE_INT;
296 #endif
297 break;
298 }
299
300 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
301 {
302 if (((*ptr)->alignment - 1) & cif->bytes)
303 cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
304 cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
305 }
306
307 #ifdef X86_WIN64
308 /* ensure space for storing four registers */
309 cif->bytes += 4 * sizeof(ffi_arg);
310 #endif
311
312 #ifdef X86_DARWIN
313 cif->bytes = (cif->bytes + 15) & ~0xF;
314 #endif
315
316 return FFI_OK;
317 }
318
319 #ifdef X86_WIN64
320 extern int
321 ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
322 unsigned, unsigned, unsigned *, void (*fn)(void));
323 #elif defined(X86_WIN32)
324 extern void
325 ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
326 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
327 #else
328 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
329 unsigned, unsigned, unsigned *, void (*fn)(void));
330 #endif
331
332 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
333 {
334 extended_cif ecif;
335
336 ecif.cif = cif;
337 ecif.avalue = avalue;
338
339 /* If the return value is a struct and we don't have a return */
340 /* value address then we need to make one */
341
342 #ifdef X86_WIN64
343 if (rvalue == NULL
344 && cif->flags == FFI_TYPE_STRUCT
345 && cif->rtype->size != 1 && cif->rtype->size != 2
346 && cif->rtype->size != 4 && cif->rtype->size != 8)
347 {
348 ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
349 }
350 #else
351 if (rvalue == NULL
352 && cif->flags == FFI_TYPE_STRUCT)
353 {
354 ecif.rvalue = alloca(cif->rtype->size);
355 }
356 #endif
357 else
358 ecif.rvalue = rvalue;
359
360
361 switch (cif->abi)
362 {
363 #ifdef X86_WIN64
364 case FFI_WIN64:
365 ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
366 cif->flags, ecif.rvalue, fn);
367 break;
368 #elif defined(X86_WIN32)
369 case FFI_SYSV:
370 case FFI_STDCALL:
371 ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
372 ecif.rvalue, fn);
373 break;
374 case FFI_THISCALL:
375 case FFI_FASTCALL:
376 {
377 unsigned int abi = cif->abi;
378 unsigned int i, passed_regs = 0;
379
380 if (cif->flags == FFI_TYPE_STRUCT)
381 ++passed_regs;
382
383 for (i=0; i < cif->nargs && passed_regs < 2;i++)
384 {
385 size_t sz;
386
387 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
388 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
389 continue;
390 sz = (cif->arg_types[i]->size + 3) & ~3;
391 if (sz == 0 || sz > 4)
392 continue;
393 ++passed_regs;
394 }
395 if (passed_regs < 2 && abi == FFI_FASTCALL)
396 abi = FFI_THISCALL;
397 if (passed_regs < 1 && abi == FFI_THISCALL)
398 abi = FFI_STDCALL;
399 ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
400 ecif.rvalue, fn);
401 }
402 break;
403 #else
404 case FFI_SYSV:
405 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
406 fn);
407 break;
408 #endif
409 default:
410 FFI_ASSERT(0);
411 break;
412 }
413 }
414
415
416 /** private members **/
417
418 /* The following __attribute__((regparm(1))) decorations will have no effect
419 on MSVC - standard cdecl convention applies. */
420 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
421 void** args, ffi_cif* cif);
422 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
423 __attribute__ ((regparm(1)));
424 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
425 __attribute__ ((regparm(1)));
426 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
427 __attribute__ ((regparm(1)));
428 #ifdef X86_WIN32
429 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
430 __attribute__ ((regparm(1)));
431 #endif
432 #ifdef X86_WIN64
433 void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
434 #endif
435
436 /* This function is jumped to by the trampoline */
437
438 #ifdef X86_WIN64
439 void * FFI_HIDDEN
440 ffi_closure_win64_inner (ffi_closure *closure, void *args) {
441 ffi_cif *cif;
442 void **arg_area;
443 void *result;
444 void *resp = &result;
445
446 cif = closure->cif;
447 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
448
449 /* this call will initialize ARG_AREA, such that each
450 * element in that array points to the corresponding
451 * value on the stack; and if the function returns
452 * a structure, it will change RESP to point to the
453 * structure return address. */
454
455 ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
456
457 (closure->fun) (cif, resp, arg_area, closure->user_data);
458
459 /* The result is returned in rax. This does the right thing for
460 result types except for floats; we have to 'mov xmm0, rax' in the
461 caller to correct this.
462 TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
463 */
464 return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
465 }
466
467 #else
468 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
469 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
470 {
471 /* our various things... */
472 ffi_cif *cif;
473 void **arg_area;
474
475 cif = closure->cif;
476 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
477
478 /* this call will initialize ARG_AREA, such that each
479 * element in that array points to the corresponding
480 * value on the stack; and if the function returns
481 * a structure, it will change RESP to point to the
482 * structure return address. */
483
484 ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
485
486 (closure->fun) (cif, *respp, arg_area, closure->user_data);
487
488 return cif->flags;
489 }
490 #endif /* !X86_WIN64 */
491
492 static void
493 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
494 ffi_cif *cif)
495 {
496 register unsigned int i;
497 register void **p_argv;
498 register char *argp;
499 register ffi_type **p_arg;
500
501 argp = stack;
502
503 #ifdef X86_WIN64
504 if (cif->rtype->size > sizeof(ffi_arg)
505 || (cif->flags == FFI_TYPE_STRUCT
506 && (cif->rtype->size != 1 && cif->rtype->size != 2
507 && cif->rtype->size != 4 && cif->rtype->size != 8))) {
508 *rvalue = *(void **) argp;
509 argp += sizeof(void *);
510 }
511 #else
512 if ( cif->flags == FFI_TYPE_STRUCT ) {
513 *rvalue = *(void **) argp;
514 argp += sizeof(void *);
515 }
516 #endif
517
518 p_argv = avalue;
519
520 for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
521 {
522 size_t z;
523
524 /* Align if necessary */
525 if ((sizeof(void*) - 1) & (size_t) argp) {
526 argp = (char *) ALIGN(argp, sizeof(void*));
527 }
528
529 #ifdef X86_WIN64
530 if ((*p_arg)->size > sizeof(ffi_arg)
531 || ((*p_arg)->type == FFI_TYPE_STRUCT
532 && ((*p_arg)->size != 1 && (*p_arg)->size != 2
533 && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
534 {
535 z = sizeof(void *);
536 *p_argv = *(void **)argp;
537 }
538 else
539 #endif
540 {
541 z = (*p_arg)->size;
542
543 /* because we're little endian, this is what it turns into. */
544
545 *p_argv = (void*) argp;
546 }
547
548 p_argv++;
549 #ifdef X86_WIN64
550 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
551 #else
552 argp += z;
553 #endif
554 }
555
556 return;
557 }
558
559 #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
560 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
561 void* __fun = (void*)(FUN); \
562 void* __ctx = (void*)(CTX); \
563 *(unsigned char*) &__tramp[0] = 0x41; \
564 *(unsigned char*) &__tramp[1] = 0xbb; \
565 *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
566 *(unsigned char*) &__tramp[6] = 0x48; \
567 *(unsigned char*) &__tramp[7] = 0xb8; \
568 *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
569 *(unsigned char *) &__tramp[16] = 0x49; \
570 *(unsigned char *) &__tramp[17] = 0xba; \
571 *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
572 *(unsigned char *) &__tramp[26] = 0x41; \
573 *(unsigned char *) &__tramp[27] = 0xff; \
574 *(unsigned char *) &__tramp[28] = 0xe2; /* jmp %r10 */ \
575 }
576
577 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
578
579 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
580 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
581 unsigned int __fun = (unsigned int)(FUN); \
582 unsigned int __ctx = (unsigned int)(CTX); \
583 unsigned int __dis = __fun - (__ctx + 10); \
584 *(unsigned char*) &__tramp[0] = 0xb8; \
585 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
586 *(unsigned char *) &__tramp[5] = 0xe9; \
587 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
588 }
589
590 #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE) \
591 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
592 unsigned int __fun = (unsigned int)(FUN); \
593 unsigned int __ctx = (unsigned int)(CTX); \
594 unsigned int __dis = __fun - (__ctx + 10); \
595 unsigned short __size = (unsigned short)(SIZE); \
596 *(unsigned char*) &__tramp[0] = 0xb8; \
597 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
598 *(unsigned char *) &__tramp[5] = 0xe8; \
599 *(unsigned int*) &__tramp[6] = __dis; /* call __fun */ \
600 *(unsigned char *) &__tramp[10] = 0xc2; \
601 *(unsigned short*) &__tramp[11] = __size; /* ret __size */ \
602 }
603
604 /* the cif must already be prep'ed */
605
606 ffi_status
607 ffi_prep_closure_loc (ffi_closure* closure,
608 ffi_cif* cif,
609 void (*fun)(ffi_cif*,void*,void**,void*),
610 void *user_data,
611 void *codeloc)
612 {
613 #ifdef X86_WIN64
614 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
615 #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
616 if (cif->abi == FFI_WIN64)
617 {
618 int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
619 FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
620 &ffi_closure_win64,
621 codeloc, mask);
622 /* make sure we can execute here */
623 }
624 #else
625 if (cif->abi == FFI_SYSV)
626 {
627 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
628 &ffi_closure_SYSV,
629 (void*)codeloc);
630 }
631 #ifdef X86_WIN32
632 else if (cif->abi == FFI_STDCALL)
633 {
634 FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
635 &ffi_closure_STDCALL,
636 (void*)codeloc, cif->bytes);
637 }
638 #endif /* X86_WIN32 */
639 #endif /* !X86_WIN64 */
640 else
641 {
642 return FFI_BAD_ABI;
643 }
644
645 closure->cif = cif;
646 closure->user_data = user_data;
647 closure->fun = fun;
648
649 return FFI_OK;
650 }
651
652 /* ------- Native raw API support -------------------------------- */
653
654 #if !FFI_NO_RAW_API
655
656 ffi_status
657 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
658 ffi_cif* cif,
659 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
660 void *user_data,
661 void *codeloc)
662 {
663 int i;
664
665 if (cif->abi != FFI_SYSV) {
666 return FFI_BAD_ABI;
667 }
668
669 /* we currently don't support certain kinds of arguments for raw
670 closures. This should be implemented by a separate assembly
671 language routine, since it would require argument processing,
672 something we don't do now for performance. */
673
674 for (i = cif->nargs-1; i >= 0; i--)
675 {
676 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
677 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
678 }
679
680
681 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
682 codeloc);
683
684 closure->cif = cif;
685 closure->user_data = user_data;
686 closure->fun = fun;
687
688 return FFI_OK;
689 }
690
691 static void
692 ffi_prep_args_raw(char *stack, extended_cif *ecif)
693 {
694 memcpy (stack, ecif->avalue, ecif->cif->bytes);
695 }
696
697 /* we borrow this routine from libffi (it must be changed, though, to
698 * actually call the function passed in the first argument. as of
699 * libffi-1.20, this is not the case.)
700 */
701
702 void
703 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
704 {
705 extended_cif ecif;
706 void **avalue = (void **)fake_avalue;
707
708 ecif.cif = cif;
709 ecif.avalue = avalue;
710
711 /* If the return value is a struct and we don't have a return */
712 /* value address then we need to make one */
713
714 if ((rvalue == NULL) &&
715 (cif->rtype->type == FFI_TYPE_STRUCT))
716 {
717 ecif.rvalue = alloca(cif->rtype->size);
718 }
719 else
720 ecif.rvalue = rvalue;
721
722
723 switch (cif->abi)
724 {
725 #ifdef X86_WIN32
726 case FFI_SYSV:
727 case FFI_STDCALL:
728 ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
729 ecif.rvalue, fn);
730 break;
731 case FFI_THISCALL:
732 case FFI_FASTCALL:
733 {
734 unsigned int abi = cif->abi;
735 unsigned int i, passed_regs = 0;
736
737 if (cif->flags == FFI_TYPE_STRUCT)
738 ++passed_regs;
739
740 for (i=0; i < cif->nargs && passed_regs < 2;i++)
741 {
742 size_t sz;
743
744 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
745 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
746 continue;
747 sz = (cif->arg_types[i]->size + 3) & ~3;
748 if (sz == 0 || sz > 4)
749 continue;
750 ++passed_regs;
751 }
752 if (passed_regs < 2 && abi == FFI_FASTCALL)
753 cif->abi = abi = FFI_THISCALL;
754 if (passed_regs < 1 && abi == FFI_THISCALL)
755 cif->abi = abi = FFI_STDCALL;
756 ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
757 ecif.rvalue, fn);
758 }
759 break;
760 #else
761 case FFI_SYSV:
762 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
763 ecif.rvalue, fn);
764 break;
765 #endif
766 default:
767 FFI_ASSERT(0);
768 break;
769 }
770 }
771
772 #endif
773
774 #endif /* !__x86_64__ || X86_WIN64 */
775