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