OSDN Git Service

2004-08-10 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libffi / src / x86 / ffi64.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2002  Bo Thorsen <bo@suse.de>
3    
4    x86-64 Foreign Function Interface 
5
6    Permission is hereby granted, free of charge, to any person obtaining
7    a copy of this software and associated documentation files (the
8    ``Software''), to deal in the Software without restriction, including
9    without limitation the rights to use, copy, modify, merge, publish,
10    distribute, sublicense, and/or sell copies of the Software, and to
11    permit persons to whom the Software is furnished to do so, subject to
12    the following conditions:
13
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
16
17    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23    OTHER DEALINGS IN THE SOFTWARE.
24    ----------------------------------------------------------------------- */
25
26 #include <ffi.h>
27 #include <ffi_common.h>
28
29 #include <stdlib.h>
30 #include <stdarg.h>
31
32 /* ffi_prep_args is called by the assembly routine once stack space
33    has been allocated for the function's arguments */
34
35 #ifdef __x86_64__
36
37 #define MAX_GPR_REGS 6
38 #define MAX_SSE_REGS 8
39 typedef struct
40 {
41   /* Registers for argument passing.  */
42   long gpr[MAX_GPR_REGS];
43   __int128_t sse[MAX_SSE_REGS];
44
45   /* Stack space for arguments.  */
46   char argspace[0];
47 } stackLayout;
48
49 /* All reference to register classes here is identical to the code in
50    gcc/config/i386/i386.c. Do *not* change one without the other.  */
51
52 /* Register class used for passing given 64bit part of the argument.
53    These represent classes as documented by the PS ABI, with the exception
54    of SSESF, SSEDF classes, that are basically SSE class, just gcc will
55    use SF or DFmode move instead of DImode to avoid reformating penalties.
56
57    Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
58    whenever possible (upper half does contain padding).
59  */
60 enum x86_64_reg_class
61   {
62     X86_64_NO_CLASS,
63     X86_64_INTEGER_CLASS,
64     X86_64_INTEGERSI_CLASS,
65     X86_64_SSE_CLASS,
66     X86_64_SSESF_CLASS,
67     X86_64_SSEDF_CLASS,
68     X86_64_SSEUP_CLASS,
69     X86_64_X87_CLASS,
70     X86_64_X87UP_CLASS,
71     X86_64_MEMORY_CLASS
72   };
73
74 #define MAX_CLASSES 4
75
76 /* x86-64 register passing implementation.  See x86-64 ABI for details.  Goal
77    of this code is to classify each 8bytes of incoming argument by the register
78    class and assign registers accordingly.  */
79
80 /* Return the union class of CLASS1 and CLASS2.
81    See the x86-64 PS ABI for details.  */
82
83 static enum x86_64_reg_class
84 merge_classes (enum x86_64_reg_class class1, enum x86_64_reg_class class2)
85 {
86   /* Rule #1: If both classes are equal, this is the resulting class.  */
87   if (class1 == class2)
88     return class1;
89
90   /* Rule #2: If one of the classes is NO_CLASS, the resulting class is
91      the other class.  */
92   if (class1 == X86_64_NO_CLASS)
93     return class2;
94   if (class2 == X86_64_NO_CLASS)
95     return class1;
96
97   /* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  */
98   if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS)
99     return X86_64_MEMORY_CLASS;
100
101   /* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  */
102   if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS)
103       || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS))
104     return X86_64_INTEGERSI_CLASS;
105   if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS
106       || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS)
107     return X86_64_INTEGER_CLASS;
108
109   /* Rule #5: If one of the classes is X87 or X87UP class, MEMORY is used.  */
110   if (class1 == X86_64_X87_CLASS || class1 == X86_64_X87UP_CLASS
111       || class2 == X86_64_X87_CLASS || class2 == X86_64_X87UP_CLASS)
112     return X86_64_MEMORY_CLASS;
113
114   /* Rule #6: Otherwise class SSE is used.  */
115   return X86_64_SSE_CLASS;
116 }
117
118 /* Classify the argument of type TYPE and mode MODE.
119    CLASSES will be filled by the register class used to pass each word
120    of the operand.  The number of words is returned.  In case the parameter
121    should be passed in memory, 0 is returned. As a special case for zero
122    sized containers, classes[0] will be NO_CLASS and 1 is returned.
123
124    See the x86-64 PS ABI for details.
125 */
126 static int
127 classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
128                    int *byte_offset)
129 {
130   /* First, align to the right place.  */
131   *byte_offset = ALIGN(*byte_offset, type->alignment);
132
133   switch (type->type)
134     {
135     case FFI_TYPE_UINT8:
136     case FFI_TYPE_SINT8:
137     case FFI_TYPE_UINT16:
138     case FFI_TYPE_SINT16:
139     case FFI_TYPE_UINT32:
140     case FFI_TYPE_SINT32:
141     case FFI_TYPE_UINT64:
142     case FFI_TYPE_SINT64:
143     case FFI_TYPE_POINTER:
144       if (((*byte_offset) % 8 + type->size) <= 4)
145         classes[0] = X86_64_INTEGERSI_CLASS;
146       else
147         classes[0] = X86_64_INTEGER_CLASS;
148       return 1;
149     case FFI_TYPE_FLOAT:
150       if (((*byte_offset) % 8) == 0)
151         classes[0] = X86_64_SSESF_CLASS;
152       else
153         classes[0] = X86_64_SSE_CLASS;
154       return 1;
155     case FFI_TYPE_DOUBLE:
156       classes[0] = X86_64_SSEDF_CLASS;
157       return 1;
158     case FFI_TYPE_LONGDOUBLE:
159       classes[0] = X86_64_X87_CLASS;
160       classes[1] = X86_64_X87UP_CLASS;
161       return 2;
162     case FFI_TYPE_STRUCT:
163       {
164         const int UNITS_PER_WORD = 8;
165         int words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
166         ffi_type **ptr; 
167         int i;
168         enum x86_64_reg_class subclasses[MAX_CLASSES];
169
170         /* If the struct is larger than 16 bytes, pass it on the stack.  */
171         if (type->size > 16)
172           return 0;
173
174         for (i = 0; i < words; i++)
175           classes[i] = X86_64_NO_CLASS;
176
177         /* Merge the fields of structure.  */
178         for (ptr=type->elements; (*ptr)!=NULL; ptr++)
179           {
180             int num;
181
182             num = classify_argument (*ptr, subclasses, byte_offset);
183             if (num == 0)
184               return 0;
185             for (i = 0; i < num; i++)
186               {
187                 int pos = *byte_offset / 8;
188                 classes[i + pos] =
189                   merge_classes (subclasses[i], classes[i + pos]);
190               }
191
192             if ((*ptr)->type != FFI_TYPE_STRUCT)
193               *byte_offset += (*ptr)->size;
194           }
195
196         /* Final merger cleanup.  */
197         for (i = 0; i < words; i++)
198           {
199             /* If one class is MEMORY, everything should be passed in
200                memory.  */
201             if (classes[i] == X86_64_MEMORY_CLASS)
202               return 0;
203
204             /* The X86_64_SSEUP_CLASS should be always preceded by
205                X86_64_SSE_CLASS.  */
206             if (classes[i] == X86_64_SSEUP_CLASS
207                 && (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
208               classes[i] = X86_64_SSE_CLASS;
209
210             /*  X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS.  */
211             if (classes[i] == X86_64_X87UP_CLASS
212                 && (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
213               classes[i] = X86_64_SSE_CLASS;
214           }
215         return words;
216       }
217
218     default:
219       FFI_ASSERT(0);
220     }
221   return 0; /* Never reached.  */
222 }
223
224 /* Examine the argument and return set number of register required in each
225    class.  Return 0 iff parameter should be passed in memory.  */
226 static int
227 examine_argument (ffi_type *type, int in_return, int *int_nregs,int *sse_nregs)
228 {
229   enum x86_64_reg_class class[MAX_CLASSES];
230   int offset = 0;
231   int n;
232
233   n = classify_argument (type, class, &offset);
234
235   if (n == 0)
236     return 0;
237
238   *int_nregs = 0;
239   *sse_nregs = 0;
240   for (n--; n>=0; n--)
241     switch (class[n])
242       {
243       case X86_64_INTEGER_CLASS:
244       case X86_64_INTEGERSI_CLASS:
245         (*int_nregs)++;
246         break;
247       case X86_64_SSE_CLASS:
248       case X86_64_SSESF_CLASS:
249       case X86_64_SSEDF_CLASS:
250         (*sse_nregs)++;
251         break;
252       case X86_64_NO_CLASS:
253       case X86_64_SSEUP_CLASS:
254         break;
255       case X86_64_X87_CLASS:
256       case X86_64_X87UP_CLASS:
257         if (!in_return)
258           return 0;
259         break;
260       default:
261         abort ();
262       }
263   return 1;
264 }
265
266 /* Functions to load floats and double to an SSE register placeholder.  */
267 extern void float2sse (float, __int128_t *);
268 extern void double2sse (double, __int128_t *);
269 extern void floatfloat2sse (void *, __int128_t *);
270
271 /* Functions to put the floats and doubles back.  */
272 extern float sse2float (__int128_t *);
273 extern double sse2double (__int128_t *);
274 extern void sse2floatfloat(__int128_t *, void *);
275
276 /*@-exportheader@*/
277 void
278 ffi_prep_args (stackLayout *stack, extended_cif *ecif)
279 /*@=exportheader@*/
280 {
281   int gprcount, ssecount, i, g, s;
282   void **p_argv;
283   void *argp = &stack->argspace;
284   ffi_type **p_arg;
285
286   /* First check if the return value should be passed in memory. If so,
287      pass the pointer as the first argument.  */
288   gprcount = ssecount = 0;
289   if (ecif->cif->rtype->type != FFI_TYPE_VOID 
290       && examine_argument (ecif->cif->rtype, 1, &g, &s) == 0)
291     stack->gpr[gprcount++] = (long) ecif->rvalue;
292
293   for (i=ecif->cif->nargs, p_arg=ecif->cif->arg_types, p_argv = ecif->avalue;
294        i!=0; i--, p_arg++, p_argv++)
295     {
296       int in_register = 0;
297
298       switch ((*p_arg)->type)
299         {
300         case FFI_TYPE_SINT8:
301         case FFI_TYPE_SINT16:
302         case FFI_TYPE_SINT32:
303         case FFI_TYPE_SINT64:
304         case FFI_TYPE_UINT8:
305         case FFI_TYPE_UINT16:
306         case FFI_TYPE_UINT32:
307         case FFI_TYPE_UINT64:
308         case FFI_TYPE_POINTER:
309           if (gprcount < MAX_GPR_REGS)
310             {
311               stack->gpr[gprcount] = 0;
312               stack->gpr[gprcount++] = *(long long *)(*p_argv);
313               in_register = 1;
314             }
315           break;
316
317         case FFI_TYPE_FLOAT:
318           if (ssecount < MAX_SSE_REGS)
319             {
320               float2sse (*(float *)(*p_argv), &stack->sse[ssecount++]);
321               in_register = 1;
322             }
323           break;
324
325         case FFI_TYPE_DOUBLE:
326           if (ssecount < MAX_SSE_REGS)
327             {
328               double2sse (*(double *)(*p_argv), &stack->sse[ssecount++]);
329               in_register = 1;
330             }
331           break;
332         }
333
334       if (in_register)
335         continue;
336
337       /* Either all places in registers where filled, or this is a
338          type that potentially goes into a memory slot.  */
339       if (examine_argument (*p_arg, 0, &g, &s) == 0
340           || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
341         {
342           /* Pass this argument in memory.  */
343           argp = (void *)ALIGN(argp, (*p_arg)->alignment);
344           /* Stack arguments are *always* at least 8 byte aligned.  */
345           argp = (void *)ALIGN(argp, 8);
346           memcpy (argp, *p_argv, (*p_arg)->size);
347           argp += (*p_arg)->size;
348         }
349       else
350         {
351           /* All easy cases are eliminated. Now fire the big guns.  */
352
353           enum x86_64_reg_class classes[MAX_CLASSES];
354           int offset = 0, j, num;
355           void *a;
356
357           num = classify_argument (*p_arg, classes, &offset);
358           for (j=0, a=*p_argv; j<num; j++, a+=8)
359             {
360               switch (classes[j])
361                 {
362                 case X86_64_INTEGER_CLASS:
363                 case X86_64_INTEGERSI_CLASS:
364                   stack->gpr[gprcount++] = *(long long *)a;
365                   break;
366                 case X86_64_SSE_CLASS:
367                   floatfloat2sse (a, &stack->sse[ssecount++]);
368                   break;
369                 case X86_64_SSESF_CLASS:
370                   float2sse (*(float *)a, &stack->sse[ssecount++]);
371                   break;
372                 case X86_64_SSEDF_CLASS:
373                   double2sse (*(double *)a, &stack->sse[ssecount++]);
374                   break;
375                 default:
376                   abort();
377                 }
378             }
379         }
380     }
381 }
382
383 /* Perform machine dependent cif processing.  */
384 ffi_status
385 ffi_prep_cif_machdep (ffi_cif *cif)
386 {
387   int gprcount, ssecount, i, g, s;
388
389   gprcount = ssecount = 0;
390
391   /* Reset the byte count. We handle this size estimation here.  */
392   cif->bytes = 0;
393
394   /* If the return value should be passed in memory, pass the pointer
395      as the first argument. The actual memory isn't allocated here.  */
396   if (cif->rtype->type != FFI_TYPE_VOID 
397       && examine_argument (cif->rtype, 1, &g, &s) == 0)
398     gprcount = 1;
399
400   /* Go over all arguments and determine the way they should be passed.
401      If it's in a register and there is space for it, let that be so. If
402      not, add it's size to the stack byte count.  */
403   for (i=0; i<cif->nargs; i++)
404     {
405       if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
406           || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
407         {
408           /* This is passed in memory. First align to the basic type.  */
409           cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
410
411           /* Stack arguments are *always* at least 8 byte aligned.  */
412           cif->bytes = ALIGN(cif->bytes, 8);
413
414           /* Now add the size of this argument.  */
415           cif->bytes += cif->arg_types[i]->size;
416         }
417       else
418         {
419           gprcount += g;
420           ssecount += s;
421         }
422     }
423
424   /* Set the flag for the closures return.  */
425     switch (cif->rtype->type)
426     {
427     case FFI_TYPE_VOID:
428     case FFI_TYPE_STRUCT:
429     case FFI_TYPE_SINT64:
430     case FFI_TYPE_FLOAT:
431     case FFI_TYPE_DOUBLE:
432     case FFI_TYPE_LONGDOUBLE:
433       cif->flags = (unsigned) cif->rtype->type;
434       break;
435
436     case FFI_TYPE_UINT64:
437       cif->flags = FFI_TYPE_SINT64;
438       break;
439
440     default:
441       cif->flags = FFI_TYPE_INT;
442       break;
443     }
444
445   return FFI_OK;
446 }
447
448 typedef struct
449 {
450   long gpr[2];
451   __int128_t sse[2];
452   long double st0;
453 } return_value;
454
455 void
456 ffi_fill_return_value (return_value *rv, extended_cif *ecif)
457 {
458   enum x86_64_reg_class classes[MAX_CLASSES];
459   int i = 0, num;
460   long *gpr = rv->gpr;
461   __int128_t *sse = rv->sse;
462   signed char sc;
463   signed short ss;
464
465   /* This is needed because of the way x86-64 handles signed short
466      integers.  */
467   switch (ecif->cif->rtype->type)
468     {
469     case FFI_TYPE_SINT8:
470       sc = *(signed char *)gpr;
471       *(long long *)ecif->rvalue = (long long)sc;
472       return;
473     case FFI_TYPE_SINT16:
474       ss = *(signed short *)gpr;
475       *(long long *)ecif->rvalue = (long long)ss;
476       return;
477     default:
478       /* Just continue.  */
479       ;
480     }
481
482   num = classify_argument (ecif->cif->rtype, classes, &i);
483
484   if (num == 0)
485     /* Return in memory.  */
486     ecif->rvalue = (void *) rv->gpr[0];
487   else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
488         classes[1] == X86_64_X87UP_CLASS)
489     /* This is a long double (this is easiest to handle this way instead
490        of an eightbyte at a time as in the loop below.  */
491     *((long double *)ecif->rvalue) = rv->st0;
492   else
493     {
494       void *a;
495
496       for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
497         {
498           switch (classes[i])
499             {
500             case X86_64_INTEGER_CLASS:
501             case X86_64_INTEGERSI_CLASS:
502               *(long long *)a = *gpr;
503               gpr++;
504               break;
505             case X86_64_SSE_CLASS:
506               sse2floatfloat (sse++, a);
507               break;
508             case X86_64_SSESF_CLASS:
509               *(float *)a = sse2float (sse++);
510               break;
511             case X86_64_SSEDF_CLASS:
512               *(double *)a = sse2double (sse++);
513               break;
514             default:
515               abort();
516             }
517         }
518     }
519 }
520
521 /*@-declundef@*/
522 /*@-exportheader@*/
523 extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
524                             void (*) (return_value *, extended_cif *),
525                             /*@out@*/ extended_cif *, 
526                             unsigned, /*@out@*/ unsigned *, void (*fn)());
527 /*@=declundef@*/
528 /*@=exportheader@*/
529
530 void ffi_call(/*@dependent@*/ ffi_cif *cif, 
531               void (*fn)(), 
532               /*@out@*/ void *rvalue, 
533               /*@dependent@*/ void **avalue)
534 {
535   extended_cif ecif;
536   int dummy;
537
538   ecif.cif = cif;
539   ecif.avalue = avalue;
540   
541   /* If the return value is a struct and we don't have a return */
542   /* value address then we need to make one                     */
543
544   if ((rvalue == NULL) && 
545       (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
546     {
547       /*@-sysunrecog@*/
548       ecif.rvalue = alloca(cif->rtype->size);
549       /*@=sysunrecog@*/
550     }
551   else
552     ecif.rvalue = rvalue;
553     
554   /* Stack must always be 16byte aligned. Make it so.  */
555   cif->bytes = ALIGN(cif->bytes, 16);
556   
557   switch (cif->abi) 
558     {
559     case FFI_SYSV:
560       /* Calling 32bit code from 64bit is not possible  */
561       FFI_ASSERT(0);
562       break;
563
564     case FFI_UNIX64:
565       /*@-usedef@*/
566       ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
567                        cif->bytes, ecif.rvalue, fn);
568       /*@=usedef@*/
569       break;
570
571     default:
572       FFI_ASSERT(0);
573       break;
574     }
575 }
576
577 extern void ffi_closure_UNIX64(void);
578
579 ffi_status
580 ffi_prep_closure (ffi_closure* closure,
581                   ffi_cif* cif,
582                   void (*fun)(ffi_cif*, void*, void**, void*),
583                   void *user_data)
584 {
585   volatile unsigned short *tramp;
586
587   /* FFI_ASSERT (cif->abi == FFI_OSF);  */
588
589   tramp = (volatile unsigned short *) &closure->tramp[0];
590   tramp[0] = 0xbb49;            /* mov <code>, %r11     */
591   tramp[5] = 0xba49;            /* mov <data>, %r10     */
592   tramp[10] = 0xff49;           /* jmp *%r11    */
593   tramp[11] = 0x00e3;
594   *(void * volatile *) &tramp[1] = ffi_closure_UNIX64;
595   *(void * volatile *) &tramp[6] = closure;
596
597   closure->cif = cif;
598   closure->fun = fun;
599   closure->user_data = user_data;
600
601   return FFI_OK;
602 }
603
604 int
605 ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp)
606 {
607   ffi_cif *cif;
608   void **avalue;
609   ffi_type **arg_types;
610   long i, avn, argn;
611
612   cif = closure->cif;
613   avalue = alloca(cif->nargs * sizeof(void *));
614
615   argn = 0;
616
617   i = 0;
618   avn = cif->nargs;
619   arg_types = cif->arg_types;
620   
621   /* Grab the addresses of the arguments from the stack frame.  */
622   while (i < avn)
623     {
624       switch (arg_types[i]->type)
625         {
626         case FFI_TYPE_SINT8:
627         case FFI_TYPE_UINT8:
628         case FFI_TYPE_SINT16:
629         case FFI_TYPE_UINT16:
630         case FFI_TYPE_SINT32:
631         case FFI_TYPE_UINT32:
632         case FFI_TYPE_SINT64:
633         case FFI_TYPE_UINT64:
634         case FFI_TYPE_POINTER:
635           {
636             if (l->gp_offset > 48-8)
637               {
638                 avalue[i] = l->overflow_arg_area;
639                 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
640               }
641             else
642               {
643                 avalue[i] = (char *)l->reg_save_area + l->gp_offset;
644                 l->gp_offset += 8;
645               }
646           }
647           break;
648
649         case FFI_TYPE_STRUCT:
650           /* FIXME  */
651           FFI_ASSERT(0);
652           break;
653
654         case FFI_TYPE_DOUBLE:
655           {
656             if (l->fp_offset > 176-16)
657               {
658                 avalue[i] = l->overflow_arg_area;
659                 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
660               }
661             else
662               {
663                 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
664                 l->fp_offset += 16;
665               }
666           }
667 #if DEBUG_FFI
668           fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);
669 #endif
670           break;
671           
672         case FFI_TYPE_FLOAT:
673           {
674             if (l->fp_offset > 176-16)
675               {
676                 avalue[i] = l->overflow_arg_area;
677                 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
678               }
679             else
680               {
681                 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
682                 l->fp_offset += 16;
683               }
684           }
685 #if DEBUG_FFI
686           fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);
687 #endif
688           break;
689           
690         default:
691           FFI_ASSERT(0);
692         }
693
694       argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
695       i++;
696     }
697
698   /* Invoke the closure.  */
699   (closure->fun) (cif, rp, avalue, closure->user_data);
700
701   /* FIXME: Structs not supported.  */
702   FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);
703
704   /* Tell ffi_closure_UNIX64 how to perform return type promotions.  */
705
706   return cif->rtype->type;
707 }
708 #endif /* ifndef __x86_64__ */