OSDN Git Service

343ee925fde707f999ac2c30abae35662bc596ae
[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           memcpy (argp, *p_argv, (*p_arg)->size);
345           argp += (*p_arg)->size;
346         }
347       else
348         {
349           /* All easy cases are eliminated. Now fire the big guns.  */
350
351           enum x86_64_reg_class classes[MAX_CLASSES];
352           int offset = 0, j, num;
353           void *a;
354
355           num = classify_argument (*p_arg, classes, &offset);
356           for (j=0, a=*p_argv; j<num; j++, a+=8)
357             {
358               switch (classes[j])
359                 {
360                 case X86_64_INTEGER_CLASS:
361                 case X86_64_INTEGERSI_CLASS:
362                   stack->gpr[gprcount++] = *(long long *)a;
363                   break;
364                 case X86_64_SSE_CLASS:
365                   floatfloat2sse (a, &stack->sse[ssecount++]);
366                   break;
367                 case X86_64_SSESF_CLASS:
368                   float2sse (*(float *)a, &stack->sse[ssecount++]);
369                   break;
370                 case X86_64_SSEDF_CLASS:
371                   double2sse (*(double *)a, &stack->sse[ssecount++]);
372                   break;
373                 default:
374                   abort();
375                 }
376             }
377         }
378     }
379 }
380
381 /* Perform machine dependent cif processing.  */
382 ffi_status
383 ffi_prep_cif_machdep (ffi_cif *cif)
384 {
385   int gprcount, ssecount, i, g, s;
386
387   gprcount = ssecount = 0;
388
389   /* Reset the byte count. We handle this size estimation here.  */
390   cif->bytes = 0;
391
392   /* If the return value should be passed in memory, pass the pointer
393      as the first argument. The actual memory isn't allocated here.  */
394   if (cif->rtype->type != FFI_TYPE_VOID 
395       && examine_argument (cif->rtype, 1, &g, &s) == 0)
396     gprcount = 1;
397
398   /* Go over all arguments and determine the way they should be passed.
399      If it's in a register and there is space for it, let that be so. If
400      not, add it's size to the stack byte count.  */
401   for (i=0; i<cif->nargs; i++)
402     {
403       if (examine_argument (cif->arg_types[i], 0, &g, &s) == 0
404           || gprcount + g > MAX_GPR_REGS || ssecount + s > MAX_SSE_REGS)
405         {
406           /* This is passed in memory. First align to the basic type.  */
407           cif->bytes = ALIGN(cif->bytes, cif->arg_types[i]->alignment);
408
409           /* Stack arguments are *always* at least 8 byte aligned.  */
410           cif->bytes = ALIGN(cif->bytes, 8);
411
412           /* Now add the size of this argument.  */
413           cif->bytes += cif->arg_types[i]->size;
414         }
415       else
416         {
417           gprcount += g;
418           ssecount += s;
419         }
420     }
421
422   /* Set the flag for the closures return.  */
423     switch (cif->rtype->type)
424     {
425     case FFI_TYPE_VOID:
426     case FFI_TYPE_STRUCT:
427     case FFI_TYPE_SINT64:
428     case FFI_TYPE_FLOAT:
429     case FFI_TYPE_DOUBLE:
430     case FFI_TYPE_LONGDOUBLE:
431       cif->flags = (unsigned) cif->rtype->type;
432       break;
433
434     case FFI_TYPE_UINT64:
435       cif->flags = FFI_TYPE_SINT64;
436       break;
437
438     default:
439       cif->flags = FFI_TYPE_INT;
440       break;
441     }
442
443   return FFI_OK;
444 }
445
446 typedef struct
447 {
448   long gpr[2];
449   __int128_t sse[2];
450   long double st0;
451 } return_value;
452
453 void
454 ffi_fill_return_value (return_value *rv, extended_cif *ecif)
455 {
456   enum x86_64_reg_class classes[MAX_CLASSES];
457   int i = 0, num;
458   long *gpr = rv->gpr;
459   __int128_t *sse = rv->sse;
460   signed char sc;
461   signed short ss;
462
463   /* This is needed because of the way x86-64 handles signed short
464      integers.  */
465   switch (ecif->cif->rtype->type)
466     {
467     case FFI_TYPE_SINT8:
468       sc = *(signed char *)gpr;
469       *(long long *)ecif->rvalue = (long long)sc;
470       return;
471     case FFI_TYPE_SINT16:
472       ss = *(signed short *)gpr;
473       *(long long *)ecif->rvalue = (long long)ss;
474       return;
475     default:
476       /* Just continue.  */
477       ;
478     }
479
480   num = classify_argument (ecif->cif->rtype, classes, &i);
481
482   if (num == 0)
483     /* Return in memory.  */
484     ecif->rvalue = (void *) rv->gpr[0];
485   else if (num == 2 && classes[0] == X86_64_X87_CLASS &&
486         classes[1] == X86_64_X87UP_CLASS)
487     /* This is a long double (this is easiest to handle this way instead
488        of an eightbyte at a time as in the loop below.  */
489     *((long double *)ecif->rvalue) = rv->st0;
490   else
491     {
492       void *a;
493
494       for (i=0, a=ecif->rvalue; i<num; i++, a+=8)
495         {
496           switch (classes[i])
497             {
498             case X86_64_INTEGER_CLASS:
499             case X86_64_INTEGERSI_CLASS:
500               *(long long *)a = *gpr;
501               gpr++;
502               break;
503             case X86_64_SSE_CLASS:
504               sse2floatfloat (sse++, a);
505               break;
506             case X86_64_SSESF_CLASS:
507               *(float *)a = sse2float (sse++);
508               break;
509             case X86_64_SSEDF_CLASS:
510               *(double *)a = sse2double (sse++);
511               break;
512             default:
513               abort();
514             }
515         }
516     }
517 }
518
519 /*@-declundef@*/
520 /*@-exportheader@*/
521 extern void ffi_call_UNIX64(void (*)(stackLayout *, extended_cif *),
522                             void (*) (return_value *, extended_cif *),
523                             /*@out@*/ extended_cif *, 
524                             unsigned, /*@out@*/ unsigned *, void (*fn)());
525 /*@=declundef@*/
526 /*@=exportheader@*/
527
528 void ffi_call(/*@dependent@*/ ffi_cif *cif, 
529               void (*fn)(), 
530               /*@out@*/ void *rvalue, 
531               /*@dependent@*/ void **avalue)
532 {
533   extended_cif ecif;
534   int dummy;
535
536   ecif.cif = cif;
537   ecif.avalue = avalue;
538   
539   /* If the return value is a struct and we don't have a return */
540   /* value address then we need to make one                     */
541
542   if ((rvalue == NULL) && 
543       (examine_argument (cif->rtype, 1, &dummy, &dummy) == 0))
544     {
545       /*@-sysunrecog@*/
546       ecif.rvalue = alloca(cif->rtype->size);
547       /*@=sysunrecog@*/
548     }
549   else
550     ecif.rvalue = rvalue;
551     
552   /* Stack must always be 16byte aligned. Make it so.  */
553   cif->bytes = ALIGN(cif->bytes, 16);
554   
555   switch (cif->abi) 
556     {
557     case FFI_SYSV:
558       /* Calling 32bit code from 64bit is not possible  */
559       FFI_ASSERT(0);
560       break;
561
562     case FFI_UNIX64:
563       /*@-usedef@*/
564       ffi_call_UNIX64 (ffi_prep_args, ffi_fill_return_value, &ecif,
565                        cif->bytes, ecif.rvalue, fn);
566       /*@=usedef@*/
567       break;
568
569     default:
570       FFI_ASSERT(0);
571       break;
572     }
573 }
574
575 extern void ffi_closure_UNIX64(void);
576
577 ffi_status
578 ffi_prep_closure (ffi_closure* closure,
579                   ffi_cif* cif,
580                   void (*fun)(ffi_cif*, void*, void**, void*),
581                   void *user_data)
582 {
583   volatile unsigned short *tramp;
584
585   /* FFI_ASSERT (cif->abi == FFI_OSF);  */
586
587   tramp = (volatile unsigned short *) &closure->tramp[0];
588   tramp[0] = 0xbb49;            /* mov <code>, %r11     */
589   tramp[5] = 0xba49;            /* mov <data>, %r10     */
590   tramp[10] = 0xff49;           /* jmp *%r11    */
591   tramp[11] = 0x00e3;
592   *(void * volatile *) &tramp[1] = ffi_closure_UNIX64;
593   *(void * volatile *) &tramp[6] = closure;
594
595   closure->cif = cif;
596   closure->fun = fun;
597   closure->user_data = user_data;
598
599   return FFI_OK;
600 }
601
602 int
603 ffi_closure_UNIX64_inner(ffi_closure *closure, va_list l, void *rp)
604 {
605   ffi_cif *cif;
606   void **avalue;
607   ffi_type **arg_types;
608   long i, avn, argn;
609
610   cif = closure->cif;
611   avalue = alloca(cif->nargs * sizeof(void *));
612
613   argn = 0;
614
615   i = 0;
616   avn = cif->nargs;
617   arg_types = cif->arg_types;
618   
619   /* Grab the addresses of the arguments from the stack frame.  */
620   while (i < avn)
621     {
622       switch (arg_types[i]->type)
623         {
624         case FFI_TYPE_SINT8:
625         case FFI_TYPE_UINT8:
626         case FFI_TYPE_SINT16:
627         case FFI_TYPE_UINT16:
628         case FFI_TYPE_SINT32:
629         case FFI_TYPE_UINT32:
630         case FFI_TYPE_SINT64:
631         case FFI_TYPE_UINT64:
632         case FFI_TYPE_POINTER:
633           {
634             if (l->gp_offset > 48-8)
635               {
636                 avalue[i] = l->overflow_arg_area;
637                 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
638               }
639             else
640               {
641                 avalue[i] = (char *)l->reg_save_area + l->gp_offset;
642                 l->gp_offset += 8;
643               }
644           }
645           break;
646
647         case FFI_TYPE_STRUCT:
648           /* FIXME  */
649           FFI_ASSERT(0);
650           break;
651
652         case FFI_TYPE_DOUBLE:
653           {
654             if (l->fp_offset > 176-16)
655               {
656                 avalue[i] = l->overflow_arg_area;
657                 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
658               }
659             else
660               {
661                 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
662                 l->fp_offset += 16;
663               }
664           }
665 #if DEBUG_FFI
666           fprintf (stderr, "double arg %d = %g\n", i, *(double *)avalue[i]);
667 #endif
668           break;
669           
670         case FFI_TYPE_FLOAT:
671           {
672             if (l->fp_offset > 176-16)
673               {
674                 avalue[i] = l->overflow_arg_area;
675                 l->overflow_arg_area = (char *)l->overflow_arg_area + 8;
676               }
677             else
678               {
679                 avalue[i] = (char *)l->reg_save_area + l->fp_offset;
680                 l->fp_offset += 16;
681               }
682           }
683 #if DEBUG_FFI
684           fprintf (stderr, "float arg %d = %g\n", i, *(float *)avalue[i]);
685 #endif
686           break;
687           
688         default:
689           FFI_ASSERT(0);
690         }
691
692       argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
693       i++;
694     }
695
696   /* Invoke the closure.  */
697   (closure->fun) (cif, rp, avalue, closure->user_data);
698
699   /* FIXME: Structs not supported.  */
700   FFI_ASSERT(cif->rtype->type != FFI_TYPE_STRUCT);
701
702   /* Tell ffi_closure_UNIX64 how to perform return type promotions.  */
703
704   return cif->rtype->type;
705 }
706 #endif /* ifndef __x86_64__ */