~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Modules/_ctypes/libffi_msvc/ffi.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

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