LCOV - app.info - js/src/ctypes/libffi/src/x86/ffi.c

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