Home | History | Annotate | Download | only in libffi_msvc
      1 /* -----------------------------------------------------------------------
      2    ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
      3            Copyright (c) 2002  Ranjit Mathew
      4            Copyright (c) 2002  Bo Thorsen
      5            Copyright (c) 2002  Roger Sayle
      6 
      7    x86 Foreign Function Interface
      8 
      9    Permission is hereby granted, free of charge, to any person obtaining
     10    a copy of this software and associated documentation files (the
     11    ``Software''), to deal in the Software without restriction, including
     12    without limitation the rights to use, copy, modify, merge, publish,
     13    distribute, sublicense, and/or sell copies of the Software, and to
     14    permit persons to whom the Software is furnished to do so, subject to
     15    the following conditions:
     16 
     17    The above copyright notice and this permission notice shall be included
     18    in all copies or substantial portions of the Software.
     19 
     20    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     21    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     22    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     23    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     24    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     25    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     26    OTHER DEALINGS IN THE SOFTWARE.
     27    ----------------------------------------------------------------------- */
     28 
     29 #include <ffi.h>
     30 #include <ffi_common.h>
     31 
     32 #include <stdlib.h>
     33 
     34 /* ffi_prep_args is called by the assembly routine once stack space
     35    has been allocated for the function's arguments */
     36 
     37 extern void Py_FatalError(const char *msg);
     38 
     39 /*@-exportheader@*/
     40 void ffi_prep_args(char *stack, extended_cif *ecif)
     41 /*@=exportheader@*/
     42 {
     43   register unsigned int i;
     44   register void **p_argv;
     45   register char *argp;
     46   register ffi_type **p_arg;
     47 
     48   argp = stack;
     49   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
     50     {
     51       *(void **) argp = ecif->rvalue;
     52       argp += sizeof(void *);
     53     }
     54 
     55   p_argv = ecif->avalue;
     56 
     57   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
     58        i != 0;
     59        i--, p_arg++)
     60     {
     61       size_t z;
     62 
     63       /* Align if necessary */
     64       if ((sizeof(void *) - 1) & (size_t) argp)
     65 	argp = (char *) ALIGN(argp, sizeof(void *));
     66 
     67       z = (*p_arg)->size;
     68       if (z < sizeof(intptr_t))
     69 	{
     70 	  z = sizeof(intptr_t);
     71 	  switch ((*p_arg)->type)
     72 	    {
     73 	    case FFI_TYPE_SINT8:
     74 	      *(intptr_t *) argp = (intptr_t)*(SINT8 *)(* p_argv);
     75 	      break;
     76 
     77 	    case FFI_TYPE_UINT8:
     78 	      *(uintptr_t *) argp = (uintptr_t)*(UINT8 *)(* p_argv);
     79 	      break;
     80 
     81 	    case FFI_TYPE_SINT16:
     82 	      *(intptr_t *) argp = (intptr_t)*(SINT16 *)(* p_argv);
     83 	      break;
     84 
     85 	    case FFI_TYPE_UINT16:
     86 	      *(uintptr_t *) argp = (uintptr_t)*(UINT16 *)(* p_argv);
     87 	      break;
     88 
     89 	    case FFI_TYPE_SINT32:
     90 	      *(intptr_t *) argp = (intptr_t)*(SINT32 *)(* p_argv);
     91 	      break;
     92 
     93 	    case FFI_TYPE_UINT32:
     94 	      *(uintptr_t *) argp = (uintptr_t)*(UINT32 *)(* p_argv);
     95 	      break;
     96 
     97 	    case FFI_TYPE_FLOAT:
     98 	      *(uintptr_t *) argp = 0;
     99 	      *(float *) argp = *(float *)(* p_argv);
    100 	      break;
    101 
    102 	    // 64-bit value cases should never be used for x86 and AMD64 builds
    103 	    case FFI_TYPE_SINT64:
    104 	      *(intptr_t *) argp = (intptr_t)*(SINT64 *)(* p_argv);
    105 	      break;
    106 
    107 	    case FFI_TYPE_UINT64:
    108 	      *(uintptr_t *) argp = (uintptr_t)*(UINT64 *)(* p_argv);
    109 	      break;
    110 
    111 	    case FFI_TYPE_STRUCT:
    112 	      *(uintptr_t *) argp = (uintptr_t)*(UINT32 *)(* p_argv);
    113 	      break;
    114 
    115 	    case FFI_TYPE_DOUBLE:
    116 	      *(uintptr_t *) argp = 0;
    117 	      *(double *) argp = *(double *)(* p_argv);
    118 	      break;
    119 
    120 	    default:
    121 	      FFI_ASSERT(0);
    122 	    }
    123 	}
    124 #ifdef _WIN64
    125       else if (z > 8)
    126         {
    127           /* On Win64, if a single argument takes more than 8 bytes,
    128              then it is always passed by reference. */
    129           *(void **)argp = *p_argv;
    130           z = 8;
    131         }
    132 #endif
    133       else
    134 	{
    135 	  memcpy(argp, *p_argv, z);
    136 	}
    137       p_argv++;
    138       argp += z;
    139     }
    140 
    141   if (argp >= stack && (unsigned)(argp - stack) > ecif->cif->bytes)
    142     {
    143       Py_FatalError("FFI BUG: not enough stack space for arguments");
    144     }
    145   return;
    146 }
    147 
    148 /* Perform machine dependent cif processing */
    149 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
    150 {
    151   /* Set the return type flag */
    152   switch (cif->rtype->type)
    153     {
    154     case FFI_TYPE_VOID:
    155     case FFI_TYPE_SINT64:
    156     case FFI_TYPE_FLOAT:
    157     case FFI_TYPE_DOUBLE:
    158     case FFI_TYPE_LONGDOUBLE:
    159       cif->flags = (unsigned) cif->rtype->type;
    160       break;
    161 
    162     case FFI_TYPE_STRUCT:
    163       /* MSVC returns small structures in registers.  Put in cif->flags
    164          the value FFI_TYPE_STRUCT only if the structure is big enough;
    165          otherwise, put the 4- or 8-bytes integer type. */
    166       if (cif->rtype->size <= 4)
    167         cif->flags = FFI_TYPE_INT;
    168       else if (cif->rtype->size <= 8)
    169         cif->flags = FFI_TYPE_SINT64;
    170       else
    171         cif->flags = FFI_TYPE_STRUCT;
    172       break;
    173 
    174     case FFI_TYPE_UINT64:
    175 #ifdef _WIN64
    176     case FFI_TYPE_POINTER:
    177 #endif
    178       cif->flags = FFI_TYPE_SINT64;
    179       break;
    180 
    181     default:
    182       cif->flags = FFI_TYPE_INT;
    183       break;
    184     }
    185 
    186   return FFI_OK;
    187 }
    188 
    189 #ifdef _WIN32
    190 extern int
    191 ffi_call_x86(void (*)(char *, extended_cif *),
    192 	     /*@out@*/ extended_cif *,
    193 	     unsigned, unsigned,
    194 	     /*@out@*/ unsigned *,
    195 	     void (*fn)());
    196 #endif
    197 
    198 #ifdef _WIN64
    199 extern int
    200 ffi_call_AMD64(void (*)(char *, extended_cif *),
    201 		 /*@out@*/ extended_cif *,
    202 		 unsigned, unsigned,
    203 		 /*@out@*/ unsigned *,
    204 		 void (*fn)());
    205 #endif
    206 
    207 int
    208 ffi_call(/*@dependent@*/ ffi_cif *cif,
    209 	 void (*fn)(),
    210 	 /*@out@*/ void *rvalue,
    211 	 /*@dependent@*/ void **avalue)
    212 {
    213   extended_cif ecif;
    214 
    215   ecif.cif = cif;
    216   ecif.avalue = avalue;
    217 
    218   /* If the return value is a struct and we don't have a return	*/
    219   /* value address then we need to make one		        */
    220 
    221   if ((rvalue == NULL) &&
    222       (cif->rtype->type == FFI_TYPE_STRUCT))
    223     {
    224       /*@-sysunrecog@*/
    225       ecif.rvalue = alloca(cif->rtype->size);
    226       /*@=sysunrecog@*/
    227     }
    228   else
    229     ecif.rvalue = rvalue;
    230 
    231 
    232   switch (cif->abi)
    233     {
    234 #if !defined(_WIN64)
    235     case FFI_SYSV:
    236     case FFI_STDCALL:
    237       return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,
    238 			  cif->flags, ecif.rvalue, fn);
    239       break;
    240 #else
    241     case FFI_SYSV:
    242       /* If a single argument takes more than 8 bytes,
    243          then a copy is passed by reference. */
    244       for (unsigned i = 0; i < cif->nargs; i++) {
    245           size_t z = cif->arg_types[i]->size;
    246           if (z > 8) {
    247               void *temp = alloca(z);
    248               memcpy(temp, avalue[i], z);
    249               avalue[i] = temp;
    250           }
    251       }
    252       /*@-usedef@*/
    253       return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
    254 			   cif->flags, ecif.rvalue, fn);
    255       /*@=usedef@*/
    256       break;
    257 #endif
    258 
    259     default:
    260       FFI_ASSERT(0);
    261       break;
    262     }
    263   return -1; /* theller: Hrm. */
    264 }
    265 
    266 
    267 /** private members **/
    268 
    269 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
    270 					  void** args, ffi_cif* cif);
    271 /* This function is jumped to by the trampoline */
    272 
    273 #ifdef _WIN64
    274 void *
    275 #else
    276 static void __fastcall
    277 #endif
    278 ffi_closure_SYSV (ffi_closure *closure, char *argp)
    279 {
    280   // this is our return value storage
    281   long double    res;
    282 
    283   // our various things...
    284   ffi_cif       *cif;
    285   void         **arg_area;
    286   unsigned short rtype;
    287   void          *resp = (void*)&res;
    288   void *args = argp + sizeof(void*);
    289 
    290   cif         = closure->cif;
    291   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
    292 
    293   /* this call will initialize ARG_AREA, such that each
    294    * element in that array points to the corresponding
    295    * value on the stack; and if the function returns
    296    * a structure, it will re-set RESP to point to the
    297    * structure return address.  */
    298 
    299   ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
    300 
    301   (closure->fun) (cif, resp, arg_area, closure->user_data);
    302 
    303   rtype = cif->flags;
    304 
    305 #if defined(_WIN32) && !defined(_WIN64)
    306 #ifdef _MSC_VER
    307   /* now, do a generic return based on the value of rtype */
    308   if (rtype == FFI_TYPE_INT)
    309     {
    310 	    _asm mov eax, resp ;
    311 	    _asm mov eax, [eax] ;
    312     }
    313   else if (rtype == FFI_TYPE_FLOAT)
    314     {
    315 	    _asm mov eax, resp ;
    316 	    _asm fld DWORD PTR [eax] ;
    317 //      asm ("flds (%0)" : : "r" (resp) : "st" );
    318     }
    319   else if (rtype == FFI_TYPE_DOUBLE)
    320     {
    321 	    _asm mov eax, resp ;
    322 	    _asm fld QWORD PTR [eax] ;
    323 //      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
    324     }
    325   else if (rtype == FFI_TYPE_LONGDOUBLE)
    326     {
    327 //      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
    328     }
    329   else if (rtype == FFI_TYPE_SINT64)
    330     {
    331 	    _asm mov edx, resp ;
    332 	    _asm mov eax, [edx] ;
    333 	    _asm mov edx, [edx + 4] ;
    334 //      asm ("movl 0(%0),%%eax;"
    335 //	   "movl 4(%0),%%edx"
    336 //	   : : "r"(resp)
    337 //	   : "eax", "edx");
    338     }
    339 #else
    340   /* now, do a generic return based on the value of rtype */
    341   if (rtype == FFI_TYPE_INT)
    342     {
    343       asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
    344     }
    345   else if (rtype == FFI_TYPE_FLOAT)
    346     {
    347       asm ("flds (%0)" : : "r" (resp) : "st" );
    348     }
    349   else if (rtype == FFI_TYPE_DOUBLE)
    350     {
    351       asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
    352     }
    353   else if (rtype == FFI_TYPE_LONGDOUBLE)
    354     {
    355       asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
    356     }
    357   else if (rtype == FFI_TYPE_SINT64)
    358     {
    359       asm ("movl 0(%0),%%eax;"
    360 	   "movl 4(%0),%%edx"
    361 	   : : "r"(resp)
    362 	   : "eax", "edx");
    363     }
    364 #endif
    365 #endif
    366 
    367 #ifdef _WIN64
    368   /* The result is returned in rax.  This does the right thing for
    369      result types except for floats; we have to 'mov xmm0, rax' in the
    370      caller to correct this.
    371   */
    372   return *(void **)resp;
    373 #endif
    374 }
    375 
    376 /*@-exportheader@*/
    377 static void
    378 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
    379 			    void **avalue, ffi_cif *cif)
    380 /*@=exportheader@*/
    381 {
    382   register unsigned int i;
    383   register void **p_argv;
    384   register char *argp;
    385   register ffi_type **p_arg;
    386 
    387   argp = stack;
    388 
    389   if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
    390     *rvalue = *(void **) argp;
    391     argp += sizeof(void *);
    392   }
    393 
    394   p_argv = avalue;
    395 
    396   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
    397     {
    398       size_t z;
    399 
    400       /* Align if necessary */
    401       if ((sizeof(char *) - 1) & (size_t) argp) {
    402         argp = (char *) ALIGN(argp, sizeof(char*));
    403       }
    404 
    405       z = (*p_arg)->size;
    406 
    407       /* because we're little endian, this is what it turns into.   */
    408 
    409 #ifdef _WIN64
    410       if (z > 8) {
    411         /* On Win64, if a single argument takes more than 8 bytes,
    412          * then it is always passed by reference.
    413          */
    414         *p_argv = *((void**) argp);
    415         z = 8;
    416       }
    417       else
    418 #endif
    419       *p_argv = (void*) argp;
    420 
    421       p_argv++;
    422       argp += z;
    423     }
    424 
    425   return;
    426 }
    427 
    428 /* the cif must already be prep'ed */
    429 extern void ffi_closure_OUTER();
    430 
    431 ffi_status
    432 ffi_prep_closure_loc (ffi_closure* closure,
    433 					  ffi_cif* cif,
    434 					  void (*fun)(ffi_cif*,void*,void**,void*),
    435 					  void *user_data,
    436 					  void *codeloc)
    437 {
    438   short bytes;
    439   char *tramp;
    440 #ifdef _WIN64
    441   int mask = 0;
    442 #endif
    443   FFI_ASSERT (cif->abi == FFI_SYSV);
    444 
    445   if (cif->abi == FFI_SYSV)
    446     bytes = 0;
    447 #if !defined(_WIN64)
    448   else if (cif->abi == FFI_STDCALL)
    449     bytes = cif->bytes;
    450 #endif
    451   else
    452     return FFI_BAD_ABI;
    453 
    454   tramp = &closure->tramp[0];
    455 
    456 #define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
    457 #define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
    458 #define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
    459 #define INT(x) *(int*)tramp = x, tramp += sizeof(int)
    460 
    461 #ifdef _WIN64
    462   if (cif->nargs >= 1 &&
    463       (cif->arg_types[0]->type == FFI_TYPE_FLOAT
    464        || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
    465     mask |= 1;
    466   if (cif->nargs >= 2 &&
    467       (cif->arg_types[1]->type == FFI_TYPE_FLOAT
    468        || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
    469     mask |= 2;
    470   if (cif->nargs >= 3 &&
    471       (cif->arg_types[2]->type == FFI_TYPE_FLOAT
    472        || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
    473     mask |= 4;
    474   if (cif->nargs >= 4 &&
    475       (cif->arg_types[3]->type == FFI_TYPE_FLOAT
    476        || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
    477     mask |= 8;
    478 
    479   /* 41 BB ----         mov         r11d,mask */
    480   BYTES("\x41\xBB"); INT(mask);
    481 
    482   /* 48 B8 --------     mov         rax, closure			*/
    483   BYTES("\x48\xB8"); POINTER(closure);
    484 
    485   /* 49 BA --------     mov         r10, ffi_closure_OUTER */
    486   BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
    487 
    488   /* 41 FF E2           jmp         r10 */
    489   BYTES("\x41\xFF\xE2");
    490 
    491 #else
    492 
    493   /* mov ecx, closure */
    494   BYTES("\xb9"); POINTER(closure);
    495 
    496   /* mov edx, esp */
    497   BYTES("\x8b\xd4");
    498 
    499   /* call ffi_closure_SYSV */
    500   BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
    501 
    502   /* ret bytes */
    503   BYTES("\xc2");
    504   SHORT(bytes);
    505 
    506 #endif
    507 
    508   if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
    509     Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
    510 
    511   closure->cif  = cif;
    512   closure->user_data = user_data;
    513   closure->fun  = fun;
    514   return FFI_OK;
    515 }
    516