LCOV - code coverage report
Current view: directory - js/src/ctypes/libffi/src/x86 - ffi.c (source / functions) Found Hit Coverage
Test: app.info Lines: 88 0 0.0 %
Date: 2012-04-07 Functions: 6 0 0.0 %

       1                 : /* -----------------------------------------------------------------------
       2                 :    ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
       3                 :            Copyright (c) 2002  Ranjit Mathew
       4                 :            Copyright (c) 2002  Bo Thorsen
       5                 :            Copyright (c) 2002  Roger Sayle
       6                 :            Copyright (C) 2008  Free Software Foundation, Inc.
       7                 : 
       8                 :    x86 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                 : #if !defined(__x86_64__) || defined(_WIN64)
      32                 : 
      33                 : #ifdef _WIN64
      34                 : #include <windows.h>
      35                 : #endif
      36                 : 
      37                 : #include <ffi.h>
      38                 : #include <ffi_common.h>
      39                 : 
      40                 : #include <stdlib.h>
      41                 : 
      42                 : /* ffi_prep_args is called by the assembly routine once stack space
      43                 :    has been allocated for the function's arguments */
      44                 : 
      45               0 : void ffi_prep_args(char *stack, extended_cif *ecif)
      46                 : {
      47                 :   register unsigned int i;
      48                 :   register void **p_argv;
      49                 :   register char *argp;
      50                 :   register ffi_type **p_arg;
      51                 : 
      52               0 :   argp = stack;
      53                 : 
      54               0 :   if (ecif->cif->flags == FFI_TYPE_STRUCT
      55                 : #ifdef X86_WIN64
      56                 :       && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
      57                 :           && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
      58                 : #endif
      59                 :       )
      60                 :     {
      61               0 :       *(void **) argp = ecif->rvalue;
      62               0 :       argp += sizeof(void*);
      63                 :     }
      64                 : 
      65               0 :   p_argv = ecif->avalue;
      66                 : 
      67               0 :   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
      68                 :        i != 0;
      69               0 :        i--, p_arg++)
      70                 :     {
      71                 :       size_t z;
      72                 : 
      73                 :       /* Align if necessary */
      74               0 :       if ((sizeof(void*) - 1) & (size_t) argp)
      75               0 :         argp = (char *) ALIGN(argp, sizeof(void*));
      76                 : 
      77               0 :       z = (*p_arg)->size;
      78                 : #ifdef X86_WIN64
      79                 :       if (z > sizeof(ffi_arg)
      80                 :           || ((*p_arg)->type == FFI_TYPE_STRUCT
      81                 :               && (z != 1 && z != 2 && z != 4 && z != 8))
      82                 : #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
      83                 :           || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
      84                 : #endif
      85                 :           )
      86                 :         {
      87                 :           z = sizeof(ffi_arg);
      88                 :           *(void **)argp = *p_argv;
      89                 :         }
      90                 :       else if ((*p_arg)->type == FFI_TYPE_FLOAT)
      91                 :         {
      92                 :           memcpy(argp, *p_argv, z);
      93                 :         }
      94                 :       else
      95                 : #endif
      96               0 :       if (z < sizeof(ffi_arg))
      97                 :         {
      98               0 :           z = sizeof(ffi_arg);
      99               0 :           switch ((*p_arg)->type)
     100                 :             {
     101                 :             case FFI_TYPE_SINT8:
     102               0 :               *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
     103               0 :               break;
     104                 : 
     105                 :             case FFI_TYPE_UINT8:
     106               0 :               *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
     107               0 :               break;
     108                 : 
     109                 :             case FFI_TYPE_SINT16:
     110               0 :               *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
     111               0 :               break;
     112                 : 
     113                 :             case FFI_TYPE_UINT16:
     114               0 :               *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
     115               0 :               break;
     116                 : 
     117                 :             case FFI_TYPE_SINT32:
     118               0 :               *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
     119               0 :               break;
     120                 : 
     121                 :             case FFI_TYPE_UINT32:
     122               0 :               *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
     123               0 :               break;
     124                 : 
     125                 :             case FFI_TYPE_STRUCT:
     126               0 :               *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
     127               0 :               break;
     128                 : 
     129                 :             default:
     130               0 :               FFI_ASSERT(0);
     131                 :             }
     132                 :         }
     133                 :       else
     134                 :         {
     135               0 :           memcpy(argp, *p_argv, z);
     136                 :         }
     137               0 :       p_argv++;
     138                 : #ifdef X86_WIN64
     139                 :       argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
     140                 : #else
     141               0 :       argp += z;
     142                 : #endif
     143                 :     }
     144                 :   
     145                 :   return;
     146                 : }
     147                 : 
     148                 : /* Perform machine dependent cif processing */
     149               0 : ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
     150                 : {
     151                 :   unsigned int i;
     152                 :   ffi_type **ptr;
     153                 : 
     154                 :   /* Set the return type flag */
     155               0 :   switch (cif->rtype->type)
     156                 :     {
     157                 :     case FFI_TYPE_VOID:
     158                 :     case FFI_TYPE_UINT8:
     159                 :     case FFI_TYPE_UINT16:
     160                 :     case FFI_TYPE_SINT8:
     161                 :     case FFI_TYPE_SINT16:
     162                 : #ifdef X86_WIN64
     163                 :     case FFI_TYPE_UINT32:
     164                 :     case FFI_TYPE_SINT32:
     165                 : #endif
     166                 :     case FFI_TYPE_SINT64:
     167                 :     case FFI_TYPE_FLOAT:
     168                 :     case FFI_TYPE_DOUBLE:
     169                 : #ifndef X86_WIN64
     170                 : #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
     171                 :     case FFI_TYPE_LONGDOUBLE:
     172                 : #endif
     173                 : #endif
     174               0 :       cif->flags = (unsigned) cif->rtype->type;
     175               0 :       break;
     176                 : 
     177                 :     case FFI_TYPE_UINT64:
     178                 : #ifdef X86_WIN64
     179                 :     case FFI_TYPE_POINTER:
     180                 : #endif
     181               0 :       cif->flags = FFI_TYPE_SINT64;
     182               0 :       break;
     183                 : 
     184                 :     case FFI_TYPE_STRUCT:
     185                 : #ifndef X86
     186                 :       if (cif->rtype->size == 1)
     187                 :         {
     188                 :           cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
     189                 :         }
     190                 :       else if (cif->rtype->size == 2)
     191                 :         {
     192                 :           cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
     193                 :         }
     194                 :       else if (cif->rtype->size == 4)
     195                 :         {
     196                 : #ifdef X86_WIN64
     197                 :           cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
     198                 : #else
     199                 :           cif->flags = FFI_TYPE_INT; /* same as int type */
     200                 : #endif
     201                 :         }
     202                 :       else if (cif->rtype->size == 8)
     203                 :         {
     204                 :           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
     205                 :         }
     206                 :       else
     207                 : #endif
     208                 :         {
     209               0 :           cif->flags = FFI_TYPE_STRUCT;
     210                 :           /* allocate space for return value pointer */
     211               0 :           cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
     212                 :         }
     213               0 :       break;
     214                 : 
     215                 :     default:
     216                 : #ifdef X86_WIN64
     217                 :       cif->flags = FFI_TYPE_SINT64;
     218                 :       break;
     219                 :     case FFI_TYPE_INT:
     220                 :       cif->flags = FFI_TYPE_SINT32;
     221                 : #else
     222               0 :       cif->flags = FFI_TYPE_INT;
     223                 : #endif
     224               0 :       break;
     225                 :     }
     226                 : 
     227               0 :   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
     228                 :     {
     229               0 :       if (((*ptr)->alignment - 1) & cif->bytes)
     230               0 :         cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
     231               0 :       cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
     232                 :     }
     233                 : 
     234                 : #ifdef X86_WIN64
     235                 :   /* ensure space for storing four registers */
     236                 :   cif->bytes += 4 * sizeof(ffi_arg);
     237                 : #endif
     238                 : 
     239                 : #ifdef X86_DARWIN
     240                 :   cif->bytes = (cif->bytes + 15) & ~0xF;
     241                 : #endif
     242                 : 
     243               0 :   return FFI_OK;
     244                 : }
     245                 : 
     246                 : #ifdef X86_WIN64
     247                 : extern int
     248                 : ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
     249                 :                unsigned, unsigned, unsigned *, void (*fn)(void));
     250                 : #elif defined(X86_WIN32)
     251                 : extern void
     252                 : ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
     253                 :                unsigned, unsigned, unsigned *, void (*fn)(void));
     254                 : #else
     255                 : extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
     256                 :                           unsigned, unsigned, unsigned *, void (*fn)(void));
     257                 : #endif
     258                 : 
     259               0 : void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     260                 : {
     261                 :   extended_cif ecif;
     262                 : 
     263               0 :   ecif.cif = cif;
     264               0 :   ecif.avalue = avalue;
     265                 :   
     266                 :   /* If the return value is a struct and we don't have a return */
     267                 :   /* value address then we need to make one                     */
     268                 : 
     269                 : #ifdef X86_WIN64
     270                 :   if (rvalue == NULL
     271                 :       && cif->flags == FFI_TYPE_STRUCT
     272                 :       && cif->rtype->size != 1 && cif->rtype->size != 2
     273                 :       && cif->rtype->size != 4 && cif->rtype->size != 8)
     274                 :     {
     275                 :       ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
     276                 :     }
     277                 : #else
     278               0 :   if (rvalue == NULL
     279               0 :       && cif->flags == FFI_TYPE_STRUCT)
     280                 :     {
     281               0 :       ecif.rvalue = alloca(cif->rtype->size);
     282                 :     }
     283                 : #endif
     284                 :   else
     285               0 :     ecif.rvalue = rvalue;
     286                 :     
     287                 :   
     288               0 :   switch (cif->abi) 
     289                 :     {
     290                 : #ifdef X86_WIN64
     291                 :     case FFI_WIN64:
     292                 :       ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
     293                 :                      cif->flags, ecif.rvalue, fn);
     294                 :       break;
     295                 : #elif defined(X86_WIN32)
     296                 :     case FFI_SYSV:
     297                 :     case FFI_STDCALL:
     298                 :       ffi_call_win32(ffi_prep_args, &ecif, cif->bytes, cif->flags,
     299                 :                      ecif.rvalue, fn);
     300                 :       break;
     301                 : #else
     302                 :     case FFI_SYSV:
     303               0 :       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
     304                 :                     fn);
     305               0 :       break;
     306                 : #endif
     307                 :     default:
     308               0 :       FFI_ASSERT(0);
     309               0 :       break;
     310                 :     }
     311               0 : }
     312                 : 
     313                 : 
     314                 : /** private members **/
     315                 : 
     316                 : /* The following __attribute__((regparm(1))) decorations will have no effect
     317                 :    on MSVC - standard cdecl convention applies. */
     318                 : static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
     319                 :                                          void** args, ffi_cif* cif);
     320                 : void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
     321                 :      __attribute__ ((regparm(1)));
     322                 : unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
     323                 :      __attribute__ ((regparm(1)));
     324                 : void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
     325                 :      __attribute__ ((regparm(1)));
     326                 : #ifdef X86_WIN32
     327                 : void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
     328                 :      __attribute__ ((regparm(1)));
     329                 : #endif
     330                 : #ifdef X86_WIN64
     331                 : void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
     332                 : #endif
     333                 : 
     334                 : /* This function is jumped to by the trampoline */
     335                 : 
     336                 : #ifdef X86_WIN64
     337                 : void * FFI_HIDDEN
     338                 : ffi_closure_win64_inner (ffi_closure *closure, void *args) {
     339                 :   ffi_cif       *cif;
     340                 :   void         **arg_area;
     341                 :   void          *result;
     342                 :   void          *resp = &result;
     343                 : 
     344                 :   cif         = closure->cif;
     345                 :   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
     346                 : 
     347                 :   /* this call will initialize ARG_AREA, such that each
     348                 :    * element in that array points to the corresponding 
     349                 :    * value on the stack; and if the function returns
     350                 :    * a structure, it will change RESP to point to the
     351                 :    * structure return address.  */
     352                 : 
     353                 :   ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
     354                 :   
     355                 :   (closure->fun) (cif, resp, arg_area, closure->user_data);
     356                 : 
     357                 :   /* The result is returned in rax.  This does the right thing for
     358                 :      result types except for floats; we have to 'mov xmm0, rax' in the
     359                 :      caller to correct this.
     360                 :      TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
     361                 :   */
     362                 :   return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
     363                 : }
     364                 : 
     365                 : #else
     366                 : unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
     367               0 : ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
     368                 : {
     369                 :   /* our various things...  */
     370                 :   ffi_cif       *cif;
     371                 :   void         **arg_area;
     372                 : 
     373               0 :   cif         = closure->cif;
     374               0 :   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
     375                 : 
     376                 :   /* this call will initialize ARG_AREA, such that each
     377                 :    * element in that array points to the corresponding 
     378                 :    * value on the stack; and if the function returns
     379                 :    * a structure, it will change RESP to point to the
     380                 :    * structure return address.  */
     381                 : 
     382               0 :   ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
     383                 : 
     384               0 :   (closure->fun) (cif, *respp, arg_area, closure->user_data);
     385                 : 
     386               0 :   return cif->flags;
     387                 : }
     388                 : #endif /* !X86_WIN64 */
     389                 : 
     390                 : static void
     391               0 : ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
     392                 :                             ffi_cif *cif)
     393                 : {
     394                 :   register unsigned int i;
     395                 :   register void **p_argv;
     396                 :   register char *argp;
     397                 :   register ffi_type **p_arg;
     398                 : 
     399               0 :   argp = stack;
     400                 : 
     401                 : #ifdef X86_WIN64
     402                 :   if (cif->rtype->size > sizeof(ffi_arg)
     403                 :       || (cif->flags == FFI_TYPE_STRUCT
     404                 :           && (cif->rtype->size != 1 && cif->rtype->size != 2
     405                 :               && cif->rtype->size != 4 && cif->rtype->size != 8))) {
     406                 :     *rvalue = *(void **) argp;
     407                 :     argp += sizeof(void *);
     408                 :   }
     409                 : #else
     410               0 :   if ( cif->flags == FFI_TYPE_STRUCT ) {
     411               0 :     *rvalue = *(void **) argp;
     412               0 :     argp += sizeof(void *);
     413                 :   }
     414                 : #endif
     415                 : 
     416               0 :   p_argv = avalue;
     417                 : 
     418               0 :   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
     419                 :     {
     420                 :       size_t z;
     421                 : 
     422                 :       /* Align if necessary */
     423               0 :       if ((sizeof(void*) - 1) & (size_t) argp) {
     424               0 :         argp = (char *) ALIGN(argp, sizeof(void*));
     425                 :       }
     426                 : 
     427                 : #ifdef X86_WIN64
     428                 :       if ((*p_arg)->size > sizeof(ffi_arg)
     429                 :           || ((*p_arg)->type == FFI_TYPE_STRUCT
     430                 :               && ((*p_arg)->size != 1 && (*p_arg)->size != 2
     431                 :                   && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
     432                 :         {
     433                 :           z = sizeof(void *);
     434                 :           *p_argv = *(void **)argp;
     435                 :         }
     436                 :       else
     437                 : #endif
     438                 :         {
     439               0 :           z = (*p_arg)->size;
     440                 :           
     441                 :           /* because we're little endian, this is what it turns into.   */
     442                 :           
     443               0 :           *p_argv = (void*) argp;
     444                 :         }
     445                 :           
     446               0 :       p_argv++;
     447                 : #ifdef X86_WIN64
     448                 :       argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
     449                 : #else
     450               0 :       argp += z;
     451                 : #endif
     452                 :     }
     453                 :   
     454                 :   return;
     455                 : }
     456                 : 
     457                 : #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
     458                 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     459                 :    void*  __fun = (void*)(FUN); \
     460                 :    void*  __ctx = (void*)(CTX); \
     461                 :    *(unsigned char*) &__tramp[0] = 0x41; \
     462                 :    *(unsigned char*) &__tramp[1] = 0xbb; \
     463                 :    *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
     464                 :    *(unsigned char*) &__tramp[6] = 0x48; \
     465                 :    *(unsigned char*) &__tramp[7] = 0xb8; \
     466                 :    *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
     467                 :    *(unsigned char *)  &__tramp[16] = 0x49; \
     468                 :    *(unsigned char *)  &__tramp[17] = 0xba; \
     469                 :    *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
     470                 :    *(unsigned char *)  &__tramp[26] = 0x41; \
     471                 :    *(unsigned char *)  &__tramp[27] = 0xff; \
     472                 :    *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
     473                 :  }
     474                 : 
     475                 : /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
     476                 : 
     477                 : #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
     478                 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     479                 :    unsigned int  __fun = (unsigned int)(FUN); \
     480                 :    unsigned int  __ctx = (unsigned int)(CTX); \
     481                 :    unsigned int  __dis = __fun - (__ctx + 10);  \
     482                 :    *(unsigned char*) &__tramp[0] = 0xb8; \
     483                 :    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
     484                 :    *(unsigned char *)  &__tramp[5] = 0xe9; \
     485                 :    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
     486                 :  }
     487                 : 
     488                 : #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
     489                 : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     490                 :    unsigned int  __fun = (unsigned int)(FUN); \
     491                 :    unsigned int  __ctx = (unsigned int)(CTX); \
     492                 :    unsigned int  __dis = __fun - (__ctx + 10); \
     493                 :    unsigned short __size = (unsigned short)(SIZE); \
     494                 :    *(unsigned char*) &__tramp[0] = 0xb8; \
     495                 :    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
     496                 :    *(unsigned char *)  &__tramp[5] = 0xe8; \
     497                 :    *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
     498                 :    *(unsigned char *)  &__tramp[10] = 0xc2; \
     499                 :    *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
     500                 :  }
     501                 : 
     502                 : /* the cif must already be prep'ed */
     503                 : 
     504                 : ffi_status
     505               0 : ffi_prep_closure_loc (ffi_closure* closure,
     506                 :                       ffi_cif* cif,
     507                 :                       void (*fun)(ffi_cif*,void*,void**,void*),
     508                 :                       void *user_data,
     509                 :                       void *codeloc)
     510                 : {
     511                 : #ifdef X86_WIN64
     512                 : #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
     513                 : #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
     514                 :   if (cif->abi == FFI_WIN64) 
     515                 :     {
     516                 :       int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
     517                 :       FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
     518                 :                                  &ffi_closure_win64,
     519                 :                                  codeloc, mask);
     520                 :       /* make sure we can execute here */
     521                 :     }
     522                 : #else
     523               0 :   if (cif->abi == FFI_SYSV)
     524                 :     {
     525               0 :       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
     526                 :                            &ffi_closure_SYSV,
     527                 :                            (void*)codeloc);
     528                 :     }
     529                 : #ifdef X86_WIN32
     530                 :   else if (cif->abi == FFI_STDCALL)
     531                 :     {
     532                 :       FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
     533                 :                                    &ffi_closure_STDCALL,
     534                 :                                    (void*)codeloc, cif->bytes);
     535                 :     }
     536                 : #endif /* X86_WIN32 */
     537                 : #endif /* !X86_WIN64 */
     538                 :   else
     539                 :     {
     540               0 :       return FFI_BAD_ABI;
     541                 :     }
     542                 :     
     543               0 :   closure->cif  = cif;
     544               0 :   closure->user_data = user_data;
     545               0 :   closure->fun  = fun;
     546                 : 
     547               0 :   return FFI_OK;
     548                 : }
     549                 : 
     550                 : /* ------- Native raw API support -------------------------------- */
     551                 : 
     552                 : #if !FFI_NO_RAW_API
     553                 : 
     554                 : ffi_status
     555                 : ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
     556                 :                           ffi_cif* cif,
     557                 :                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
     558                 :                           void *user_data,
     559                 :                           void *codeloc)
     560                 : {
     561                 :   int i;
     562                 : 
     563                 :   if (cif->abi != FFI_SYSV) {
     564                 :     return FFI_BAD_ABI;
     565                 :   }
     566                 : 
     567                 :   /* we currently don't support certain kinds of arguments for raw
     568                 :      closures.  This should be implemented by a separate assembly
     569                 :      language routine, since it would require argument processing,
     570                 :      something we don't do now for performance.  */
     571                 : 
     572                 :   for (i = cif->nargs-1; i >= 0; i--)
     573                 :     {
     574                 :       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
     575                 :       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
     576                 :     }
     577                 :   
     578                 : 
     579                 :   FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
     580                 :                        codeloc);
     581                 :     
     582                 :   closure->cif  = cif;
     583                 :   closure->user_data = user_data;
     584                 :   closure->fun  = fun;
     585                 : 
     586                 :   return FFI_OK;
     587                 : }
     588                 : 
     589                 : static void 
     590                 : ffi_prep_args_raw(char *stack, extended_cif *ecif)
     591                 : {
     592                 :   memcpy (stack, ecif->avalue, ecif->cif->bytes);
     593                 : }
     594                 : 
     595                 : /* we borrow this routine from libffi (it must be changed, though, to
     596                 :  * actually call the function passed in the first argument.  as of
     597                 :  * libffi-1.20, this is not the case.)
     598                 :  */
     599                 : 
     600                 : void
     601                 : ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
     602                 : {
     603                 :   extended_cif ecif;
     604                 :   void **avalue = (void **)fake_avalue;
     605                 : 
     606                 :   ecif.cif = cif;
     607                 :   ecif.avalue = avalue;
     608                 :   
     609                 :   /* If the return value is a struct and we don't have a return */
     610                 :   /* value address then we need to make one                     */
     611                 : 
     612                 :   if ((rvalue == NULL) && 
     613                 :       (cif->rtype->type == FFI_TYPE_STRUCT))
     614                 :     {
     615                 :       ecif.rvalue = alloca(cif->rtype->size);
     616                 :     }
     617                 :   else
     618                 :     ecif.rvalue = rvalue;
     619                 :     
     620                 :   
     621                 :   switch (cif->abi) 
     622                 :     {
     623                 : #ifdef X86_WIN32
     624                 :     case FFI_SYSV:
     625                 :     case FFI_STDCALL:
     626                 :       ffi_call_win32(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
     627                 :                      ecif.rvalue, fn);
     628                 :       break;
     629                 : #else
     630                 :     case FFI_SYSV:
     631                 :       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
     632                 :                     ecif.rvalue, fn);
     633                 :       break;
     634                 : #endif
     635                 :     default:
     636                 :       FFI_ASSERT(0);
     637                 :       break;
     638                 :     }
     639                 : }
     640                 : 
     641                 : #endif
     642                 : 
     643                 : #endif /* !__x86_64__  || X86_WIN64 */
     644                 : 

Generated by: LCOV version 1.7