x86: Remove some conditional compilation
[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 /* ??? This should be a different ABI rather than an ifdef. */
221 if (cif->rtype->size == 1)
222 cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
223 else if (cif->rtype->size == 2)
224 cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
225 else if (cif->rtype->size == 4)
226 cif->flags = FFI_TYPE_INT; /* same as int type */
227 else if (cif->rtype->size == 8)
228 cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
229 else
230 #endif
231 {
232 if (cif->abi == FFI_MS_CDECL)
233 cif->flags = FFI_TYPE_MS_STRUCT;
234 else
235 cif->flags = FFI_TYPE_STRUCT;
236 /* Allocate space for return value pointer. */
237 cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
238 }
239 break;
240
241 default:
242 cif->flags = FFI_TYPE_INT;
243 break;
244 }
245
246 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
247 {
248 if (((*ptr)->alignment - 1) & cif->bytes)
249 cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
250 cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
251 }
252
253 if (cif->abi == FFI_SYSV)
254 cif->bytes = ALIGN (cif->bytes, 15);
255
256 return FFI_OK;
257 }
258
259 extern void
260 ffi_call_win32(unsigned int (*)(char *, extended_cif *), extended_cif *,
261 unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
262 extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
263 unsigned, unsigned, unsigned *, void (*fn)(void));
264
265 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
266 {
267 extended_cif ecif;
268
269 ecif.cif = cif;
270 ecif.avalue = avalue;
271
272 /* If the return value is a struct and we don't have a return */
273 /* value address then we need to make one */
274
275 if (rvalue == NULL
276 && (cif->flags == FFI_TYPE_STRUCT
277 || cif->flags == FFI_TYPE_MS_STRUCT))
278 {
279 ecif.rvalue = alloca(cif->rtype->size);
280 }
281 else
282 ecif.rvalue = rvalue;
283
284
285 switch (cif->abi)
286 {
287 #ifndef X86_WIN32
288 case FFI_SYSV:
289 ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
290 fn);
291 break;
292 #else
293 case FFI_SYSV:
294 case FFI_MS_CDECL:
295 #endif
296 case FFI_STDCALL:
297 case FFI_THISCALL:
298 case FFI_FASTCALL:
299 case FFI_PASCAL:
300 case FFI_REGISTER:
301 ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
302 ecif.rvalue, fn);
303 break;
304 default:
305 FFI_ASSERT(0);
306 break;
307 }
308 }
309
310
311 /** private members **/
312
313 /* The following __attribute__((regparm(1))) decorations will have no effect
314 on MSVC or SUNPRO_C -- standard conventions apply. */
315 static unsigned int ffi_prep_incoming_args (char *stack, void **ret,
316 void** args, ffi_cif* cif);
317 void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
318 __attribute__ ((regparm(1)));
319 unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
320 __attribute__ ((regparm(1)));
321 unsigned int FFI_HIDDEN ffi_closure_WIN32_inner (ffi_closure *, void **, void *)
322 __attribute__ ((regparm(1)));
323 void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
324 __attribute__ ((regparm(1)));
325 #ifdef X86_WIN32
326 void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
327 __attribute__ ((regparm(1)));
328 #endif
329 void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *);
330 void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *);
331 void FFI_HIDDEN ffi_closure_FASTCALL (ffi_closure *);
332 void FFI_HIDDEN ffi_closure_REGISTER (ffi_closure *);
333
334 /* This function is jumped to by the trampoline */
335
336 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
337 ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
338 {
339 /* our various things... */
340 ffi_cif *cif;
341 void **arg_area;
342
343 cif = closure->cif;
344 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
345
346 /* this call will initialize ARG_AREA, such that each
347 * element in that array points to the corresponding
348 * value on the stack; and if the function returns
349 * a structure, it will change RESP to point to the
350 * structure return address. */
351
352 ffi_prep_incoming_args(args, respp, arg_area, cif);
353
354 (closure->fun) (cif, *respp, arg_area, closure->user_data);
355
356 return cif->flags;
357 }
358
359 unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
360 ffi_closure_WIN32_inner (ffi_closure *closure, void **respp, void *args)
361 {
362 /* our various things... */
363 ffi_cif *cif;
364 void **arg_area;
365 unsigned int ret;
366
367 cif = closure->cif;
368 arg_area = (void**) alloca (cif->nargs * sizeof (void*));
369
370 /* this call will initialize ARG_AREA, such that each
371 * element in that array points to the corresponding
372 * value on the stack; and if the function returns
373 * a structure, it will change RESP to point to the
374 * structure return address. */
375
376 ret = ffi_prep_incoming_args(args, respp, arg_area, cif);
377
378 (closure->fun) (cif, *respp, arg_area, closure->user_data);
379
380 return ret;
381 }
382
383 static unsigned int
384 ffi_prep_incoming_args(char *stack, void **rvalue, void **avalue,
385 ffi_cif *cif)
386 {
387 register unsigned int i;
388 register void **p_argv;
389 register char *argp;
390 register ffi_type **p_arg;
391 const int cabi = cif->abi;
392 const int dir = (cabi == FFI_PASCAL || cabi == FFI_REGISTER) ? -1 : +1;
393 const unsigned int max_stack_count = (cabi == FFI_THISCALL) ? 1
394 : (cabi == FFI_FASTCALL) ? 2
395 : (cabi == FFI_REGISTER) ? 3
396 : 0;
397 unsigned int passed_regs = 0;
398 void *p_stack_data[3] = { stack - 1 };
399
400 argp = stack;
401 argp += max_stack_count * FFI_SIZEOF_ARG;
402
403 if ((cif->flags == FFI_TYPE_STRUCT
404 || cif->flags == FFI_TYPE_MS_STRUCT))
405 {
406 if (passed_regs < max_stack_count)
407 {
408 *rvalue = *(void**) (stack + (passed_regs*FFI_SIZEOF_ARG));
409 ++passed_regs;
410 }
411 else
412 {
413 *rvalue = *(void **) argp;
414 argp += sizeof(void *);
415 }
416 }
417
418 /* Do register arguments first */
419 for (i = 0, p_arg = cif->arg_types;
420 i < cif->nargs && passed_regs < max_stack_count;
421 i++, p_arg++)
422 {
423 if ((*p_arg)->type == FFI_TYPE_FLOAT
424 || (*p_arg)->type == FFI_TYPE_STRUCT)
425 continue;
426
427 size_t sz = (*p_arg)->size;
428 if(sz == 0 || sz > FFI_SIZEOF_ARG)
429 continue;
430
431 p_stack_data[passed_regs] = avalue + i;
432 avalue[i] = stack + (passed_regs*FFI_SIZEOF_ARG);
433 ++passed_regs;
434 }
435
436 p_arg = cif->arg_types;
437 p_argv = avalue;
438 if (dir < 0)
439 {
440 const int nargs = cif->nargs - 1;
441 if (nargs > 0)
442 {
443 p_arg += nargs;
444 p_argv += nargs;
445 }
446 }
447
448 for (i = cif->nargs;
449 i != 0;
450 i--, p_arg += dir, p_argv += dir)
451 {
452 /* Align if necessary */
453 if ((sizeof(void*) - 1) & (size_t) argp)
454 argp = (char *) ALIGN(argp, sizeof(void*));
455
456 size_t z = (*p_arg)->size;
457
458 if (passed_regs > 0
459 && z <= FFI_SIZEOF_ARG
460 && (p_argv == p_stack_data[0]
461 || p_argv == p_stack_data[1]
462 || p_argv == p_stack_data[2]))
463 {
464 /* Already assigned a register value */
465 continue;
466 }
467 else
468 {
469 /* because we're little endian, this is what it turns into. */
470 *p_argv = (void*) argp;
471 }
472
473 argp += z;
474 }
475
476 return (size_t)argp - (size_t)stack;
477 }
478
479 /* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
480
481 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
482 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
483 unsigned int __fun = (unsigned int)(FUN); \
484 unsigned int __ctx = (unsigned int)(CTX); \
485 unsigned int __dis = __fun - (__ctx + 10); \
486 *(unsigned char*) &__tramp[0] = 0xb8; \
487 *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
488 *(unsigned char*) &__tramp[5] = 0xe9; \
489 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
490 }
491
492 #define FFI_INIT_TRAMPOLINE_RAW_THISCALL(TRAMP,FUN,CTX,SIZE) \
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 + 49); \
497 unsigned short __size = (unsigned short)(SIZE); \
498 *(unsigned int *) &__tramp[0] = 0x8324048b; /* mov (%esp), %eax */ \
499 *(unsigned int *) &__tramp[4] = 0x4c890cec; /* sub $12, %esp */ \
500 *(unsigned int *) &__tramp[8] = 0x04890424; /* mov %ecx, 4(%esp) */ \
501 *(unsigned char*) &__tramp[12] = 0x24; /* mov %eax, (%esp) */ \
502 *(unsigned char*) &__tramp[13] = 0xb8; \
503 *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
504 *(unsigned int *) &__tramp[18] = 0x08244c8d; /* lea 8(%esp), %ecx */ \
505 *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
506 *(unsigned short*) &__tramp[26] = 0x0b74; /* jz 1f */ \
507 *(unsigned int *) &__tramp[28] = 0x8908518b; /* 2b: mov 8(%ecx), %edx */ \
508 *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
509 *(unsigned char*) &__tramp[36] = 0x48; /* dec %eax */ \
510 *(unsigned short*) &__tramp[37] = 0xf575; /* jnz 2b ; 1f: */ \
511 *(unsigned char*) &__tramp[39] = 0xb8; \
512 *(unsigned int*) &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
513 *(unsigned char *) &__tramp[44] = 0xe8; \
514 *(unsigned int*) &__tramp[45] = __dis; /* call __fun */ \
515 *(unsigned char*) &__tramp[49] = 0xc2; /* ret */ \
516 *(unsigned short*) &__tramp[50] = (__size + 8); /* ret (__size + 8) */ \
517 }
518
519 #define FFI_INIT_TRAMPOLINE_WIN32(TRAMP,FUN,CTX) \
520 { unsigned char *__tramp = (unsigned char*)(TRAMP); \
521 unsigned int __fun = (unsigned int)(FUN); \
522 unsigned int __ctx = (unsigned int)(CTX); \
523 unsigned int __dis = __fun - (__ctx + 10); \
524 *(unsigned char*) &__tramp[0] = 0x68; \
525 *(unsigned int*) &__tramp[1] = __ctx; /* push __ctx */ \
526 *(unsigned char*) &__tramp[5] = 0xe9; \
527 *(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
528 }
529
530 /* the cif must already be prep'ed */
531
532 ffi_status
533 ffi_prep_closure_loc (ffi_closure* closure,
534 ffi_cif* cif,
535 void (*fun)(ffi_cif*,void*,void**,void*),
536 void *user_data,
537 void *codeloc)
538 {
539 if (cif->abi == FFI_SYSV)
540 {
541 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
542 &ffi_closure_SYSV,
543 (void*)codeloc);
544 }
545 else if (cif->abi == FFI_REGISTER)
546 {
547 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
548 &ffi_closure_REGISTER,
549 (void*)codeloc);
550 }
551 else if (cif->abi == FFI_FASTCALL)
552 {
553 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
554 &ffi_closure_FASTCALL,
555 (void*)codeloc);
556 }
557 else if (cif->abi == FFI_THISCALL)
558 {
559 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
560 &ffi_closure_THISCALL,
561 (void*)codeloc);
562 }
563 else if (cif->abi == FFI_STDCALL || cif->abi == FFI_PASCAL)
564 {
565 FFI_INIT_TRAMPOLINE_WIN32 (&closure->tramp[0],
566 &ffi_closure_STDCALL,
567 (void*)codeloc);
568 }
569 else if (cif->abi == FFI_MS_CDECL)
570 {
571 FFI_INIT_TRAMPOLINE (&closure->tramp[0],
572 &ffi_closure_SYSV,
573 (void*)codeloc);
574 }
575 else
576 {
577 return FFI_BAD_ABI;
578 }
579
580 closure->cif = cif;
581 closure->user_data = user_data;
582 closure->fun = fun;
583
584 return FFI_OK;
585 }
586
587 /* ------- Native raw API support -------------------------------- */
588
589 #if !FFI_NO_RAW_API
590
591 ffi_status
592 ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
593 ffi_cif* cif,
594 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
595 void *user_data,
596 void *codeloc)
597 {
598 int i;
599
600 /* We currently don't support certain kinds of arguments for raw
601 closures. This should be implemented by a separate assembly
602 language routine, since it would require argument processing,
603 something we don't do now for performance. */
604 for (i = cif->nargs-1; i >= 0; i--)
605 {
606 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
607 FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
608 }
609
610 switch (cif->abi)
611 {
612 #ifdef X86_WIN32
613 case FFI_THISCALL:
614 FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0],
615 &ffi_closure_raw_THISCALL,
616 codeloc, cif->bytes);
617 break;
618 #endif
619 case FFI_SYSV:
620 FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
621 codeloc);
622 break;
623 default:
624 return FFI_BAD_ABI;
625 }
626
627 closure->cif = cif;
628 closure->fun = fun;
629 closure->user_data = user_data;
630
631 return FFI_OK;
632 }
633
634 static unsigned int
635 ffi_prep_args_raw(char *stack, extended_cif *ecif)
636 {
637 const ffi_cif *cif = ecif->cif;
638 unsigned int i, passed_regs = 0;
639
640 const unsigned int abi = cif->abi;
641 const unsigned int max_regs = (abi == FFI_THISCALL) ? 1
642 : (abi == FFI_FASTCALL) ? 2
643 : (abi == FFI_REGISTER) ? 3
644 : 0;
645
646 if (cif->flags == FFI_TYPE_STRUCT)
647 ++passed_regs;
648
649 for (i = 0; i < cif->nargs && passed_regs <= max_regs; i++)
650 {
651 if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
652 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
653 continue;
654
655 size_t sz = cif->arg_types[i]->size;
656 if (sz == 0 || sz > FFI_SIZEOF_ARG)
657 continue;
658
659 ++passed_regs;
660 }
661
662 memcpy (stack, ecif->avalue, cif->bytes);
663 return passed_regs;
664 }
665
666 /* we borrow this routine from libffi (it must be changed, though, to
667 * actually call the function passed in the first argument. as of
668 * libffi-1.20, this is not the case.)
669 */
670
671 void
672 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
673 {
674 extended_cif ecif;
675 void **avalue = (void **)fake_avalue;
676
677 ecif.cif = cif;
678 ecif.avalue = avalue;
679
680 /* If the return value is a struct and we don't have a return */
681 /* value address then we need to make one */
682
683 if (rvalue == NULL
684 && (cif->flags == FFI_TYPE_STRUCT
685 || cif->flags == FFI_TYPE_MS_STRUCT))
686 {
687 ecif.rvalue = alloca(cif->rtype->size);
688 }
689 else
690 ecif.rvalue = rvalue;
691
692
693 switch (cif->abi)
694 {
695 #ifndef X86_WIN32
696 case FFI_SYSV:
697 ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
698 ecif.rvalue, fn);
699 break;
700 #else
701 case FFI_SYSV:
702 case FFI_MS_CDECL:
703 #endif
704 case FFI_STDCALL:
705 case FFI_THISCALL:
706 case FFI_FASTCALL:
707 case FFI_PASCAL:
708 case FFI_REGISTER:
709 ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
710 ecif.rvalue, fn);
711 break;
712 default:
713 FFI_ASSERT(0);
714 break;
715 }
716 }
717 #endif /* !FFI_NO_RAW_API */
718 #endif /* !__x86_64__ */