1 /* -----------------------------------------------------------------------
2 ffi.c - Copyright (c) 2017 Anthony Green
3 Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc.
4 Copyright (c) 2002 Ranjit Mathew
5 Copyright (c) 2002 Bo Thorsen
6 Copyright (c) 2002 Roger Sayle
7 Copyright (C) 2008, 2010 Free Software Foundation, Inc.
8
9 x86 Foreign Function Interface
10
11 Permission is hereby granted, free of charge, to any person obtaining
12 a copy of this software and associated documentation files (the
13 ``Software''), to deal in the Software without restriction, including
14 without limitation the rights to use, copy, modify, merge, publish,
15 distribute, sublicense, and/or sell copies of the Software, and to
16 permit persons to whom the Software is furnished to do so, subject to
17 the following conditions:
18
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 DEALINGS IN THE SOFTWARE.
30 ----------------------------------------------------------------------- */
31
32 #if defined(__i386__) || defined(_M_IX86)
33 #include <ffi.h>
34 #include <ffi_common.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include "internal.h"
38
39 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
40 all further uses in this file will refer to the 80-bit type. */
41 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
42 # if FFI_TYPE_LONGDOUBLE != 4
43 # error FFI_TYPE_LONGDOUBLE out of date
44 # endif
45 #else
46 # undef FFI_TYPE_LONGDOUBLE
47 # define FFI_TYPE_LONGDOUBLE 4
48 #endif
49
50 #if defined(__GNUC__) && !defined(__declspec)
51 # define __declspec(x) __attribute__((x))
52 #endif
53
54 #if defined(_MSC_VER) && defined(_M_IX86)
55 /* Stack is not 16-byte aligned on Windows. */
56 #define STACK_ALIGN(bytes) (bytes)
57 #else
58 #define STACK_ALIGN(bytes) FFI_ALIGN (bytes, 16)
59 #endif
60
61 /* Perform machine dependent cif processing. */
62 ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif * cif)63 ffi_prep_cif_machdep(ffi_cif *cif)
64 {
65 size_t bytes = 0;
66 int i, n, flags, cabi = cif->abi;
67
68 switch (cabi)
69 {
70 case FFI_SYSV:
71 case FFI_STDCALL:
72 case FFI_THISCALL:
73 case FFI_FASTCALL:
74 case FFI_MS_CDECL:
75 case FFI_PASCAL:
76 case FFI_REGISTER:
77 break;
78 default:
79 return FFI_BAD_ABI;
80 }
81
82 switch (cif->rtype->type)
83 {
84 case FFI_TYPE_VOID:
85 flags = X86_RET_VOID;
86 break;
87 case FFI_TYPE_FLOAT:
88 flags = X86_RET_FLOAT;
89 break;
90 case FFI_TYPE_DOUBLE:
91 flags = X86_RET_DOUBLE;
92 break;
93 case FFI_TYPE_LONGDOUBLE:
94 flags = X86_RET_LDOUBLE;
95 break;
96 case FFI_TYPE_UINT8:
97 flags = X86_RET_UINT8;
98 break;
99 case FFI_TYPE_UINT16:
100 flags = X86_RET_UINT16;
101 break;
102 case FFI_TYPE_SINT8:
103 flags = X86_RET_SINT8;
104 break;
105 case FFI_TYPE_SINT16:
106 flags = X86_RET_SINT16;
107 break;
108 case FFI_TYPE_INT:
109 case FFI_TYPE_SINT32:
110 case FFI_TYPE_UINT32:
111 case FFI_TYPE_POINTER:
112 flags = X86_RET_INT32;
113 break;
114 case FFI_TYPE_SINT64:
115 case FFI_TYPE_UINT64:
116 flags = X86_RET_INT64;
117 break;
118 case FFI_TYPE_STRUCT:
119 #ifndef X86
120 /* ??? This should be a different ABI rather than an ifdef. */
121 if (cif->rtype->size == 1)
122 flags = X86_RET_STRUCT_1B;
123 else if (cif->rtype->size == 2)
124 flags = X86_RET_STRUCT_2B;
125 else if (cif->rtype->size == 4)
126 flags = X86_RET_INT32;
127 else if (cif->rtype->size == 8)
128 flags = X86_RET_INT64;
129 else
130 #endif
131 {
132 do_struct:
133 switch (cabi)
134 {
135 case FFI_THISCALL:
136 case FFI_FASTCALL:
137 case FFI_STDCALL:
138 case FFI_MS_CDECL:
139 flags = X86_RET_STRUCTARG;
140 break;
141 default:
142 flags = X86_RET_STRUCTPOP;
143 break;
144 }
145 /* Allocate space for return value pointer. */
146 bytes += FFI_ALIGN (sizeof(void*), FFI_SIZEOF_ARG);
147 }
148 break;
149 case FFI_TYPE_COMPLEX:
150 switch (cif->rtype->elements[0]->type)
151 {
152 case FFI_TYPE_DOUBLE:
153 case FFI_TYPE_LONGDOUBLE:
154 case FFI_TYPE_SINT64:
155 case FFI_TYPE_UINT64:
156 goto do_struct;
157 case FFI_TYPE_FLOAT:
158 case FFI_TYPE_INT:
159 case FFI_TYPE_SINT32:
160 case FFI_TYPE_UINT32:
161 flags = X86_RET_INT64;
162 break;
163 case FFI_TYPE_SINT16:
164 case FFI_TYPE_UINT16:
165 flags = X86_RET_INT32;
166 break;
167 case FFI_TYPE_SINT8:
168 case FFI_TYPE_UINT8:
169 flags = X86_RET_STRUCT_2B;
170 break;
171 default:
172 return FFI_BAD_TYPEDEF;
173 }
174 break;
175 default:
176 return FFI_BAD_TYPEDEF;
177 }
178 cif->flags = flags;
179
180 for (i = 0, n = cif->nargs; i < n; i++)
181 {
182 ffi_type *t = cif->arg_types[i];
183
184 bytes = FFI_ALIGN (bytes, t->alignment);
185 bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG);
186 }
187 cif->bytes = bytes;
188
189 return FFI_OK;
190 }
191
192 static ffi_arg
extend_basic_type(void * arg,int type)193 extend_basic_type(void *arg, int type)
194 {
195 switch (type)
196 {
197 case FFI_TYPE_SINT8:
198 return *(SINT8 *)arg;
199 case FFI_TYPE_UINT8:
200 return *(UINT8 *)arg;
201 case FFI_TYPE_SINT16:
202 return *(SINT16 *)arg;
203 case FFI_TYPE_UINT16:
204 return *(UINT16 *)arg;
205
206 case FFI_TYPE_SINT32:
207 case FFI_TYPE_UINT32:
208 case FFI_TYPE_POINTER:
209 case FFI_TYPE_FLOAT:
210 return *(UINT32 *)arg;
211
212 default:
213 abort();
214 }
215 }
216
217 struct call_frame
218 {
219 void *ebp; /* 0 */
220 void *retaddr; /* 4 */
221 void (*fn)(void); /* 8 */
222 int flags; /* 12 */
223 void *rvalue; /* 16 */
224 unsigned regs[3]; /* 20-28 */
225 };
226
227 struct abi_params
228 {
229 int dir; /* parameter growth direction */
230 int static_chain; /* the static chain register used by gcc */
231 int nregs; /* number of register parameters */
232 int regs[3];
233 };
234
235 static const struct abi_params abi_params[FFI_LAST_ABI] = {
236 [FFI_SYSV] = { 1, R_ECX, 0 },
237 [FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } },
238 [FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } },
239 [FFI_STDCALL] = { 1, R_ECX, 0 },
240 [FFI_PASCAL] = { -1, R_ECX, 0 },
241 /* ??? No defined static chain; gcc does not support REGISTER. */
242 [FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } },
243 [FFI_MS_CDECL] = { 1, R_ECX, 0 }
244 };
245
246 #ifdef HAVE_FASTCALL
247 #ifdef _MSC_VER
248 #define FFI_DECLARE_FASTCALL __fastcall
249 #else
250 #define FFI_DECLARE_FASTCALL __declspec(fastcall)
251 #endif
252 #else
253 #define FFI_DECLARE_FASTCALL
254 #endif
255
256 extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN;
257
258 static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)259 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
260 void **avalue, void *closure)
261 {
262 size_t rsize, bytes;
263 struct call_frame *frame;
264 char *stack, *argp;
265 ffi_type **arg_types;
266 int flags, cabi, i, n, dir, narg_reg;
267 const struct abi_params *pabi;
268
269 flags = cif->flags;
270 cabi = cif->abi;
271 pabi = &abi_params[cabi];
272 dir = pabi->dir;
273
274 rsize = 0;
275 if (rvalue == NULL)
276 {
277 switch (flags)
278 {
279 case X86_RET_FLOAT:
280 case X86_RET_DOUBLE:
281 case X86_RET_LDOUBLE:
282 case X86_RET_STRUCTPOP:
283 case X86_RET_STRUCTARG:
284 /* The float cases need to pop the 387 stack.
285 The struct cases need to pass a valid pointer to the callee. */
286 rsize = cif->rtype->size;
287 break;
288 default:
289 /* We can pretend that the callee returns nothing. */
290 flags = X86_RET_VOID;
291 break;
292 }
293 }
294
295 bytes = STACK_ALIGN (cif->bytes);
296 stack = alloca(bytes + sizeof(*frame) + rsize);
297 argp = (dir < 0 ? stack + bytes : stack);
298 frame = (struct call_frame *)(stack + bytes);
299 if (rsize)
300 rvalue = frame + 1;
301
302 frame->fn = fn;
303 frame->flags = flags;
304 frame->rvalue = rvalue;
305 frame->regs[pabi->static_chain] = (unsigned)closure;
306
307 narg_reg = 0;
308 switch (flags)
309 {
310 case X86_RET_STRUCTARG:
311 /* The pointer is passed as the first argument. */
312 if (pabi->nregs > 0)
313 {
314 frame->regs[pabi->regs[0]] = (unsigned)rvalue;
315 narg_reg = 1;
316 break;
317 }
318 /* fallthru */
319 case X86_RET_STRUCTPOP:
320 *(void **)argp = rvalue;
321 argp += sizeof(void *);
322 break;
323 }
324
325 arg_types = cif->arg_types;
326 for (i = 0, n = cif->nargs; i < n; i++)
327 {
328 ffi_type *ty = arg_types[i];
329 void *valp = avalue[i];
330 size_t z = ty->size;
331 int t = ty->type;
332
333 if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
334 {
335 ffi_arg val = extend_basic_type (valp, t);
336
337 if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
338 frame->regs[pabi->regs[narg_reg++]] = val;
339 else if (dir < 0)
340 {
341 argp -= 4;
342 *(ffi_arg *)argp = val;
343 }
344 else
345 {
346 *(ffi_arg *)argp = val;
347 argp += 4;
348 }
349 }
350 else
351 {
352 size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG);
353 size_t align = FFI_SIZEOF_ARG;
354
355 /* Issue 434: For thiscall and fastcall, if the paramter passed
356 as 64-bit integer or struct, all following integer paramters
357 will be passed on stack. */
358 if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
359 && (t == FFI_TYPE_SINT64
360 || t == FFI_TYPE_UINT64
361 || t == FFI_TYPE_STRUCT))
362 narg_reg = 2;
363
364 /* Alignment rules for arguments are quite complex. Vectors and
365 structures with 16 byte alignment get it. Note that long double
366 on Darwin does have 16 byte alignment, and does not get this
367 alignment if passed directly; a structure with a long double
368 inside, however, would get 16 byte alignment. Since libffi does
369 not support vectors, we need non concern ourselves with other
370 cases. */
371 if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
372 align = 16;
373
374 if (dir < 0)
375 {
376 /* ??? These reverse argument ABIs are probably too old
377 to have cared about alignment. Someone should check. */
378 argp -= za;
379 memcpy (argp, valp, z);
380 }
381 else
382 {
383 argp = (char *)FFI_ALIGN (argp, align);
384 memcpy (argp, valp, z);
385 argp += za;
386 }
387 }
388 }
389 FFI_ASSERT (dir > 0 || argp == stack);
390
391 ffi_call_i386 (frame, stack);
392 }
393
394 void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)395 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
396 {
397 ffi_call_int (cif, fn, rvalue, avalue, NULL);
398 }
399
400 void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)401 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
402 void **avalue, void *closure)
403 {
404 ffi_call_int (cif, fn, rvalue, avalue, closure);
405 }
406
407 /** private members **/
408
409 void FFI_HIDDEN ffi_closure_i386(void);
410 void FFI_HIDDEN ffi_closure_STDCALL(void);
411 void FFI_HIDDEN ffi_closure_REGISTER(void);
412
413 struct closure_frame
414 {
415 unsigned rettemp[4]; /* 0 */
416 unsigned regs[3]; /* 16-24 */
417 ffi_cif *cif; /* 28 */
418 void (*fun)(ffi_cif*,void*,void**,void*); /* 32 */
419 void *user_data; /* 36 */
420 };
421
422 int FFI_HIDDEN FFI_DECLARE_FASTCALL
ffi_closure_inner(struct closure_frame * frame,char * stack)423 ffi_closure_inner (struct closure_frame *frame, char *stack)
424 {
425 ffi_cif *cif = frame->cif;
426 int cabi, i, n, flags, dir, narg_reg;
427 const struct abi_params *pabi;
428 ffi_type **arg_types;
429 char *argp;
430 void *rvalue;
431 void **avalue;
432
433 cabi = cif->abi;
434 flags = cif->flags;
435 narg_reg = 0;
436 rvalue = frame->rettemp;
437 pabi = &abi_params[cabi];
438 dir = pabi->dir;
439 argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack);
440
441 switch (flags)
442 {
443 case X86_RET_STRUCTARG:
444 if (pabi->nregs > 0)
445 {
446 rvalue = (void *)frame->regs[pabi->regs[0]];
447 narg_reg = 1;
448 frame->rettemp[0] = (unsigned)rvalue;
449 break;
450 }
451 /* fallthru */
452 case X86_RET_STRUCTPOP:
453 rvalue = *(void **)argp;
454 argp += sizeof(void *);
455 frame->rettemp[0] = (unsigned)rvalue;
456 break;
457 }
458
459 n = cif->nargs;
460 avalue = alloca(sizeof(void *) * n);
461
462 arg_types = cif->arg_types;
463 for (i = 0; i < n; ++i)
464 {
465 ffi_type *ty = arg_types[i];
466 size_t z = ty->size;
467 int t = ty->type;
468 void *valp;
469
470 if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
471 {
472 if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
473 valp = &frame->regs[pabi->regs[narg_reg++]];
474 else if (dir < 0)
475 {
476 argp -= 4;
477 valp = argp;
478 }
479 else
480 {
481 valp = argp;
482 argp += 4;
483 }
484 }
485 else
486 {
487 size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG);
488 size_t align = FFI_SIZEOF_ARG;
489
490 /* See the comment in ffi_call_int. */
491 if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
492 align = 16;
493
494 /* Issue 434: For thiscall and fastcall, if the paramter passed
495 as 64-bit integer or struct, all following integer paramters
496 will be passed on stack. */
497 if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
498 && (t == FFI_TYPE_SINT64
499 || t == FFI_TYPE_UINT64
500 || t == FFI_TYPE_STRUCT))
501 narg_reg = 2;
502
503 if (dir < 0)
504 {
505 /* ??? These reverse argument ABIs are probably too old
506 to have cared about alignment. Someone should check. */
507 argp -= za;
508 valp = argp;
509 }
510 else
511 {
512 argp = (char *)FFI_ALIGN (argp, align);
513 valp = argp;
514 argp += za;
515 }
516 }
517
518 avalue[i] = valp;
519 }
520
521 frame->fun (cif, rvalue, avalue, frame->user_data);
522
523 if (cabi == FFI_STDCALL)
524 return flags + (cif->bytes << X86_RET_POP_SHIFT);
525 else
526 return flags;
527 }
528
529 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)530 ffi_prep_closure_loc (ffi_closure* closure,
531 ffi_cif* cif,
532 void (*fun)(ffi_cif*,void*,void**,void*),
533 void *user_data,
534 void *codeloc)
535 {
536 char *tramp = closure->tramp;
537 void (*dest)(void);
538 int op = 0xb8; /* movl imm, %eax */
539
540 switch (cif->abi)
541 {
542 case FFI_SYSV:
543 case FFI_THISCALL:
544 case FFI_FASTCALL:
545 case FFI_MS_CDECL:
546 dest = ffi_closure_i386;
547 break;
548 case FFI_STDCALL:
549 case FFI_PASCAL:
550 dest = ffi_closure_STDCALL;
551 break;
552 case FFI_REGISTER:
553 dest = ffi_closure_REGISTER;
554 op = 0x68; /* pushl imm */
555 break;
556 default:
557 return FFI_BAD_ABI;
558 }
559
560 /* movl or pushl immediate. */
561 tramp[0] = op;
562 *(void **)(tramp + 1) = codeloc;
563
564 /* jmp dest */
565 tramp[5] = 0xe9;
566 *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
567
568 closure->cif = cif;
569 closure->fun = fun;
570 closure->user_data = user_data;
571
572 return FFI_OK;
573 }
574
575 void FFI_HIDDEN ffi_go_closure_EAX(void);
576 void FFI_HIDDEN ffi_go_closure_ECX(void);
577 void FFI_HIDDEN ffi_go_closure_STDCALL(void);
578
579 ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))580 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
581 void (*fun)(ffi_cif*,void*,void**,void*))
582 {
583 void (*dest)(void);
584
585 switch (cif->abi)
586 {
587 case FFI_SYSV:
588 case FFI_MS_CDECL:
589 dest = ffi_go_closure_ECX;
590 break;
591 case FFI_THISCALL:
592 case FFI_FASTCALL:
593 dest = ffi_go_closure_EAX;
594 break;
595 case FFI_STDCALL:
596 case FFI_PASCAL:
597 dest = ffi_go_closure_STDCALL;
598 break;
599 case FFI_REGISTER:
600 default:
601 return FFI_BAD_ABI;
602 }
603
604 closure->tramp = dest;
605 closure->cif = cif;
606 closure->fun = fun;
607
608 return FFI_OK;
609 }
610
611 /* ------- Native raw API support -------------------------------- */
612
613 #if !FFI_NO_RAW_API
614
615 void FFI_HIDDEN ffi_closure_raw_SYSV(void);
616 void FFI_HIDDEN ffi_closure_raw_THISCALL(void);
617
618 ffi_status
ffi_prep_raw_closure_loc(ffi_raw_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,ffi_raw *,void *),void * user_data,void * codeloc)619 ffi_prep_raw_closure_loc (ffi_raw_closure *closure,
620 ffi_cif *cif,
621 void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
622 void *user_data,
623 void *codeloc)
624 {
625 char *tramp = closure->tramp;
626 void (*dest)(void);
627 int i;
628
629 /* We currently don't support certain kinds of arguments for raw
630 closures. This should be implemented by a separate assembly
631 language routine, since it would require argument processing,
632 something we don't do now for performance. */
633 for (i = cif->nargs-1; i >= 0; i--)
634 switch (cif->arg_types[i]->type)
635 {
636 case FFI_TYPE_STRUCT:
637 case FFI_TYPE_LONGDOUBLE:
638 return FFI_BAD_TYPEDEF;
639 }
640
641 switch (cif->abi)
642 {
643 case FFI_THISCALL:
644 dest = ffi_closure_raw_THISCALL;
645 break;
646 case FFI_SYSV:
647 dest = ffi_closure_raw_SYSV;
648 break;
649 default:
650 return FFI_BAD_ABI;
651 }
652
653 /* movl imm, %eax. */
654 tramp[0] = 0xb8;
655 *(void **)(tramp + 1) = codeloc;
656
657 /* jmp dest */
658 tramp[5] = 0xe9;
659 *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
660
661 closure->cif = cif;
662 closure->fun = fun;
663 closure->user_data = user_data;
664
665 return FFI_OK;
666 }
667
668 void
ffi_raw_call(ffi_cif * cif,void (* fn)(void),void * rvalue,ffi_raw * avalue)669 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
670 {
671 size_t rsize, bytes;
672 struct call_frame *frame;
673 char *stack, *argp;
674 ffi_type **arg_types;
675 int flags, cabi, i, n, narg_reg;
676 const struct abi_params *pabi;
677
678 flags = cif->flags;
679 cabi = cif->abi;
680 pabi = &abi_params[cabi];
681
682 rsize = 0;
683 if (rvalue == NULL)
684 {
685 switch (flags)
686 {
687 case X86_RET_FLOAT:
688 case X86_RET_DOUBLE:
689 case X86_RET_LDOUBLE:
690 case X86_RET_STRUCTPOP:
691 case X86_RET_STRUCTARG:
692 /* The float cases need to pop the 387 stack.
693 The struct cases need to pass a valid pointer to the callee. */
694 rsize = cif->rtype->size;
695 break;
696 default:
697 /* We can pretend that the callee returns nothing. */
698 flags = X86_RET_VOID;
699 break;
700 }
701 }
702
703 bytes = STACK_ALIGN (cif->bytes);
704 argp = stack =
705 (void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16);
706 frame = (struct call_frame *)(stack + bytes);
707 if (rsize)
708 rvalue = frame + 1;
709
710 frame->fn = fn;
711 frame->flags = flags;
712 frame->rvalue = rvalue;
713
714 narg_reg = 0;
715 switch (flags)
716 {
717 case X86_RET_STRUCTARG:
718 /* The pointer is passed as the first argument. */
719 if (pabi->nregs > 0)
720 {
721 frame->regs[pabi->regs[0]] = (unsigned)rvalue;
722 narg_reg = 1;
723 break;
724 }
725 /* fallthru */
726 case X86_RET_STRUCTPOP:
727 *(void **)argp = rvalue;
728 argp += sizeof(void *);
729 bytes -= sizeof(void *);
730 break;
731 }
732
733 arg_types = cif->arg_types;
734 for (i = 0, n = cif->nargs; narg_reg < pabi->nregs && i < n; i++)
735 {
736 ffi_type *ty = arg_types[i];
737 size_t z = ty->size;
738 int t = ty->type;
739
740 if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT && t != FFI_TYPE_FLOAT)
741 {
742 ffi_arg val = extend_basic_type (avalue, t);
743 frame->regs[pabi->regs[narg_reg++]] = val;
744 z = FFI_SIZEOF_ARG;
745 }
746 else
747 {
748 memcpy (argp, avalue, z);
749 z = FFI_ALIGN (z, FFI_SIZEOF_ARG);
750 argp += z;
751 }
752 avalue += z;
753 bytes -= z;
754 }
755 if (i < n)
756 memcpy (argp, avalue, bytes);
757
758 ffi_call_i386 (frame, stack);
759 }
760 #endif /* !FFI_NO_RAW_API */
761 #endif /* __i386__ */
762