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