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(int))
     69 	{
     70 	  z = sizeof(int);
     71 	  switch ((*p_arg)->type)
     72 	    {
     73 	    case FFI_TYPE_SINT8:
     74 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
     75 	      break;
     76 
     77 	    case FFI_TYPE_UINT8:
     78 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
     79 	      break;
     80 
     81 	    case FFI_TYPE_SINT16:
     82 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
     83 	      break;
     84 
     85 	    case FFI_TYPE_UINT16:
     86 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
     87 	      break;
     88 
     89 	    case FFI_TYPE_SINT32:
     90 	      *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
     91 	      break;
     92 
     93 	    case FFI_TYPE_UINT32:
     94 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
     95 	      break;
     96 
     97 	    case FFI_TYPE_STRUCT:
     98 	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
     99 	      break;
    100 
    101 	    default:
    102 	      FFI_ASSERT(0);
    103 	    }
    104 	}
    105 #ifdef _WIN64
    106       else if (z > 8)
    107         {
    108           /* On Win64, if a single argument takes more than 8 bytes,
    109              then it is always passed by reference. */
    110           *(void **)argp = *p_argv;
    111           z = 8;
    112         }
    113 #endif
    114       else
    115 	{
    116 	  memcpy(argp, *p_argv, z);
    117 	}
    118       p_argv++;
    119       argp += z;
    120     }
    121 
    122   if (argp - stack > ecif->cif->bytes)
    123     {
    124       Py_FatalError("FFI BUG: not enough stack space for arguments");
    125     }
    126   return;
    127 }
    128 
    129 /* Perform machine dependent cif processing */
    130 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
    131 {
    132   /* Set the return type flag */
    133   switch (cif->rtype->type)
    134     {
    135     case FFI_TYPE_VOID:
    136     case FFI_TYPE_SINT64:
    137     case FFI_TYPE_FLOAT:
    138     case FFI_TYPE_DOUBLE:
    139     case FFI_TYPE_LONGDOUBLE:
    140       cif->flags = (unsigned) cif->rtype->type;
    141       break;
    142 
    143     case FFI_TYPE_STRUCT:
    144       /* MSVC returns small structures in registers.  Put in cif->flags
    145          the value FFI_TYPE_STRUCT only if the structure is big enough;
    146          otherwise, put the 4- or 8-bytes integer type. */
    147       if (cif->rtype->size <= 4)
    148         cif->flags = FFI_TYPE_INT;
    149       else if (cif->rtype->size <= 8)
    150         cif->flags = FFI_TYPE_SINT64;
    151       else
    152         cif->flags = FFI_TYPE_STRUCT;
    153       break;
    154 
    155     case FFI_TYPE_UINT64:
    156 #ifdef _WIN64
    157     case FFI_TYPE_POINTER:
    158 #endif
    159       cif->flags = FFI_TYPE_SINT64;
    160       break;
    161 
    162     default:
    163       cif->flags = FFI_TYPE_INT;
    164       break;
    165     }
    166 
    167   return FFI_OK;
    168 }
    169 
    170 #ifdef _WIN32
    171 extern int
    172 ffi_call_x86(void (*)(char *, extended_cif *),
    173 	     /*@out@*/ extended_cif *,
    174 	     unsigned, unsigned,
    175 	     /*@out@*/ unsigned *,
    176 	     void (*fn)());
    177 #endif
    178 
    179 #ifdef _WIN64
    180 extern int
    181 ffi_call_AMD64(void (*)(char *, extended_cif *),
    182 		 /*@out@*/ extended_cif *,
    183 		 unsigned, unsigned,
    184 		 /*@out@*/ unsigned *,
    185 		 void (*fn)());
    186 #endif
    187 
    188 int
    189 ffi_call(/*@dependent@*/ ffi_cif *cif,
    190 	 void (*fn)(),
    191 	 /*@out@*/ void *rvalue,
    192 	 /*@dependent@*/ void **avalue)
    193 {
    194   extended_cif ecif;
    195 
    196   ecif.cif = cif;
    197   ecif.avalue = avalue;
    198 
    199   /* If the return value is a struct and we don't have a return	*/
    200   /* value address then we need to make one		        */
    201 
    202   if ((rvalue == NULL) &&
    203       (cif->rtype->type == FFI_TYPE_STRUCT))
    204     {
    205       /*@-sysunrecog@*/
    206       ecif.rvalue = alloca(cif->rtype->size);
    207       /*@=sysunrecog@*/
    208     }
    209   else
    210     ecif.rvalue = rvalue;
    211 
    212 
    213   switch (cif->abi)
    214     {
    215 #if !defined(_WIN64)
    216     case FFI_SYSV:
    217     case FFI_STDCALL:
    218       return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,
    219 			  cif->flags, ecif.rvalue, fn);
    220       break;
    221 #else
    222     case FFI_SYSV:
    223       /*@-usedef@*/
    224       return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
    225 			   cif->flags, ecif.rvalue, fn);
    226       /*@=usedef@*/
    227       break;
    228 #endif
    229 
    230     default:
    231       FFI_ASSERT(0);
    232       break;
    233     }
    234   return -1; /* theller: Hrm. */
    235 }
    236 
    237 
    238 /** private members **/
    239 
    240 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
    241 					  void** args, ffi_cif* cif);
    242 /* This function is jumped to by the trampoline */
    243 
    244 #ifdef _WIN64
    245 void *
    246 #else
    247 static void __fastcall
    248 #endif
    249 ffi_closure_SYSV (ffi_closure *closure, char *argp)
    250 {
    251   // this is our return value storage
    252   long double    res;
    253 
    254   // our various things...
    255   ffi_cif       *cif;
    256   void         **arg_area;
    257   unsigned short rtype;
    258   void          *resp = (void*)&res;
    259   void *args = argp + sizeof(void*);
    260 
    261   cif         = closure->cif;
    262   arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
    263 
    264   /* this call will initialize ARG_AREA, such that each
    265    * element in that array points to the corresponding
    266    * value on the stack; and if the function returns
    267    * a structure, it will re-set RESP to point to the
    268    * structure return address.  */
    269 
    270   ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
    271 
    272   (closure->fun) (cif, resp, arg_area, closure->user_data);
    273 
    274   rtype = cif->flags;
    275 
    276 #if defined(_WIN32) && !defined(_WIN64)
    277 #ifdef _MSC_VER
    278   /* now, do a generic return based on the value of rtype */
    279   if (rtype == FFI_TYPE_INT)
    280     {
    281 	    _asm mov eax, resp ;
    282 	    _asm mov eax, [eax] ;
    283     }
    284   else if (rtype == FFI_TYPE_FLOAT)
    285     {
    286 	    _asm mov eax, resp ;
    287 	    _asm fld DWORD PTR [eax] ;
    288 //      asm ("flds (%0)" : : "r" (resp) : "st" );
    289     }
    290   else if (rtype == FFI_TYPE_DOUBLE)
    291     {
    292 	    _asm mov eax, resp ;
    293 	    _asm fld QWORD PTR [eax] ;
    294 //      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
    295     }
    296   else if (rtype == FFI_TYPE_LONGDOUBLE)
    297     {
    298 //      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
    299     }
    300   else if (rtype == FFI_TYPE_SINT64)
    301     {
    302 	    _asm mov edx, resp ;
    303 	    _asm mov eax, [edx] ;
    304 	    _asm mov edx, [edx + 4] ;
    305 //      asm ("movl 0(%0),%%eax;"
    306 //	   "movl 4(%0),%%edx"
    307 //	   : : "r"(resp)
    308 //	   : "eax", "edx");
    309     }
    310 #else
    311   /* now, do a generic return based on the value of rtype */
    312   if (rtype == FFI_TYPE_INT)
    313     {
    314       asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
    315     }
    316   else if (rtype == FFI_TYPE_FLOAT)
    317     {
    318       asm ("flds (%0)" : : "r" (resp) : "st" );
    319     }
    320   else if (rtype == FFI_TYPE_DOUBLE)
    321     {
    322       asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
    323     }
    324   else if (rtype == FFI_TYPE_LONGDOUBLE)
    325     {
    326       asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
    327     }
    328   else if (rtype == FFI_TYPE_SINT64)
    329     {
    330       asm ("movl 0(%0),%%eax;"
    331 	   "movl 4(%0),%%edx"
    332 	   : : "r"(resp)
    333 	   : "eax", "edx");
    334     }
    335 #endif
    336 #endif
    337 
    338 #ifdef _WIN64
    339   /* The result is returned in rax.  This does the right thing for
    340      result types except for floats; we have to 'mov xmm0, rax' in the
    341      caller to correct this.
    342   */
    343   return *(void **)resp;
    344 #endif
    345 }
    346 
    347 /*@-exportheader@*/
    348 static void
    349 ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
    350 			    void **avalue, ffi_cif *cif)
    351 /*@=exportheader@*/
    352 {
    353   register unsigned int i;
    354   register void **p_argv;
    355   register char *argp;
    356   register ffi_type **p_arg;
    357 
    358   argp = stack;
    359 
    360   if ( cif->rtype->type == FFI_TYPE_STRUCT ) {
    361     *rvalue = *(void **) argp;
    362     argp += sizeof(void *);
    363   }
    364 
    365   p_argv = avalue;
    366 
    367   for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
    368     {
    369       size_t z;
    370 
    371       /* Align if necessary */
    372       if ((sizeof(char *) - 1) & (size_t) argp) {
    373         argp = (char *) ALIGN(argp, sizeof(char*));
    374       }
    375 
    376       z = (*p_arg)->size;
    377 
    378       /* because we're little endian, this is what it turns into.   */
    379 
    380 #ifdef _WIN64
    381       if (z > 8) {
    382         /* On Win64, if a single argument takes more than 8 bytes,
    383          * then it is always passed by reference.
    384          */
    385         *p_argv = *((void**) argp);
    386         z = 8;
    387       }
    388       else
    389 #endif
    390       *p_argv = (void*) argp;
    391 
    392       p_argv++;
    393       argp += z;
    394     }
    395 
    396   return;
    397 }
    398 
    399 /* the cif must already be prep'ed */
    400 extern void ffi_closure_OUTER();
    401 
    402 ffi_status
    403 ffi_prep_closure_loc (ffi_closure* closure,
    404 					  ffi_cif* cif,
    405 					  void (*fun)(ffi_cif*,void*,void**,void*),
    406 					  void *user_data,
    407 					  void *codeloc)
    408 {
    409   short bytes;
    410   char *tramp;
    411 #ifdef _WIN64
    412   int mask = 0;
    413 #endif
    414   FFI_ASSERT (cif->abi == FFI_SYSV);
    415 
    416   if (cif->abi == FFI_SYSV)
    417     bytes = 0;
    418 #if !defined(_WIN64)
    419   else if (cif->abi == FFI_STDCALL)
    420     bytes = cif->bytes;
    421 #endif
    422   else
    423     return FFI_BAD_ABI;
    424 
    425   tramp = &closure->tramp[0];
    426 
    427 #define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
    428 #define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
    429 #define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
    430 #define INT(x) *(int*)tramp = x, tramp += sizeof(int)
    431 
    432 #ifdef _WIN64
    433   if (cif->nargs >= 1 &&
    434       (cif->arg_types[0]->type == FFI_TYPE_FLOAT
    435        || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
    436     mask |= 1;
    437   if (cif->nargs >= 2 &&
    438       (cif->arg_types[1]->type == FFI_TYPE_FLOAT
    439        || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
    440     mask |= 2;
    441   if (cif->nargs >= 3 &&
    442       (cif->arg_types[2]->type == FFI_TYPE_FLOAT
    443        || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
    444     mask |= 4;
    445   if (cif->nargs >= 4 &&
    446       (cif->arg_types[3]->type == FFI_TYPE_FLOAT
    447        || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
    448     mask |= 8;
    449 
    450   /* 41 BB ----         mov         r11d,mask */
    451   BYTES("\x41\xBB"); INT(mask);
    452 
    453   /* 48 B8 --------     mov         rax, closure			*/
    454   BYTES("\x48\xB8"); POINTER(closure);
    455 
    456   /* 49 BA --------     mov         r10, ffi_closure_OUTER */
    457   BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
    458 
    459   /* 41 FF E2           jmp         r10 */
    460   BYTES("\x41\xFF\xE2");
    461 
    462 #else
    463 
    464   /* mov ecx, closure */
    465   BYTES("\xb9"); POINTER(closure);
    466 
    467   /* mov edx, esp */
    468   BYTES("\x8b\xd4");
    469 
    470   /* call ffi_closure_SYSV */
    471   BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
    472 
    473   /* ret bytes */
    474   BYTES("\xc2");
    475   SHORT(bytes);
    476 
    477 #endif
    478 
    479   if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
    480     Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
    481 
    482   closure->cif  = cif;
    483   closure->user_data = user_data;
    484   closure->fun  = fun;
    485   return FFI_OK;
    486 }
    487