3b39056ed12d7ec43fc129f9a9b2faea14e4d25b
[platform/upstream/libffi.git] / src / arm / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2011 Timothy Wall
3            Copyright (c) 2011 Plausible Labs Cooperative, Inc.
4            Copyright (c) 2011 Anthony Green
5            Copyright (c) 2011 Free Software Foundation
6            Copyright (c) 1998, 2008, 2011  Red Hat, Inc.
7
8    ARM 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 #include <ffi.h>
32 #include <ffi_common.h>
33
34 #include <stdlib.h>
35
36 /* Forward declares. */
37 static int vfp_type_p (ffi_type *);
38 static void layout_vfp_args (ffi_cif *);
39
40 int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space);
41 int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space);
42
43 static char* ffi_align(ffi_type **p_arg, char *argp)
44 {
45   /* Align if necessary */
46   register size_t alignment = (*p_arg)->alignment;
47   if (alignment < 4)
48   {
49     alignment = 4;
50   }
51 #ifdef _WIN32_WCE
52   if (alignment > 4)
53   {
54     alignment = 4;
55   }
56 #endif
57   if ((alignment - 1) & (unsigned) argp)
58   {
59     argp = (char *) ALIGN(argp, alignment);
60   }
61
62   if ((*p_arg)->type == FFI_TYPE_STRUCT)
63   {
64     argp = (char *) ALIGN(argp, 4);
65   }
66   return argp;
67 }
68
69 static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack)
70 {
71         register char* argp = stack;
72         register ffi_type **p_arg = arg_type;
73         register void **p_argv = arg;
74         register size_t z = (*p_arg)->size;
75   if (z < sizeof(int))
76     {
77                 z = sizeof(int);
78                 switch ((*p_arg)->type)
79       {
80       case FFI_TYPE_SINT8:
81         *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
82         break;
83         
84       case FFI_TYPE_UINT8:
85         *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
86         break;
87         
88       case FFI_TYPE_SINT16:
89         *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
90         break;
91         
92       case FFI_TYPE_UINT16:
93         *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
94         break;
95         
96       case FFI_TYPE_STRUCT:
97         memcpy(argp, *p_argv, (*p_arg)->size);
98         break;
99
100       default:
101         FFI_ASSERT(0);
102       }
103     }
104   else if (z == sizeof(int))
105     {
106                 if ((*p_arg)->type == FFI_TYPE_FLOAT)
107                         *(float *) argp = *(float *)(* p_argv);
108                 else
109                         *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
110     }
111         else if (z == sizeof(double) && (*p_arg)->type == FFI_TYPE_DOUBLE)
112                 {
113                         *(double *) argp = *(double *)(* p_argv);
114                 }
115   else
116     {
117       memcpy(argp, *p_argv, z);
118     }
119   return z;
120 }
121 /* ffi_prep_args is called by the assembly routine once stack space
122    has been allocated for the function's arguments
123    
124    The vfp_space parameter is the load area for VFP regs, the return
125    value is cif->vfp_used (word bitset of VFP regs used for passing
126    arguments). These are only used for the VFP hard-float ABI.
127 */
128 int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space)
129 {
130   register unsigned int i;
131   register void **p_argv;
132   register char *argp;
133   register ffi_type **p_arg;
134   argp = stack;
135   
136
137   if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
138     *(void **) argp = ecif->rvalue;
139     argp += 4;
140   }
141
142   p_argv = ecif->avalue;
143
144   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
145        (i != 0);
146        i--, p_arg++, p_argv++)
147     {
148     argp = ffi_align(p_arg, argp);
149     argp += ffi_put_arg(p_arg, p_argv, argp);
150     }
151
152   return 0;
153 }
154
155 int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space)
156 {
157   // make sure we are using FFI_VFP
158   FFI_ASSERT(ecif->cif->abi == FFI_VFP);
159
160   register unsigned int i, vi = 0;
161   register void **p_argv;
162   register char *argp, *regp, *eo_regp;
163   register ffi_type **p_arg;
164   char stack_used = 0;
165   char done_with_regs = 0;
166   char is_vfp_type;
167
168   /* the first 4 words on the stack are used for values passed in core
169    * registers. */
170   regp = stack;
171   eo_regp = argp = regp + 16;
172   
173
174   /* if the function returns an FFI_TYPE_STRUCT in memory, that address is
175    * passed in r0 to the function */
176   if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
177     *(void **) regp = ecif->rvalue;
178     regp += 4;
179   }
180
181   p_argv = ecif->avalue;
182
183   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
184        (i != 0);
185        i--, p_arg++, p_argv++)
186     {
187       is_vfp_type = vfp_type_p (*p_arg);
188
189       /* Allocated in VFP registers. */
190       if(vi < ecif->cif->vfp_nargs && is_vfp_type)
191         {
192           char *vfp_slot = (char *)(vfp_space + ecif->cif->vfp_args[vi++]);
193           ffi_put_arg(p_arg, p_argv, vfp_slot);
194           continue;
195         }
196       /* Try allocating in core registers. */
197       else if (!done_with_regs && !is_vfp_type)
198         {
199           char *tregp = ffi_align(p_arg, regp);
200           size_t size = (*p_arg)->size; 
201           size = (size < 4)? 4 : size; // pad
202           /* Check if there is space left in the aligned register area to place
203            * the argument */
204           if(tregp + size <= eo_regp)
205             {
206               regp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
207               done_with_regs = (regp == argp);
208               // ensure we did not write into the stack area
209               FFI_ASSERT(regp <= argp);
210               continue;
211             }
212           /* In case there are no arguments in the stack area yet, 
213           the argument is passed in the remaining core registers and on the
214           stack. */
215           else if (!stack_used) 
216             {
217               stack_used = 1;
218               done_with_regs = 1;
219               argp = tregp + ffi_put_arg(p_arg, p_argv, tregp);
220               FFI_ASSERT(eo_regp < argp);
221               continue;
222             }
223         }
224       /* Base case, arguments are passed on the stack */
225       stack_used = 1;
226       argp = ffi_align(p_arg, argp);
227       argp += ffi_put_arg(p_arg, p_argv, argp);
228     }
229   /* Indicate the VFP registers used. */
230   return ecif->cif->vfp_used;
231 }
232
233 /* Perform machine dependent cif processing */
234 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
235 {
236   int type_code;
237   /* Round the stack up to a multiple of 8 bytes.  This isn't needed 
238      everywhere, but it is on some platforms, and it doesn't harm anything
239      when it isn't needed.  */
240   cif->bytes = (cif->bytes + 7) & ~7;
241
242   /* Set the return type flag */
243   switch (cif->rtype->type)
244     {
245     case FFI_TYPE_VOID:
246     case FFI_TYPE_FLOAT:
247     case FFI_TYPE_DOUBLE:
248       cif->flags = (unsigned) cif->rtype->type;
249       break;
250
251     case FFI_TYPE_SINT64:
252     case FFI_TYPE_UINT64:
253       cif->flags = (unsigned) FFI_TYPE_SINT64;
254       break;
255
256     case FFI_TYPE_STRUCT:
257       if (cif->abi == FFI_VFP
258           && (type_code = vfp_type_p (cif->rtype)) != 0)
259         {
260           /* A Composite Type passed in VFP registers, either
261              FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */
262           cif->flags = (unsigned) type_code;
263         }
264       else if (cif->rtype->size <= 4)
265         /* A Composite Type not larger than 4 bytes is returned in r0.  */
266         cif->flags = (unsigned)FFI_TYPE_INT;
267       else
268         /* A Composite Type larger than 4 bytes, or whose size cannot
269            be determined statically ... is stored in memory at an
270            address passed [in r0].  */
271         cif->flags = (unsigned)FFI_TYPE_STRUCT;
272       break;
273
274     default:
275       cif->flags = FFI_TYPE_INT;
276       break;
277     }
278
279   /* Map out the register placements of VFP register args.
280      The VFP hard-float calling conventions are slightly more sophisticated than
281      the base calling conventions, so we do it here instead of in ffi_prep_args(). */
282   if (cif->abi == FFI_VFP)
283     layout_vfp_args (cif);
284
285   return FFI_OK;
286 }
287
288 /* Perform machine dependent cif processing for variadic calls */
289 ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
290                                     unsigned int nfixedargs,
291                                     unsigned int ntotalargs)
292 {
293   /* VFP variadic calls actually use the SYSV ABI */
294   if (cif->abi == FFI_VFP)
295         cif->abi = FFI_SYSV;
296
297   return ffi_prep_cif_machdep(cif);
298 }
299
300 /* Prototypes for assembly functions, in sysv.S */
301 extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
302 extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *);
303
304 void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
305 {
306   extended_cif ecif;
307
308   int small_struct = (cif->flags == FFI_TYPE_INT 
309                       && cif->rtype->type == FFI_TYPE_STRUCT);
310   int vfp_struct = (cif->flags == FFI_TYPE_STRUCT_VFP_FLOAT
311                     || cif->flags == FFI_TYPE_STRUCT_VFP_DOUBLE);
312
313   unsigned int temp;
314   
315   ecif.cif = cif;
316   ecif.avalue = avalue;
317
318   /* If the return value is a struct and we don't have a return */
319   /* value address then we need to make one                     */
320
321   if ((rvalue == NULL) && 
322       (cif->flags == FFI_TYPE_STRUCT))
323     {
324       ecif.rvalue = alloca(cif->rtype->size);
325     }
326   else if (small_struct)
327     ecif.rvalue = &temp;
328   else if (vfp_struct)
329     {
330       /* Largest case is double x 4. */
331       ecif.rvalue = alloca(32);
332     }
333   else
334     ecif.rvalue = rvalue;
335
336   switch (cif->abi) 
337     {
338     case FFI_SYSV:
339       ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
340       break;
341
342     case FFI_VFP:
343 #ifdef __ARM_EABI__
344       ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue);
345       break;
346 #endif
347
348     default:
349       FFI_ASSERT(0);
350       break;
351     }
352   if (small_struct)
353     {
354       FFI_ASSERT(rvalue != NULL);
355       memcpy (rvalue, &temp, cif->rtype->size);
356     }
357     
358   else if (vfp_struct)
359     {
360       FFI_ASSERT(rvalue != NULL);
361       memcpy (rvalue, ecif.rvalue, cif->rtype->size);
362     }
363     
364 }
365
366 /** private members **/
367
368 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
369                                          void** args, ffi_cif* cif, float *vfp_stack);
370
371 static void ffi_prep_incoming_args_VFP (char *stack, void **ret,
372                                          void** args, ffi_cif* cif, float *vfp_stack);
373
374 void ffi_closure_SYSV (ffi_closure *);
375
376 void ffi_closure_VFP (ffi_closure *);
377
378 /* This function is jumped to by the trampoline */
379
380 unsigned int FFI_HIDDEN
381 ffi_closure_inner (ffi_closure *closure, 
382                    void **respp, void *args, void *vfp_args)
383 {
384   // our various things...
385   ffi_cif       *cif;
386   void         **arg_area;
387
388   cif         = closure->cif;
389   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
390
391   /* this call will initialize ARG_AREA, such that each
392    * element in that array points to the corresponding 
393    * value on the stack; and if the function returns
394    * a structure, it will re-set RESP to point to the
395    * structure return address.  */
396   if (cif->abi == FFI_VFP)
397     ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args);
398   else
399     ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args);
400
401   (closure->fun) (cif, *respp, arg_area, closure->user_data);
402
403   return cif->flags;
404 }
405
406 /*@-exportheader@*/
407 static void 
408 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
409                             void **avalue, ffi_cif *cif,
410                             /* Used only under VFP hard-float ABI. */
411                             float *vfp_stack)
412 /*@=exportheader@*/
413 {
414   register unsigned int i;
415   register void **p_argv;
416   register char *argp;
417   register ffi_type **p_arg;
418
419   argp = stack;
420
421   if ( cif->flags == FFI_TYPE_STRUCT ) {
422     *rvalue = *(void **) argp;
423     argp += 4;
424   }
425
426   p_argv = avalue;
427
428   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
429     {
430       size_t z;
431
432       argp = ffi_align(p_arg, argp);
433
434       z = (*p_arg)->size;
435
436       /* because we're little endian, this is what it turns into.   */
437
438       *p_argv = (void*) argp;
439
440       p_argv++;
441       argp += z;
442     }
443   
444   return;
445 }
446
447 /*@-exportheader@*/
448 static void 
449 ffi_prep_incoming_args_VFP(char *stack, void **rvalue,
450                             void **avalue, ffi_cif *cif,
451                             /* Used only under VFP hard-float ABI. */
452                             float *vfp_stack)
453 /*@=exportheader@*/
454 {
455   register unsigned int i, vi = 0;
456   register void **p_argv;
457   register char *argp, *regp, *eo_regp;
458   register ffi_type **p_arg;
459   char done_with_regs = 0;
460   char stack_used = 0;
461   char is_vfp_type;
462
463   FFI_ASSERT(cif->abi == FFI_VFP);
464   regp = stack;
465   eo_regp = argp = regp + 16;
466
467   if ( cif->flags == FFI_TYPE_STRUCT ) {
468     *rvalue = *(void **) regp;
469     regp += 4;
470   }
471
472   p_argv = avalue;
473
474   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
475     {
476     size_t z;
477     is_vfp_type = vfp_type_p (*p_arg); 
478
479     if(vi < cif->vfp_nargs && is_vfp_type)
480       {
481         *p_argv++ = (void*)(vfp_stack + cif->vfp_args[vi++]);
482         continue;
483       }
484     else if (!done_with_regs && !is_vfp_type)
485       {
486         char* tregp = ffi_align(p_arg, regp);
487
488         z = (*p_arg)->size; 
489         z = (z < 4)? 4 : z; // pad
490         
491         /* if the arguments either fits into the registers or uses registers
492          * and stack, while we haven't read other things from the stack */
493         if(tregp + z <= eo_regp || !stack_used) 
494           {
495           /* because we're little endian, this is what it turns into. */
496           *p_argv = (void*) tregp;
497
498           p_argv++;
499           regp = tregp + z;
500           // if we read past the last core register, make sure we have not read
501           // from the stack before and continue reading after regp
502           if(regp > eo_regp)
503             {
504             if(stack_used)
505               {
506                 abort(); // we should never read past the end of the register
507                          // are if the stack is already in use
508               }
509             argp = regp;
510             }
511           if(regp >= eo_regp)
512             {
513             done_with_regs = 1;
514             stack_used = 1;
515             }
516           continue;
517           }
518       }
519     stack_used = 1;
520
521     argp = ffi_align(p_arg, argp);
522
523     z = (*p_arg)->size;
524
525     /* because we're little endian, this is what it turns into.   */
526
527     *p_argv = (void*) argp;
528
529     p_argv++;
530     argp += z;
531     }
532   
533   return;
534 }
535
536 /* How to make a trampoline.  */
537
538 extern unsigned int ffi_arm_trampoline[3];
539
540 #if FFI_EXEC_TRAMPOLINE_TABLE
541
542 #include <mach/mach.h>
543 #include <pthread.h>
544 #include <stdio.h>
545 #include <stdlib.h>
546
547 extern void *ffi_closure_trampoline_table_page;
548
549 typedef struct ffi_trampoline_table ffi_trampoline_table;
550 typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
551
552 struct ffi_trampoline_table {
553   /* contiguous writable and executable pages */
554   vm_address_t config_page;
555   vm_address_t trampoline_page;
556
557   /* free list tracking */
558   uint16_t free_count;
559   ffi_trampoline_table_entry *free_list;
560   ffi_trampoline_table_entry *free_list_pool;
561
562   ffi_trampoline_table *prev;
563   ffi_trampoline_table *next;
564 };
565
566 struct ffi_trampoline_table_entry {
567   void *(*trampoline)();
568   ffi_trampoline_table_entry *next;
569 };
570
571 /* Override the standard architecture trampoline size */
572 // XXX TODO - Fix
573 #undef FFI_TRAMPOLINE_SIZE
574 #define FFI_TRAMPOLINE_SIZE 12
575
576 /* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */
577 #define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080));
578
579 /* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */
580 #define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16
581
582 /* Total number of trampolines that fit in one trampoline table */
583 #define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE)
584
585 static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
586 static ffi_trampoline_table *ffi_trampoline_tables = NULL;
587
588 static ffi_trampoline_table *
589 ffi_trampoline_table_alloc ()
590 {
591   ffi_trampoline_table *table = NULL;
592
593   /* Loop until we can allocate two contiguous pages */
594   while (table == NULL) {
595     vm_address_t config_page = 0x0;
596     kern_return_t kt;
597
598     /* Try to allocate two pages */
599     kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE);
600     if (kt != KERN_SUCCESS) {
601       fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
602       break;
603     }
604
605     /* Now drop the second half of the allocation to make room for the trampoline table */
606     vm_address_t trampoline_page = config_page+PAGE_SIZE;
607     kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
608     if (kt != KERN_SUCCESS) {
609       fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
610       break;
611     }
612
613     /* Remap the trampoline table to directly follow the config page */
614     vm_prot_t cur_prot;
615     vm_prot_t max_prot;
616
617     kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE);
618
619     /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
620     if (kt != KERN_SUCCESS) {
621       /* Log unexpected failures */
622       if (kt != KERN_NO_SPACE) {
623         fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
624       }
625
626       vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
627       continue;
628     }
629
630     /* We have valid trampoline and config pages */
631     table = calloc (1, sizeof(ffi_trampoline_table));
632     table->free_count = FFI_TRAMPOLINE_COUNT;
633     table->config_page = config_page;
634     table->trampoline_page = trampoline_page;
635
636     /* Create and initialize the free list */
637     table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry));
638
639     uint16_t i;
640     for (i = 0; i < table->free_count; i++) {
641       ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
642       entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
643
644       if (i < table->free_count - 1)
645         entry->next = &table->free_list_pool[i+1];
646     }
647
648     table->free_list = table->free_list_pool;
649   }
650
651   return table;
652 }
653
654 void *
655 ffi_closure_alloc (size_t size, void **code)
656 {
657   /* Create the closure */
658   ffi_closure *closure = malloc(size);
659   if (closure == NULL)
660     return NULL;
661
662   pthread_mutex_lock(&ffi_trampoline_lock);
663
664   /* Check for an active trampoline table with available entries. */
665   ffi_trampoline_table *table = ffi_trampoline_tables;
666   if (table == NULL || table->free_list == NULL) {
667     table = ffi_trampoline_table_alloc ();
668     if (table == NULL) {
669       free(closure);
670       return NULL;
671     }
672
673     /* Insert the new table at the top of the list */
674     table->next = ffi_trampoline_tables;
675     if (table->next != NULL)
676         table->next->prev = table;
677
678     ffi_trampoline_tables = table;
679   }
680
681   /* Claim the free entry */
682   ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
683   ffi_trampoline_tables->free_list = entry->next;
684   ffi_trampoline_tables->free_count--;
685   entry->next = NULL;
686
687   pthread_mutex_unlock(&ffi_trampoline_lock);
688
689   /* Initialize the return values */
690   *code = entry->trampoline;
691   closure->trampoline_table = table;
692   closure->trampoline_table_entry = entry;
693
694   return closure;
695 }
696
697 void
698 ffi_closure_free (void *ptr)
699 {
700   ffi_closure *closure = ptr;
701
702   pthread_mutex_lock(&ffi_trampoline_lock);
703
704   /* Fetch the table and entry references */
705   ffi_trampoline_table *table = closure->trampoline_table;
706   ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
707
708   /* Return the entry to the free list */
709   entry->next = table->free_list;
710   table->free_list = entry;
711   table->free_count++;
712
713   /* If all trampolines within this table are free, and at least one other table exists, deallocate
714    * the table */
715   if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) {
716     /* Remove from the list */
717     if (table->prev != NULL)
718       table->prev->next = table->next;
719
720     if (table->next != NULL)
721       table->next->prev = table->prev;
722
723     /* Deallocate pages */
724     kern_return_t kt;
725     kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
726     if (kt != KERN_SUCCESS)
727       fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
728
729     kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
730     if (kt != KERN_SUCCESS)
731       fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__);
732
733     /* Deallocate free list */
734     free (table->free_list_pool);
735     free (table);
736   } else if (ffi_trampoline_tables != table) {
737     /* Otherwise, bump this table to the top of the list */
738     table->prev = NULL;
739     table->next = ffi_trampoline_tables;
740     if (ffi_trampoline_tables != NULL)
741       ffi_trampoline_tables->prev = table;
742
743     ffi_trampoline_tables = table;
744   }
745
746   pthread_mutex_unlock (&ffi_trampoline_lock);
747
748   /* Free the closure */
749   free (closure);
750 }
751
752 #else
753
754 #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)                              \
755 ({ unsigned char *__tramp = (unsigned char*)(TRAMP);                    \
756    unsigned int  __fun = (unsigned int)(FUN);                           \
757    unsigned int  __ctx = (unsigned int)(CTX);                           \
758    unsigned char *insns = (unsigned char *)(CTX);                       \
759    memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline);     \
760    *(unsigned int*) &__tramp[12] = __ctx;                               \
761    *(unsigned int*) &__tramp[16] = __fun;                               \
762    __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping.  */ \
763    __clear_cache(insns, insns + 3 * sizeof (unsigned int));             \
764                                                  /* Clear instruction   \
765                                                     mapping.  */        \
766  })
767
768 #endif
769
770 /* the cif must already be prep'ed */
771
772 ffi_status
773 ffi_prep_closure_loc (ffi_closure* closure,
774                       ffi_cif* cif,
775                       void (*fun)(ffi_cif*,void*,void**,void*),
776                       void *user_data,
777                       void *codeloc)
778 {
779   void (*closure_func)(ffi_closure*) = NULL;
780
781   if (cif->abi == FFI_SYSV)
782     closure_func = &ffi_closure_SYSV;
783 #ifdef __ARM_EABI__
784   else if (cif->abi == FFI_VFP)
785     closure_func = &ffi_closure_VFP;
786 #endif
787   else
788     return FFI_BAD_ABI;
789
790 #if FFI_EXEC_TRAMPOLINE_TABLE
791   void **config = FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc);
792   config[0] = closure;
793   config[1] = closure_func;
794 #else
795   FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
796                        closure_func,  \
797                        codeloc);
798 #endif
799
800   closure->cif  = cif;
801   closure->user_data = user_data;
802   closure->fun  = fun;
803
804   return FFI_OK;
805 }
806
807 /* Below are routines for VFP hard-float support. */
808
809 static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum)
810 {
811   switch (t->type)
812     {
813     case FFI_TYPE_FLOAT:
814     case FFI_TYPE_DOUBLE:
815       *elt = (int) t->type;
816       *elnum = 1;
817       return 1;
818
819     case FFI_TYPE_STRUCT_VFP_FLOAT:
820       *elt = FFI_TYPE_FLOAT;
821       *elnum = t->size / sizeof (float);
822       return 1;
823
824     case FFI_TYPE_STRUCT_VFP_DOUBLE:
825       *elt = FFI_TYPE_DOUBLE;
826       *elnum = t->size / sizeof (double);
827       return 1;
828
829     case FFI_TYPE_STRUCT:;
830       {
831         int base_elt = 0, total_elnum = 0;
832         ffi_type **el = t->elements;
833         while (*el)
834           {
835             int el_elt = 0, el_elnum = 0;
836             if (! rec_vfp_type_p (*el, &el_elt, &el_elnum)
837                 || (base_elt && base_elt != el_elt)
838                 || total_elnum + el_elnum > 4)
839               return 0;
840             base_elt = el_elt;
841             total_elnum += el_elnum;
842             el++;
843           }
844         *elnum = total_elnum;
845         *elt = base_elt;
846         return 1;
847       }
848     default: ;
849     }
850   return 0;
851 }
852
853 static int vfp_type_p (ffi_type *t)
854 {
855   int elt, elnum;
856   if (rec_vfp_type_p (t, &elt, &elnum))
857     {
858       if (t->type == FFI_TYPE_STRUCT)
859         {
860           if (elnum == 1)
861             t->type = elt;
862           else
863             t->type = (elt == FFI_TYPE_FLOAT
864                        ? FFI_TYPE_STRUCT_VFP_FLOAT
865                        : FFI_TYPE_STRUCT_VFP_DOUBLE);
866         }
867       return (int) t->type;
868     }
869   return 0;
870 }
871
872 static int place_vfp_arg (ffi_cif *cif, ffi_type *t)
873 {
874   int reg = cif->vfp_reg_free;
875   int nregs = t->size / sizeof (float);
876   int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT
877                 || t->type == FFI_TYPE_FLOAT) ? 1 : 2);
878   /* Align register number. */
879   if ((reg & 1) && align == 2)
880     reg++;
881   while (reg + nregs <= 16)
882     {
883       int s, new_used = 0;
884       for (s = reg; s < reg + nregs; s++)
885         {
886           new_used |= (1 << s);
887           if (cif->vfp_used & (1 << s))
888             {
889               reg += align;
890               goto next_reg;
891             }
892         }
893       /* Found regs to allocate. */
894       cif->vfp_used |= new_used;
895       cif->vfp_args[cif->vfp_nargs++] = reg;
896
897       /* Update vfp_reg_free. */
898       if (cif->vfp_used & (1 << cif->vfp_reg_free))
899         {
900           reg += nregs;
901           while (cif->vfp_used & (1 << reg))
902             reg += 1;
903           cif->vfp_reg_free = reg;
904         }
905       return 0;
906     next_reg: ;
907     }
908   // done, mark all regs as used
909   cif->vfp_reg_free = 16;
910   cif->vfp_used = 0xFFFF;
911   return 1;
912 }
913
914 static void layout_vfp_args (ffi_cif *cif)
915 {
916   int i;
917   /* Init VFP fields */
918   cif->vfp_used = 0;
919   cif->vfp_nargs = 0;
920   cif->vfp_reg_free = 0;
921   memset (cif->vfp_args, -1, 16); /* Init to -1. */
922
923   for (i = 0; i < cif->nargs; i++)
924     {
925       ffi_type *t = cif->arg_types[i];
926       if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1)
927         {
928           break;
929         }
930     }
931 }