LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules/_ctypes/libffi/src/x86 - ffi.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 118 0.0 %
Date: 2012-12-17 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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, 2010  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             : #ifdef X86_WIN32
      52             :   size_t p_stack_args[2];
      53             :   void *p_stack_data[2];
      54             :   char *argp2 = stack;
      55             :   int stack_args_count = 0;
      56             :   int cabi = ecif->cif->abi;
      57             : #endif
      58             : 
      59           0 :   argp = stack;
      60             : 
      61           0 :   if ((ecif->cif->flags == FFI_TYPE_STRUCT
      62           0 :        || ecif->cif->flags == FFI_TYPE_MS_STRUCT)
      63             : #ifdef X86_WIN64
      64             :       && (ecif->cif->rtype->size != 1 && ecif->cif->rtype->size != 2
      65             :           && ecif->cif->rtype->size != 4 && ecif->cif->rtype->size != 8)
      66             : #endif
      67             :       )
      68             :     {
      69           0 :       *(void **) argp = ecif->rvalue;
      70             : #ifdef X86_WIN32
      71             :       /* For fastcall/thiscall this is first register-passed
      72             :          argument.  */
      73             :       if (cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
      74             :         {
      75             :           p_stack_args[stack_args_count] = sizeof (void*);
      76             :           p_stack_data[stack_args_count] = argp;
      77             :           ++stack_args_count;
      78             :         }
      79             : #endif
      80           0 :       argp += sizeof(void*);
      81             :     }
      82             : 
      83           0 :   p_argv = ecif->avalue;
      84             : 
      85           0 :   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
      86             :        i != 0;
      87           0 :        i--, p_arg++)
      88             :     {
      89             :       size_t z;
      90             : 
      91             :       /* Align if necessary */
      92           0 :       if ((sizeof(void*) - 1) & (size_t) argp)
      93           0 :         argp = (char *) ALIGN(argp, sizeof(void*));
      94             : 
      95           0 :       z = (*p_arg)->size;
      96             : #ifdef X86_WIN64
      97             :       if (z > sizeof(ffi_arg)
      98             :           || ((*p_arg)->type == FFI_TYPE_STRUCT
      99             :               && (z != 1 && z != 2 && z != 4 && z != 8))
     100             : #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
     101             :           || ((*p_arg)->type == FFI_TYPE_LONGDOUBLE)
     102             : #endif
     103             :           )
     104             :         {
     105             :           z = sizeof(ffi_arg);
     106             :           *(void **)argp = *p_argv;
     107             :         }
     108             :       else if ((*p_arg)->type == FFI_TYPE_FLOAT)
     109             :         {
     110             :           memcpy(argp, *p_argv, z);
     111             :         }
     112             :       else
     113             : #endif
     114           0 :       if (z < sizeof(ffi_arg))
     115             :         {
     116           0 :           z = sizeof(ffi_arg);
     117           0 :           switch ((*p_arg)->type)
     118             :             {
     119             :             case FFI_TYPE_SINT8:
     120           0 :               *(ffi_sarg *) argp = (ffi_sarg)*(SINT8 *)(* p_argv);
     121           0 :               break;
     122             : 
     123             :             case FFI_TYPE_UINT8:
     124           0 :               *(ffi_arg *) argp = (ffi_arg)*(UINT8 *)(* p_argv);
     125           0 :               break;
     126             : 
     127             :             case FFI_TYPE_SINT16:
     128           0 :               *(ffi_sarg *) argp = (ffi_sarg)*(SINT16 *)(* p_argv);
     129           0 :               break;
     130             : 
     131             :             case FFI_TYPE_UINT16:
     132           0 :               *(ffi_arg *) argp = (ffi_arg)*(UINT16 *)(* p_argv);
     133           0 :               break;
     134             : 
     135             :             case FFI_TYPE_SINT32:
     136           0 :               *(ffi_sarg *) argp = (ffi_sarg)*(SINT32 *)(* p_argv);
     137           0 :               break;
     138             : 
     139             :             case FFI_TYPE_UINT32:
     140           0 :               *(ffi_arg *) argp = (ffi_arg)*(UINT32 *)(* p_argv);
     141           0 :               break;
     142             : 
     143             :             case FFI_TYPE_STRUCT:
     144           0 :               *(ffi_arg *) argp = *(ffi_arg *)(* p_argv);
     145           0 :               break;
     146             : 
     147             :             default:
     148             :               FFI_ASSERT(0);
     149             :             }
     150             :         }
     151             :       else
     152             :         {
     153           0 :           memcpy(argp, *p_argv, z);
     154             :         }
     155             : 
     156             : #ifdef X86_WIN32
     157             :     /* For thiscall/fastcall convention register-passed arguments
     158             :        are the first two none-floating-point arguments with a size
     159             :        smaller or equal to sizeof (void*).  */
     160             :     if ((cabi == FFI_THISCALL && stack_args_count < 1)
     161             :         || (cabi == FFI_FASTCALL && stack_args_count < 2))
     162             :       {
     163             :         if (z <= 4
     164             :             && ((*p_arg)->type != FFI_TYPE_FLOAT
     165             :                 && (*p_arg)->type != FFI_TYPE_STRUCT))
     166             :           {
     167             :             p_stack_args[stack_args_count] = z;
     168             :             p_stack_data[stack_args_count] = argp;
     169             :             ++stack_args_count;
     170             :           }
     171             :       }
     172             : #endif
     173           0 :       p_argv++;
     174             : #ifdef X86_WIN64
     175             :       argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
     176             : #else
     177           0 :       argp += z;
     178             : #endif
     179             :     }
     180             : 
     181             : #ifdef X86_WIN32
     182             :   /* We need to move the register-passed arguments for thiscall/fastcall
     183             :      on top of stack, so that those can be moved to registers ecx/edx by
     184             :      call-handler.  */
     185             :   if (stack_args_count > 0)
     186             :     {
     187             :       size_t zz = (p_stack_args[0] + 3) & ~3;
     188             :       char *h;
     189             : 
     190             :       /* Move first argument to top-stack position.  */
     191             :       if (p_stack_data[0] != argp2)
     192             :         {
     193             :           h = alloca (zz + 1);
     194             :           memcpy (h, p_stack_data[0], zz);
     195             :           memmove (argp2 + zz, argp2,
     196             :                    (size_t) ((char *) p_stack_data[0] - (char*)argp2));
     197             :           memcpy (argp2, h, zz);
     198             :         }
     199             : 
     200             :       argp2 += zz;
     201             :       --stack_args_count;
     202             :       if (zz > 4)
     203             :         stack_args_count = 0;
     204             : 
     205             :       /* If we have a second argument, then move it on top
     206             :          after the first one.  */
     207             :       if (stack_args_count > 0 && p_stack_data[1] != argp2)
     208             :         {
     209             :           zz = p_stack_args[1];
     210             :           zz = (zz + 3) & ~3;
     211             :           h = alloca (zz + 1);
     212             :           h = alloca (zz + 1);
     213             :           memcpy (h, p_stack_data[1], zz);
     214             :           memmove (argp2 + zz, argp2, (size_t) ((char*) p_stack_data[1] - (char*)argp2));
     215             :           memcpy (argp2, h, zz);
     216             :         }
     217             :     }
     218             : #endif
     219           0 :   return;
     220             : }
     221             : 
     222             : /* Perform machine dependent cif processing */
     223           0 : ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
     224             : {
     225             :   unsigned int i;
     226             :   ffi_type **ptr;
     227             : 
     228             :   /* Set the return type flag */
     229           0 :   switch (cif->rtype->type)
     230             :     {
     231             :     case FFI_TYPE_VOID:
     232             :     case FFI_TYPE_UINT8:
     233             :     case FFI_TYPE_UINT16:
     234             :     case FFI_TYPE_SINT8:
     235             :     case FFI_TYPE_SINT16:
     236             : #ifdef X86_WIN64
     237             :     case FFI_TYPE_UINT32:
     238             :     case FFI_TYPE_SINT32:
     239             : #endif
     240             :     case FFI_TYPE_SINT64:
     241             :     case FFI_TYPE_FLOAT:
     242             :     case FFI_TYPE_DOUBLE:
     243             : #ifndef X86_WIN64
     244             : #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
     245             :     case FFI_TYPE_LONGDOUBLE:
     246             : #endif
     247             : #endif
     248           0 :       cif->flags = (unsigned) cif->rtype->type;
     249           0 :       break;
     250             : 
     251             :     case FFI_TYPE_UINT64:
     252             : #ifdef X86_WIN64
     253             :     case FFI_TYPE_POINTER:
     254             : #endif
     255           0 :       cif->flags = FFI_TYPE_SINT64;
     256           0 :       break;
     257             : 
     258             :     case FFI_TYPE_STRUCT:
     259             : #ifndef X86
     260             :       if (cif->rtype->size == 1)
     261             :         {
     262             :           cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
     263             :         }
     264             :       else if (cif->rtype->size == 2)
     265             :         {
     266             :           cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
     267             :         }
     268             :       else if (cif->rtype->size == 4)
     269             :         {
     270             : #ifdef X86_WIN64
     271             :           cif->flags = FFI_TYPE_SMALL_STRUCT_4B;
     272             : #else
     273             :           cif->flags = FFI_TYPE_INT; /* same as int type */
     274             : #endif
     275             :         }
     276             :       else if (cif->rtype->size == 8)
     277             :         {
     278             :           cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
     279             :         }
     280             :       else
     281             : #endif
     282             :         {
     283             : #ifdef X86_WIN32
     284             :           if (cif->abi == FFI_MS_CDECL)
     285             :             cif->flags = FFI_TYPE_MS_STRUCT;
     286             :           else
     287             : #endif
     288           0 :             cif->flags = FFI_TYPE_STRUCT;
     289             :           /* allocate space for return value pointer */
     290           0 :           cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG);
     291             :         }
     292           0 :       break;
     293             : 
     294             :     default:
     295             : #ifdef X86_WIN64
     296             :       cif->flags = FFI_TYPE_SINT64;
     297             :       break;
     298             :     case FFI_TYPE_INT:
     299             :       cif->flags = FFI_TYPE_SINT32;
     300             : #else
     301           0 :       cif->flags = FFI_TYPE_INT;
     302             : #endif
     303           0 :       break;
     304             :     }
     305             : 
     306           0 :   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
     307             :     {
     308           0 :       if (((*ptr)->alignment - 1) & cif->bytes)
     309           0 :         cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment);
     310           0 :       cif->bytes += ALIGN((*ptr)->size, FFI_SIZEOF_ARG);
     311             :     }
     312             : 
     313             : #ifdef X86_WIN64
     314             :   /* ensure space for storing four registers */
     315             :   cif->bytes += 4 * sizeof(ffi_arg);
     316             : #endif
     317             : 
     318             : #ifdef X86_DARWIN
     319             :   cif->bytes = (cif->bytes + 15) & ~0xF;
     320             : #endif
     321             : 
     322           0 :   return FFI_OK;
     323             : }
     324             : 
     325             : #ifdef X86_WIN64
     326             : extern int
     327             : ffi_call_win64(void (*)(char *, extended_cif *), extended_cif *,
     328             :                unsigned, unsigned, unsigned *, void (*fn)(void));
     329             : #elif defined(X86_WIN32)
     330             : extern void
     331             : ffi_call_win32(void (*)(char *, extended_cif *), extended_cif *,
     332             :                unsigned, unsigned, unsigned, unsigned *, void (*fn)(void));
     333             : #else
     334             : extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
     335             :                           unsigned, unsigned, unsigned *, void (*fn)(void));
     336             : #endif
     337             : 
     338           0 : void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
     339             : {
     340             :   extended_cif ecif;
     341             : 
     342           0 :   ecif.cif = cif;
     343           0 :   ecif.avalue = avalue;
     344             :   
     345             :   /* If the return value is a struct and we don't have a return */
     346             :   /* value address then we need to make one                     */
     347             : 
     348             : #ifdef X86_WIN64
     349             :   if (rvalue == NULL
     350             :       && cif->flags == FFI_TYPE_STRUCT
     351             :       && cif->rtype->size != 1 && cif->rtype->size != 2
     352             :       && cif->rtype->size != 4 && cif->rtype->size != 8)
     353             :     {
     354             :       ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF);
     355             :     }
     356             : #else
     357           0 :   if (rvalue == NULL
     358           0 :       && (cif->flags == FFI_TYPE_STRUCT
     359           0 :           || cif->flags == FFI_TYPE_MS_STRUCT))
     360             :     {
     361           0 :       ecif.rvalue = alloca(cif->rtype->size);
     362             :     }
     363             : #endif
     364             :   else
     365           0 :     ecif.rvalue = rvalue;
     366             :     
     367             :   
     368           0 :   switch (cif->abi) 
     369             :     {
     370             : #ifdef X86_WIN64
     371             :     case FFI_WIN64:
     372             :       ffi_call_win64(ffi_prep_args, &ecif, cif->bytes,
     373             :                      cif->flags, ecif.rvalue, fn);
     374             :       break;
     375             : #elif defined(X86_WIN32)
     376             :     case FFI_SYSV:
     377             :     case FFI_STDCALL:
     378             :     case FFI_MS_CDECL:
     379             :       ffi_call_win32(ffi_prep_args, &ecif, cif->abi, cif->bytes, cif->flags,
     380             :                      ecif.rvalue, fn);
     381             :       break;
     382             :     case FFI_THISCALL:
     383             :     case FFI_FASTCALL:
     384             :       {
     385             :         unsigned int abi = cif->abi;
     386             :         unsigned int i, passed_regs = 0;
     387             : 
     388             :         if (cif->flags == FFI_TYPE_STRUCT)
     389             :           ++passed_regs;
     390             : 
     391             :         for (i=0; i < cif->nargs && passed_regs < 2;i++)
     392             :           {
     393             :             size_t sz;
     394             : 
     395             :             if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
     396             :                 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
     397             :               continue;
     398             :             sz = (cif->arg_types[i]->size + 3) & ~3;
     399             :             if (sz == 0 || sz > 4)
     400             :               continue;
     401             :             ++passed_regs;
     402             :           }
     403             :         if (passed_regs < 2 && abi == FFI_FASTCALL)
     404             :           abi = FFI_THISCALL;
     405             :         if (passed_regs < 1 && abi == FFI_THISCALL)
     406             :           abi = FFI_STDCALL;
     407             :         ffi_call_win32(ffi_prep_args, &ecif, abi, cif->bytes, cif->flags,
     408             :                        ecif.rvalue, fn);
     409             :       }
     410             :       break;
     411             : #else
     412             :     case FFI_SYSV:
     413           0 :       ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
     414             :                     fn);
     415           0 :       break;
     416             : #endif
     417             :     default:
     418             :       FFI_ASSERT(0);
     419           0 :       break;
     420             :     }
     421           0 : }
     422             : 
     423             : 
     424             : /** private members **/
     425             : 
     426             : /* The following __attribute__((regparm(1))) decorations will have no effect
     427             :    on MSVC - standard cdecl convention applies. */
     428             : static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
     429             :                                          void** args, ffi_cif* cif);
     430             : void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
     431             :      __attribute__ ((regparm(1)));
     432             : unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
     433             :      __attribute__ ((regparm(1)));
     434             : void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
     435             :      __attribute__ ((regparm(1)));
     436             : #ifdef X86_WIN32
     437             : void FFI_HIDDEN ffi_closure_raw_THISCALL (ffi_raw_closure *)
     438             :      __attribute__ ((regparm(1)));
     439             : void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
     440             :      __attribute__ ((regparm(1)));
     441             : void FFI_HIDDEN ffi_closure_THISCALL (ffi_closure *)
     442             :      __attribute__ ((regparm(1)));
     443             : #endif
     444             : #ifdef X86_WIN64
     445             : void FFI_HIDDEN ffi_closure_win64 (ffi_closure *);
     446             : #endif
     447             : 
     448             : /* This function is jumped to by the trampoline */
     449             : 
     450             : #ifdef X86_WIN64
     451             : void * FFI_HIDDEN
     452             : ffi_closure_win64_inner (ffi_closure *closure, void *args) {
     453             :   ffi_cif       *cif;
     454             :   void         **arg_area;
     455             :   void          *result;
     456             :   void          *resp = &result;
     457             : 
     458             :   cif         = closure->cif;
     459             :   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
     460             : 
     461             :   /* this call will initialize ARG_AREA, such that each
     462             :    * element in that array points to the corresponding 
     463             :    * value on the stack; and if the function returns
     464             :    * a structure, it will change RESP to point to the
     465             :    * structure return address.  */
     466             : 
     467             :   ffi_prep_incoming_args_SYSV(args, &resp, arg_area, cif);
     468             :   
     469             :   (closure->fun) (cif, resp, arg_area, closure->user_data);
     470             : 
     471             :   /* The result is returned in rax.  This does the right thing for
     472             :      result types except for floats; we have to 'mov xmm0, rax' in the
     473             :      caller to correct this.
     474             :      TODO: structure sizes of 3 5 6 7 are returned by reference, too!!!
     475             :   */
     476             :   return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp;
     477             : }
     478             : 
     479             : #else
     480             : unsigned int FFI_HIDDEN __attribute__ ((regparm(1)))
     481           0 : ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args)
     482             : {
     483             :   /* our various things...  */
     484             :   ffi_cif       *cif;
     485             :   void         **arg_area;
     486             : 
     487           0 :   cif         = closure->cif;
     488           0 :   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
     489             : 
     490             :   /* this call will initialize ARG_AREA, such that each
     491             :    * element in that array points to the corresponding 
     492             :    * value on the stack; and if the function returns
     493             :    * a structure, it will change RESP to point to the
     494             :    * structure return address.  */
     495             : 
     496           0 :   ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
     497             : 
     498           0 :   (closure->fun) (cif, *respp, arg_area, closure->user_data);
     499             : 
     500           0 :   return cif->flags;
     501             : }
     502             : #endif /* !X86_WIN64 */
     503             : 
     504             : static void
     505           0 : ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
     506             :                             ffi_cif *cif)
     507             : {
     508             :   register unsigned int i;
     509             :   register void **p_argv;
     510             :   register char *argp;
     511             :   register ffi_type **p_arg;
     512             : 
     513           0 :   argp = stack;
     514             : 
     515             : #ifdef X86_WIN64
     516             :   if (cif->rtype->size > sizeof(ffi_arg)
     517             :       || (cif->flags == FFI_TYPE_STRUCT
     518             :           && (cif->rtype->size != 1 && cif->rtype->size != 2
     519             :               && cif->rtype->size != 4 && cif->rtype->size != 8))) {
     520             :     *rvalue = *(void **) argp;
     521             :     argp += sizeof(void *);
     522             :   }
     523             : #else
     524           0 :   if ( cif->flags == FFI_TYPE_STRUCT
     525           0 :        || cif->flags == FFI_TYPE_MS_STRUCT ) {
     526           0 :     *rvalue = *(void **) argp;
     527           0 :     argp += sizeof(void *);
     528             :   }
     529             : #endif
     530             : 
     531           0 :   p_argv = avalue;
     532             : 
     533           0 :   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
     534             :     {
     535             :       size_t z;
     536             : 
     537             :       /* Align if necessary */
     538           0 :       if ((sizeof(void*) - 1) & (size_t) argp) {
     539           0 :         argp = (char *) ALIGN(argp, sizeof(void*));
     540             :       }
     541             : 
     542             : #ifdef X86_WIN64
     543             :       if ((*p_arg)->size > sizeof(ffi_arg)
     544             :           || ((*p_arg)->type == FFI_TYPE_STRUCT
     545             :               && ((*p_arg)->size != 1 && (*p_arg)->size != 2
     546             :                   && (*p_arg)->size != 4 && (*p_arg)->size != 8)))
     547             :         {
     548             :           z = sizeof(void *);
     549             :           *p_argv = *(void **)argp;
     550             :         }
     551             :       else
     552             : #endif
     553             :         {
     554           0 :           z = (*p_arg)->size;
     555             :           
     556             :           /* because we're little endian, this is what it turns into.   */
     557             :           
     558           0 :           *p_argv = (void*) argp;
     559             :         }
     560             :           
     561           0 :       p_argv++;
     562             : #ifdef X86_WIN64
     563             :       argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
     564             : #else
     565           0 :       argp += z;
     566             : #endif
     567             :     }
     568             :   
     569           0 :   return;
     570             : }
     571             : 
     572             : #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
     573             : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     574             :    void*  __fun = (void*)(FUN); \
     575             :    void*  __ctx = (void*)(CTX); \
     576             :    *(unsigned char*) &__tramp[0] = 0x41; \
     577             :    *(unsigned char*) &__tramp[1] = 0xbb; \
     578             :    *(unsigned int*) &__tramp[2] = MASK; /* mov $mask, %r11 */ \
     579             :    *(unsigned char*) &__tramp[6] = 0x48; \
     580             :    *(unsigned char*) &__tramp[7] = 0xb8; \
     581             :    *(void**) &__tramp[8] = __ctx; /* mov __ctx, %rax */ \
     582             :    *(unsigned char *)  &__tramp[16] = 0x49; \
     583             :    *(unsigned char *)  &__tramp[17] = 0xba; \
     584             :    *(void**) &__tramp[18] = __fun; /* mov __fun, %r10 */ \
     585             :    *(unsigned char *)  &__tramp[26] = 0x41; \
     586             :    *(unsigned char *)  &__tramp[27] = 0xff; \
     587             :    *(unsigned char *)  &__tramp[28] = 0xe2; /* jmp %r10 */ \
     588             :  }
     589             : 
     590             : /* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
     591             : 
     592             : #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
     593             : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     594             :    unsigned int  __fun = (unsigned int)(FUN); \
     595             :    unsigned int  __ctx = (unsigned int)(CTX); \
     596             :    unsigned int  __dis = __fun - (__ctx + 10);  \
     597             :    *(unsigned char*) &__tramp[0] = 0xb8; \
     598             :    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
     599             :    *(unsigned char *)  &__tramp[5] = 0xe9; \
     600             :    *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
     601             :  }
     602             : 
     603             : #define FFI_INIT_TRAMPOLINE_THISCALL(TRAMP,FUN,CTX,SIZE) \
     604             : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     605             :    unsigned int  __fun = (unsigned int)(FUN); \
     606             :    unsigned int  __ctx = (unsigned int)(CTX); \
     607             :    unsigned int  __dis = __fun - (__ctx + 49);  \
     608             :    unsigned short __size = (unsigned short)(SIZE); \
     609             :    *(unsigned int *) &__tramp[0] = 0x8324048b;      /* mov (%esp), %eax */ \
     610             :    *(unsigned int *) &__tramp[4] = 0x4c890cec;      /* sub $12, %esp */ \
     611             :    *(unsigned int *) &__tramp[8] = 0x04890424;      /* mov %ecx, 4(%esp) */ \
     612             :    *(unsigned char*) &__tramp[12] = 0x24;   /* mov %eax, (%esp) */ \
     613             :    *(unsigned char*) &__tramp[13] = 0xb8; \
     614             :    *(unsigned int *) &__tramp[14] = __size; /* mov __size, %eax */ \
     615             :    *(unsigned int *) &__tramp[18] = 0x08244c8d;     /* lea 8(%esp), %ecx */ \
     616             :    *(unsigned int *) &__tramp[22] = 0x4802e8c1; /* shr $2, %eax ; dec %eax */ \
     617             :    *(unsigned short*) &__tramp[26] = 0x0b74;        /* jz 1f */ \
     618             :    *(unsigned int *) &__tramp[28] = 0x8908518b;     /* 2b: mov 8(%ecx), %edx */ \
     619             :    *(unsigned int *) &__tramp[32] = 0x04c18311; /* mov %edx, (%ecx) ; add $4, %ecx */ \
     620             :    *(unsigned char*) &__tramp[36] = 0x48;   /* dec %eax */ \
     621             :    *(unsigned short*) &__tramp[37] = 0xf575;        /* jnz 2b ; 1f: */ \
     622             :    *(unsigned char*) &__tramp[39] = 0xb8; \
     623             :    *(unsigned int*)  &__tramp[40] = __ctx; /* movl __ctx, %eax */ \
     624             :    *(unsigned char *)  &__tramp[44] = 0xe8; \
     625             :    *(unsigned int*)  &__tramp[45] = __dis; /* call __fun  */ \
     626             :    *(unsigned char*)  &__tramp[49] = 0xc2; /* ret  */ \
     627             :    *(unsigned short*)  &__tramp[50] = (__size + 8); /* ret (__size + 8)  */ \
     628             :  }
     629             : 
     630             : #define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
     631             : { unsigned char *__tramp = (unsigned char*)(TRAMP); \
     632             :    unsigned int  __fun = (unsigned int)(FUN); \
     633             :    unsigned int  __ctx = (unsigned int)(CTX); \
     634             :    unsigned int  __dis = __fun - (__ctx + 10); \
     635             :    unsigned short __size = (unsigned short)(SIZE); \
     636             :    *(unsigned char*) &__tramp[0] = 0xb8; \
     637             :    *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
     638             :    *(unsigned char *)  &__tramp[5] = 0xe8; \
     639             :    *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
     640             :    *(unsigned char *)  &__tramp[10] = 0xc2; \
     641             :    *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
     642             :  }
     643             : 
     644             : /* the cif must already be prep'ed */
     645             : 
     646             : ffi_status
     647           0 : ffi_prep_closure_loc (ffi_closure* closure,
     648             :                       ffi_cif* cif,
     649             :                       void (*fun)(ffi_cif*,void*,void**,void*),
     650             :                       void *user_data,
     651             :                       void *codeloc)
     652             : {
     653             : #ifdef X86_WIN64
     654             : #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE)
     655             : #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0)
     656             :   if (cif->abi == FFI_WIN64) 
     657             :     {
     658             :       int mask = FLAG(0)|FLAG(1)|FLAG(2)|FLAG(3);
     659             :       FFI_INIT_TRAMPOLINE_WIN64 (&closure->tramp[0],
     660             :                                  &ffi_closure_win64,
     661             :                                  codeloc, mask);
     662             :       /* make sure we can execute here */
     663             :     }
     664             : #else
     665           0 :   if (cif->abi == FFI_SYSV)
     666             :     {
     667           0 :       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
     668             :                            &ffi_closure_SYSV,
     669             :                            (void*)codeloc);
     670             :     }
     671             : #ifdef X86_WIN32
     672             :   else if (cif->abi == FFI_THISCALL)
     673             :     {
     674             :       FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0],
     675             :                                     &ffi_closure_THISCALL,
     676             :                                     (void*)codeloc,
     677             :                                     cif->bytes);
     678             :     }
     679             :   else if (cif->abi == FFI_STDCALL)
     680             :     {
     681             :       FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
     682             :                                    &ffi_closure_STDCALL,
     683             :                                    (void*)codeloc, cif->bytes);
     684             :     }
     685             :   else if (cif->abi == FFI_MS_CDECL)
     686             :     {
     687             :       FFI_INIT_TRAMPOLINE (&closure->tramp[0],
     688             :                            &ffi_closure_SYSV,
     689             :                            (void*)codeloc);
     690             :     }
     691             : #endif /* X86_WIN32 */
     692             : #endif /* !X86_WIN64 */
     693             :   else
     694             :     {
     695           0 :       return FFI_BAD_ABI;
     696             :     }
     697             :     
     698           0 :   closure->cif  = cif;
     699           0 :   closure->user_data = user_data;
     700           0 :   closure->fun  = fun;
     701             : 
     702           0 :   return FFI_OK;
     703             : }
     704             : 
     705             : /* ------- Native raw API support -------------------------------- */
     706             : 
     707             : #if !FFI_NO_RAW_API
     708             : 
     709             : ffi_status
     710           0 : ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
     711             :                           ffi_cif* cif,
     712             :                           void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
     713             :                           void *user_data,
     714             :                           void *codeloc)
     715             : {
     716             :   int i;
     717             : 
     718           0 :   if (cif->abi != FFI_SYSV) {
     719             : #ifdef X86_WIN32
     720             :     if (cif->abi != FFI_THISCALL)
     721             : #endif
     722           0 :     return FFI_BAD_ABI;
     723             :   }
     724             : 
     725             :   /* we currently don't support certain kinds of arguments for raw
     726             :      closures.  This should be implemented by a separate assembly
     727             :      language routine, since it would require argument processing,
     728             :      something we don't do now for performance.  */
     729             : 
     730           0 :   for (i = cif->nargs-1; i >= 0; i--)
     731             :     {
     732             :       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
     733             :       FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
     734             :     }
     735             :   
     736             : #ifdef X86_WIN32
     737             :   if (cif->abi == FFI_SYSV)
     738             :     {
     739             : #endif
     740           0 :   FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
     741             :                        codeloc);
     742             : #ifdef X86_WIN32
     743             :     }
     744             :   else if (cif->abi == FFI_THISCALL)
     745             :     {
     746             :       FFI_INIT_TRAMPOLINE_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL,
     747             :                                     codeloc, cif->bytes);
     748             :     }
     749             : #endif
     750           0 :   closure->cif  = cif;
     751           0 :   closure->user_data = user_data;
     752           0 :   closure->fun  = fun;
     753             : 
     754           0 :   return FFI_OK;
     755             : }
     756             : 
     757             : static void 
     758           0 : ffi_prep_args_raw(char *stack, extended_cif *ecif)
     759             : {
     760           0 :   memcpy (stack, ecif->avalue, ecif->cif->bytes);
     761           0 : }
     762             : 
     763             : /* we borrow this routine from libffi (it must be changed, though, to
     764             :  * actually call the function passed in the first argument.  as of
     765             :  * libffi-1.20, this is not the case.)
     766             :  */
     767             : 
     768             : void
     769           0 : ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
     770             : {
     771             :   extended_cif ecif;
     772           0 :   void **avalue = (void **)fake_avalue;
     773             : 
     774           0 :   ecif.cif = cif;
     775           0 :   ecif.avalue = avalue;
     776             :   
     777             :   /* If the return value is a struct and we don't have a return */
     778             :   /* value address then we need to make one                     */
     779             : 
     780           0 :   if (rvalue == NULL
     781           0 :       && (cif->flags == FFI_TYPE_STRUCT
     782           0 :           || cif->flags == FFI_TYPE_MS_STRUCT))
     783             :     {
     784           0 :       ecif.rvalue = alloca(cif->rtype->size);
     785             :     }
     786             :   else
     787           0 :     ecif.rvalue = rvalue;
     788             :     
     789             :   
     790           0 :   switch (cif->abi) 
     791             :     {
     792             : #ifdef X86_WIN32
     793             :     case FFI_SYSV:
     794             :     case FFI_STDCALL:
     795             :     case FFI_MS_CDECL:
     796             :       ffi_call_win32(ffi_prep_args_raw, &ecif, cif->abi, cif->bytes, cif->flags,
     797             :                      ecif.rvalue, fn);
     798             :       break;
     799             :     case FFI_THISCALL:
     800             :     case FFI_FASTCALL:
     801             :       {
     802             :         unsigned int abi = cif->abi;
     803             :         unsigned int i, passed_regs = 0;
     804             : 
     805             :         if (cif->flags == FFI_TYPE_STRUCT)
     806             :           ++passed_regs;
     807             : 
     808             :         for (i=0; i < cif->nargs && passed_regs < 2;i++)
     809             :           {
     810             :             size_t sz;
     811             : 
     812             :             if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
     813             :                 || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
     814             :               continue;
     815             :             sz = (cif->arg_types[i]->size + 3) & ~3;
     816             :             if (sz == 0 || sz > 4)
     817             :               continue;
     818             :             ++passed_regs;
     819             :           }
     820             :         if (passed_regs < 2 && abi == FFI_FASTCALL)
     821             :           cif->abi = abi = FFI_THISCALL;
     822             :         if (passed_regs < 1 && abi == FFI_THISCALL)
     823             :           cif->abi = abi = FFI_STDCALL;
     824             :         ffi_call_win32(ffi_prep_args_raw, &ecif, abi, cif->bytes, cif->flags,
     825             :                        ecif.rvalue, fn);
     826             :       }
     827             :       break;
     828             : #else
     829             :     case FFI_SYSV:
     830           0 :       ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
     831           0 :                     ecif.rvalue, fn);
     832           0 :       break;
     833             : #endif
     834             :     default:
     835             :       FFI_ASSERT(0);
     836           0 :       break;
     837             :     }
     838           0 : }
     839             : 
     840             : #endif
     841             : 
     842             : #endif /* !__x86_64__  || X86_WIN64 */
     843             : 

Generated by: LCOV version 1.10