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 #ifndef __SANITIZE_ADDRESS__
259 # ifdef __clang__
260 #  if __has_feature(address_sanitizer)
261 #   define __SANITIZE_ADDRESS__
262 #  endif
263 # endif
264 #endif
265 #ifdef __SANITIZE_ADDRESS__
266 __attribute__((noinline,no_sanitize_address))
267 #endif
268 static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)269 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
270 	      void **avalue, void *closure)
271 {
272   size_t rsize, bytes;
273   struct call_frame *frame;
274   char *stack, *argp;
275   ffi_type **arg_types;
276   int flags, cabi, i, n, dir, narg_reg;
277   const struct abi_params *pabi;
278 
279   flags = cif->flags;
280   cabi = cif->abi;
281   pabi = &abi_params[cabi];
282   dir = pabi->dir;
283 
284   rsize = 0;
285   if (rvalue == NULL)
286     {
287       switch (flags)
288 	{
289 	case X86_RET_FLOAT:
290 	case X86_RET_DOUBLE:
291 	case X86_RET_LDOUBLE:
292 	case X86_RET_STRUCTPOP:
293 	case X86_RET_STRUCTARG:
294 	  /* The float cases need to pop the 387 stack.
295 	     The struct cases need to pass a valid pointer to the callee.  */
296 	  rsize = cif->rtype->size;
297 	  break;
298 	default:
299 	  /* We can pretend that the callee returns nothing.  */
300 	  flags = X86_RET_VOID;
301 	  break;
302 	}
303     }
304 
305   bytes = STACK_ALIGN (cif->bytes);
306   stack = alloca(bytes + sizeof(*frame) + rsize);
307   argp = (dir < 0 ? stack + bytes : stack);
308   frame = (struct call_frame *)(stack + bytes);
309   if (rsize)
310     rvalue = frame + 1;
311 
312   frame->fn = fn;
313   frame->flags = flags;
314   frame->rvalue = rvalue;
315   frame->regs[pabi->static_chain] = (unsigned)closure;
316 
317   narg_reg = 0;
318   switch (flags)
319     {
320     case X86_RET_STRUCTARG:
321       /* The pointer is passed as the first argument.  */
322       if (pabi->nregs > 0)
323 	{
324 	  frame->regs[pabi->regs[0]] = (unsigned)rvalue;
325 	  narg_reg = 1;
326 	  break;
327 	}
328       /* fallthru */
329     case X86_RET_STRUCTPOP:
330       *(void **)argp = rvalue;
331       argp += sizeof(void *);
332       break;
333     }
334 
335   arg_types = cif->arg_types;
336   for (i = 0, n = cif->nargs; i < n; i++)
337     {
338       ffi_type *ty = arg_types[i];
339       void *valp = avalue[i];
340       size_t z = ty->size;
341       int t = ty->type;
342 
343       if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
344         {
345 	  ffi_arg val = extend_basic_type (valp, t);
346 
347 	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
348 	    frame->regs[pabi->regs[narg_reg++]] = val;
349 	  else if (dir < 0)
350 	    {
351 	      argp -= 4;
352 	      *(ffi_arg *)argp = val;
353 	    }
354 	  else
355 	    {
356 	      *(ffi_arg *)argp = val;
357 	      argp += 4;
358 	    }
359 	}
360       else
361 	{
362 	  size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG);
363 	  size_t align = FFI_SIZEOF_ARG;
364 
365 	  /* Issue 434: For thiscall and fastcall, if the paramter passed
366 	     as 64-bit integer or struct, all following integer paramters
367 	     will be passed on stack.  */
368 	  if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
369 	      && (t == FFI_TYPE_SINT64
370 		  || t == FFI_TYPE_UINT64
371 		  || t == FFI_TYPE_STRUCT))
372 	    narg_reg = 2;
373 
374 	  /* Alignment rules for arguments are quite complex.  Vectors and
375 	     structures with 16 byte alignment get it.  Note that long double
376 	     on Darwin does have 16 byte alignment, and does not get this
377 	     alignment if passed directly; a structure with a long double
378 	     inside, however, would get 16 byte alignment.  Since libffi does
379 	     not support vectors, we need non concern ourselves with other
380 	     cases.  */
381 	  if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
382 	    align = 16;
383 
384 	  if (dir < 0)
385 	    {
386 	      /* ??? These reverse argument ABIs are probably too old
387 		 to have cared about alignment.  Someone should check.  */
388 	      argp -= za;
389 	      memcpy (argp, valp, z);
390 	    }
391 	  else
392 	    {
393 	      argp = (char *)FFI_ALIGN (argp, align);
394 	      memcpy (argp, valp, z);
395 	      argp += za;
396 	    }
397 	}
398     }
399   FFI_ASSERT (dir > 0 || argp == stack);
400 
401   ffi_call_i386 (frame, stack);
402 }
403 
404 void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)405 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
406 {
407   ffi_call_int (cif, fn, rvalue, avalue, NULL);
408 }
409 
410 void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)411 ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
412 	     void **avalue, void *closure)
413 {
414   ffi_call_int (cif, fn, rvalue, avalue, closure);
415 }
416 
417 /** private members **/
418 
419 void FFI_HIDDEN ffi_closure_i386(void);
420 void FFI_HIDDEN ffi_closure_STDCALL(void);
421 void FFI_HIDDEN ffi_closure_REGISTER(void);
422 
423 struct closure_frame
424 {
425   unsigned rettemp[4];				/* 0 */
426   unsigned regs[3];				/* 16-24 */
427   ffi_cif *cif;					/* 28 */
428   void (*fun)(ffi_cif*,void*,void**,void*);	/* 32 */
429   void *user_data;				/* 36 */
430 };
431 
432 int FFI_HIDDEN FFI_DECLARE_FASTCALL
ffi_closure_inner(struct closure_frame * frame,char * stack)433 ffi_closure_inner (struct closure_frame *frame, char *stack)
434 {
435   ffi_cif *cif = frame->cif;
436   int cabi, i, n, flags, dir, narg_reg;
437   const struct abi_params *pabi;
438   ffi_type **arg_types;
439   char *argp;
440   void *rvalue;
441   void **avalue;
442 
443   cabi = cif->abi;
444   flags = cif->flags;
445   narg_reg = 0;
446   rvalue = frame->rettemp;
447   pabi = &abi_params[cabi];
448   dir = pabi->dir;
449   argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack);
450 
451   switch (flags)
452     {
453     case X86_RET_STRUCTARG:
454       if (pabi->nregs > 0)
455 	{
456 	  rvalue = (void *)frame->regs[pabi->regs[0]];
457 	  narg_reg = 1;
458 	  frame->rettemp[0] = (unsigned)rvalue;
459 	  break;
460 	}
461       /* fallthru */
462     case X86_RET_STRUCTPOP:
463       rvalue = *(void **)argp;
464       argp += sizeof(void *);
465       frame->rettemp[0] = (unsigned)rvalue;
466       break;
467     }
468 
469   n = cif->nargs;
470   avalue = alloca(sizeof(void *) * n);
471 
472   arg_types = cif->arg_types;
473   for (i = 0; i < n; ++i)
474     {
475       ffi_type *ty = arg_types[i];
476       size_t z = ty->size;
477       int t = ty->type;
478       void *valp;
479 
480       if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT)
481 	{
482 	  if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs)
483 	    valp = &frame->regs[pabi->regs[narg_reg++]];
484 	  else if (dir < 0)
485 	    {
486 	      argp -= 4;
487 	      valp = argp;
488 	    }
489 	  else
490 	    {
491 	      valp = argp;
492 	      argp += 4;
493 	    }
494 	}
495       else
496 	{
497 	  size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG);
498 	  size_t align = FFI_SIZEOF_ARG;
499 
500 	  /* See the comment in ffi_call_int.  */
501 	  if (t == FFI_TYPE_STRUCT && ty->alignment >= 16)
502 	    align = 16;
503 
504 	  /* Issue 434: For thiscall and fastcall, if the paramter passed
505 	     as 64-bit integer or struct, all following integer paramters
506 	     will be passed on stack.  */
507 	  if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
508 	      && (t == FFI_TYPE_SINT64
509 		  || t == FFI_TYPE_UINT64
510 		  || t == FFI_TYPE_STRUCT))
511 	    narg_reg = 2;
512 
513 	  if (dir < 0)
514 	    {
515 	      /* ??? These reverse argument ABIs are probably too old
516 		 to have cared about alignment.  Someone should check.  */
517 	      argp -= za;
518 	      valp = argp;
519 	    }
520 	  else
521 	    {
522 	      argp = (char *)FFI_ALIGN (argp, align);
523 	      valp = argp;
524 	      argp += za;
525 	    }
526 	}
527 
528       avalue[i] = valp;
529     }
530 
531   frame->fun (cif, rvalue, avalue, frame->user_data);
532 
533   if (cabi == FFI_STDCALL)
534     return flags + (cif->bytes << X86_RET_POP_SHIFT);
535   else
536     return flags;
537 }
538 
539 ffi_status
ffi_prep_closure_loc(ffi_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * codeloc)540 ffi_prep_closure_loc (ffi_closure* closure,
541                       ffi_cif* cif,
542                       void (*fun)(ffi_cif*,void*,void**,void*),
543                       void *user_data,
544                       void *codeloc)
545 {
546   char *tramp = closure->tramp;
547   void (*dest)(void);
548   int op = 0xb8;  /* movl imm, %eax */
549 
550   switch (cif->abi)
551     {
552     case FFI_SYSV:
553     case FFI_THISCALL:
554     case FFI_FASTCALL:
555     case FFI_MS_CDECL:
556       dest = ffi_closure_i386;
557       break;
558     case FFI_STDCALL:
559     case FFI_PASCAL:
560       dest = ffi_closure_STDCALL;
561       break;
562     case FFI_REGISTER:
563       dest = ffi_closure_REGISTER;
564       op = 0x68;  /* pushl imm */
565       break;
566     default:
567       return FFI_BAD_ABI;
568     }
569 
570   /* movl or pushl immediate.  */
571   tramp[0] = op;
572   *(void **)(tramp + 1) = codeloc;
573 
574   /* jmp dest */
575   tramp[5] = 0xe9;
576   *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
577 
578   closure->cif = cif;
579   closure->fun = fun;
580   closure->user_data = user_data;
581 
582   return FFI_OK;
583 }
584 
585 void FFI_HIDDEN ffi_go_closure_EAX(void);
586 void FFI_HIDDEN ffi_go_closure_ECX(void);
587 void FFI_HIDDEN ffi_go_closure_STDCALL(void);
588 
589 ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))590 ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
591 		     void (*fun)(ffi_cif*,void*,void**,void*))
592 {
593   void (*dest)(void);
594 
595   switch (cif->abi)
596     {
597     case FFI_SYSV:
598     case FFI_MS_CDECL:
599       dest = ffi_go_closure_ECX;
600       break;
601     case FFI_THISCALL:
602     case FFI_FASTCALL:
603       dest = ffi_go_closure_EAX;
604       break;
605     case FFI_STDCALL:
606     case FFI_PASCAL:
607       dest = ffi_go_closure_STDCALL;
608       break;
609     case FFI_REGISTER:
610     default:
611       return FFI_BAD_ABI;
612     }
613 
614   closure->tramp = dest;
615   closure->cif = cif;
616   closure->fun = fun;
617 
618   return FFI_OK;
619 }
620 
621 /* ------- Native raw API support -------------------------------- */
622 
623 #if !FFI_NO_RAW_API
624 
625 void FFI_HIDDEN ffi_closure_raw_SYSV(void);
626 void FFI_HIDDEN ffi_closure_raw_THISCALL(void);
627 
628 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)629 ffi_prep_raw_closure_loc (ffi_raw_closure *closure,
630                           ffi_cif *cif,
631                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
632                           void *user_data,
633                           void *codeloc)
634 {
635   char *tramp = closure->tramp;
636   void (*dest)(void);
637   int i;
638 
639   /* We currently don't support certain kinds of arguments for raw
640      closures.  This should be implemented by a separate assembly
641      language routine, since it would require argument processing,
642      something we don't do now for performance.  */
643   for (i = cif->nargs-1; i >= 0; i--)
644     switch (cif->arg_types[i]->type)
645       {
646       case FFI_TYPE_STRUCT:
647       case FFI_TYPE_LONGDOUBLE:
648 	return FFI_BAD_TYPEDEF;
649       }
650 
651   switch (cif->abi)
652     {
653     case FFI_THISCALL:
654       dest = ffi_closure_raw_THISCALL;
655       break;
656     case FFI_SYSV:
657       dest = ffi_closure_raw_SYSV;
658       break;
659     default:
660       return FFI_BAD_ABI;
661     }
662 
663   /* movl imm, %eax.  */
664   tramp[0] = 0xb8;
665   *(void **)(tramp + 1) = codeloc;
666 
667   /* jmp dest */
668   tramp[5] = 0xe9;
669   *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10);
670 
671   closure->cif = cif;
672   closure->fun = fun;
673   closure->user_data = user_data;
674 
675   return FFI_OK;
676 }
677 
678 void
ffi_raw_call(ffi_cif * cif,void (* fn)(void),void * rvalue,ffi_raw * avalue)679 ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
680 {
681   size_t rsize, bytes;
682   struct call_frame *frame;
683   char *stack, *argp;
684   ffi_type **arg_types;
685   int flags, cabi, i, n, narg_reg;
686   const struct abi_params *pabi;
687 
688   flags = cif->flags;
689   cabi = cif->abi;
690   pabi = &abi_params[cabi];
691 
692   rsize = 0;
693   if (rvalue == NULL)
694     {
695       switch (flags)
696 	{
697 	case X86_RET_FLOAT:
698 	case X86_RET_DOUBLE:
699 	case X86_RET_LDOUBLE:
700 	case X86_RET_STRUCTPOP:
701 	case X86_RET_STRUCTARG:
702 	  /* The float cases need to pop the 387 stack.
703 	     The struct cases need to pass a valid pointer to the callee.  */
704 	  rsize = cif->rtype->size;
705 	  break;
706 	default:
707 	  /* We can pretend that the callee returns nothing.  */
708 	  flags = X86_RET_VOID;
709 	  break;
710 	}
711     }
712 
713   bytes = STACK_ALIGN (cif->bytes);
714   argp = stack =
715       (void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16);
716   frame = (struct call_frame *)(stack + bytes);
717   if (rsize)
718     rvalue = frame + 1;
719 
720   frame->fn = fn;
721   frame->flags = flags;
722   frame->rvalue = rvalue;
723 
724   narg_reg = 0;
725   switch (flags)
726     {
727     case X86_RET_STRUCTARG:
728       /* The pointer is passed as the first argument.  */
729       if (pabi->nregs > 0)
730 	{
731 	  frame->regs[pabi->regs[0]] = (unsigned)rvalue;
732 	  narg_reg = 1;
733 	  break;
734 	}
735       /* fallthru */
736     case X86_RET_STRUCTPOP:
737       *(void **)argp = rvalue;
738       argp += sizeof(void *);
739       bytes -= sizeof(void *);
740       break;
741     }
742 
743   arg_types = cif->arg_types;
744   for (i = 0, n = cif->nargs; narg_reg < pabi->nregs && i < n; i++)
745     {
746       ffi_type *ty = arg_types[i];
747       size_t z = ty->size;
748       int t = ty->type;
749 
750       if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT && t != FFI_TYPE_FLOAT)
751 	{
752 	  ffi_arg val = extend_basic_type (avalue, t);
753 	  frame->regs[pabi->regs[narg_reg++]] = val;
754 	  z = FFI_SIZEOF_ARG;
755 	}
756       else
757 	{
758 	  memcpy (argp, avalue, z);
759 	  z = FFI_ALIGN (z, FFI_SIZEOF_ARG);
760 	  argp += z;
761 	}
762       avalue += z;
763       bytes -= z;
764     }
765   if (i < n)
766     memcpy (argp, avalue, bytes);
767 
768   ffi_call_i386 (frame, stack);
769 }
770 #endif /* !FFI_NO_RAW_API */
771 #endif /* __i386__ */
772