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