Home | History | Annotate | Download | only in arm
      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   register unsigned int i, vi = 0;
    158   register void **p_argv;
    159   register char *argp, *regp, *eo_regp;
    160   register ffi_type **p_arg;
    161   char stack_used = 0;
    162   char done_with_regs = 0;
    163   char is_vfp_type;
    164 
    165   // make sure we are using FFI_VFP
    166   FFI_ASSERT(ecif->cif->abi == FFI_VFP);
    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   short 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 }
    932