ffi.c revision e1f3afbde2b078598ac6db4ba0d946f289000cc9
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#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 */
130ffi_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
171extern int
172ffi_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
180extern int
181ffi_call_AMD64(void (*)(char *, extended_cif *),
182		 /*@out@*/ extended_cif *,
183		 unsigned, unsigned,
184		 /*@out@*/ unsigned *,
185		 void (*fn)());
186#endif
187
188int
189ffi_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
240static 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
245void *
246#else
247static void __fastcall
248#endif
249ffi_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@*/
348static void
349ffi_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 */
400extern void ffi_closure_OUTER();
401
402ffi_status
403ffi_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