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

« back to all changes in this revision

Viewing changes to Modules/_ctypes/libffi/src/x86/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, 2007, 2008  Red Hat, Inc.
 
3
           Copyright (c) 2002  Ranjit Mathew
 
4
           Copyright (c) 2002  Bo Thorsen
 
5
           Copyright (c) 2002  Roger Sayle
 
6
           Copyright (C) 2008  Free Software Foundation, Inc.
 
7
 
 
8
   x86 Foreign Function Interface
 
9
 
 
10
   Permission is hereby granted, free of charge, to any person obtaining
 
11
   a copy of this software and associated documentation files (the
 
12
   ``Software''), to deal in the Software without restriction, including
 
13
   without limitation the rights to use, copy, modify, merge, publish,
 
14
   distribute, sublicense, and/or sell copies of the Software, and to
 
15
   permit persons to whom the Software is furnished to do so, subject to
 
16
   the following conditions:
 
17
 
 
18
   The above copyright notice and this permission notice shall be included
 
19
   in all copies or substantial portions of the Software.
 
20
 
 
21
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
 
22
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
23
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
24
   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 
25
   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
26
   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
27
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
28
   DEALINGS IN THE SOFTWARE.
 
29
   ----------------------------------------------------------------------- */
 
30
 
 
31
#ifndef __x86_64__
 
32
 
 
33
#include <ffi.h>
 
34
#include <ffi_common.h>
 
35
 
 
36
#include <stdlib.h>
 
37
 
 
38
/* ffi_prep_args is called by the assembly routine once stack space
 
39
   has been allocated for the function's arguments */
 
40
 
 
41
void ffi_prep_args(char *stack, extended_cif *ecif)
 
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
 
 
50
  if (ecif->cif->flags == FFI_TYPE_STRUCT)
 
51
    {
 
52
      *(void **) argp = ecif->rvalue;
 
53
      argp += 4;
 
54
    }
 
55
 
 
56
  p_argv = ecif->avalue;
 
57
 
 
58
  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
 
59
       i != 0;
 
60
       i--, p_arg++)
 
61
    {
 
62
      size_t z;
 
63
 
 
64
      /* Align if necessary */
 
65
      if ((sizeof(int) - 1) & (unsigned) argp)
 
66
        argp = (char *) ALIGN(argp, sizeof(int));
 
67
 
 
68
      z = (*p_arg)->size;
 
69
      if (z < sizeof(int))
 
70
        {
 
71
          z = sizeof(int);
 
72
          switch ((*p_arg)->type)
 
73
            {
 
74
            case FFI_TYPE_SINT8:
 
75
              *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
 
76
              break;
 
77
 
 
78
            case FFI_TYPE_UINT8:
 
79
              *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
 
80
              break;
 
81
 
 
82
            case FFI_TYPE_SINT16:
 
83
              *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
 
84
              break;
 
85
 
 
86
            case FFI_TYPE_UINT16:
 
87
              *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
 
88
              break;
 
89
 
 
90
            case FFI_TYPE_SINT32:
 
91
              *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
 
92
              break;
 
93
 
 
94
            case FFI_TYPE_UINT32:
 
95
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
96
              break;
 
97
 
 
98
            case FFI_TYPE_STRUCT:
 
99
              *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
 
100
              break;
 
101
 
 
102
            default:
 
103
              FFI_ASSERT(0);
 
104
            }
 
105
        }
 
106
      else
 
107
        {
 
108
          memcpy(argp, *p_argv, z);
 
109
        }
 
110
      p_argv++;
 
111
      argp += z;
 
112
    }
 
113
  
 
114
  return;
 
115
}
 
116
 
 
117
/* Perform machine dependent cif processing */
 
118
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
 
119
{
 
120
  /* Set the return type flag */
 
121
  switch (cif->rtype->type)
 
122
    {
 
123
    case FFI_TYPE_VOID:
 
124
#ifdef X86
 
125
    case FFI_TYPE_STRUCT:
 
126
#endif
 
127
#if defined(X86) || defined(X86_DARWIN)
 
128
    case FFI_TYPE_UINT8:
 
129
    case FFI_TYPE_UINT16:
 
130
    case FFI_TYPE_SINT8:
 
131
    case FFI_TYPE_SINT16:
 
132
#endif
 
133
 
 
134
    case FFI_TYPE_SINT64:
 
135
    case FFI_TYPE_FLOAT:
 
136
    case FFI_TYPE_DOUBLE:
 
137
    case FFI_TYPE_LONGDOUBLE:
 
138
      cif->flags = (unsigned) cif->rtype->type;
 
139
      break;
 
140
 
 
141
    case FFI_TYPE_UINT64:
 
142
      cif->flags = FFI_TYPE_SINT64;
 
143
      break;
 
144
 
 
145
#ifndef X86
 
146
    case FFI_TYPE_STRUCT:
 
147
      if (cif->rtype->size == 1)
 
148
        {
 
149
          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
 
150
        }
 
151
      else if (cif->rtype->size == 2)
 
152
        {
 
153
          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
 
154
        }
 
155
      else if (cif->rtype->size == 4)
 
156
        {
 
157
          cif->flags = FFI_TYPE_INT; /* same as int type */
 
158
        }
 
159
      else if (cif->rtype->size == 8)
 
160
        {
 
161
          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
 
162
        }
 
163
      else
 
164
        {
 
165
          cif->flags = FFI_TYPE_STRUCT;
 
166
        }
 
167
      break;
 
168
#endif
 
169
 
 
170
    default:
 
171
      cif->flags = FFI_TYPE_INT;
 
172
      break;
 
173
    }
 
174
 
 
175
#ifdef X86_DARWIN
 
176
  cif->bytes = (cif->bytes + 15) & ~0xF;
 
177
#endif
 
178
 
 
179
  return FFI_OK;
 
180
}
 
181
 
 
182
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
 
183
                          unsigned, unsigned, unsigned *, void (*fn)(void));
 
184
 
 
185
#ifdef X86_WIN32
 
186
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
 
187
                          unsigned, unsigned, unsigned *, void (*fn)(void));
 
188
 
 
189
#endif /* X86_WIN32 */
 
190
 
 
191
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
 
192
{
 
193
  extended_cif ecif;
 
194
 
 
195
  ecif.cif = cif;
 
196
  ecif.avalue = avalue;
 
197
  
 
198
  /* If the return value is a struct and we don't have a return */
 
199
  /* value address then we need to make one                     */
 
200
 
 
201
  if ((rvalue == NULL) && 
 
202
      (cif->flags == FFI_TYPE_STRUCT))
 
203
    {
 
204
      ecif.rvalue = alloca(cif->rtype->size);
 
205
    }
 
206
  else
 
207
    ecif.rvalue = rvalue;
 
208
    
 
209
  
 
210
  switch (cif->abi) 
 
211
    {
 
212
    case FFI_SYSV:
 
213
      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
 
214
                    fn);
 
215
      break;
 
216
#ifdef X86_WIN32
 
217
    case FFI_STDCALL:
 
218
      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
 
219
                       ecif.rvalue, fn);
 
220
      break;
 
221
#endif /* X86_WIN32 */
 
222
    default:
 
223
      FFI_ASSERT(0);
 
224
      break;
 
225
    }
 
226
}
 
227
 
 
228
 
 
229
/** private members **/
 
230
 
 
231
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
 
232
                                         void** args, ffi_cif* cif);
 
233
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
 
234
     __attribute__ ((regparm(1)));
 
235
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
 
236
     __attribute__ ((regparm(1)));
 
237
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
 
238
     __attribute__ ((regparm(1)));
 
239
#ifdef X86_WIN32
 
240
void FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
 
241
     __attribute__ ((regparm(1)));
 
242
#endif
 
243
 
 
244
/* This function is jumped to by the trampoline */
 
245
 
 
246
unsigned int FFI_HIDDEN
 
247
ffi_closure_SYSV_inner (closure, respp, args)
 
248
     ffi_closure *closure;
 
249
     void **respp;
 
250
     void *args;
 
251
{
 
252
  /* our various things...  */
 
253
  ffi_cif       *cif;
 
254
  void         **arg_area;
 
255
 
 
256
  cif         = closure->cif;
 
257
  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));  
 
258
 
 
259
  /* this call will initialize ARG_AREA, such that each
 
260
   * element in that array points to the corresponding 
 
261
   * value on the stack; and if the function returns
 
262
   * a structure, it will re-set RESP to point to the
 
263
   * structure return address.  */
 
264
 
 
265
  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
 
266
 
 
267
  (closure->fun) (cif, *respp, arg_area, closure->user_data);
 
268
 
 
269
  return cif->flags;
 
270
}
 
271
 
 
272
static void
 
273
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
 
274
                            ffi_cif *cif)
 
275
{
 
276
  register unsigned int i;
 
277
  register void **p_argv;
 
278
  register char *argp;
 
279
  register ffi_type **p_arg;
 
280
 
 
281
  argp = stack;
 
282
 
 
283
  if ( cif->flags == FFI_TYPE_STRUCT ) {
 
284
    *rvalue = *(void **) argp;
 
285
    argp += 4;
 
286
  }
 
287
 
 
288
  p_argv = avalue;
 
289
 
 
290
  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
 
291
    {
 
292
      size_t z;
 
293
 
 
294
      /* Align if necessary */
 
295
      if ((sizeof(int) - 1) & (unsigned) argp) {
 
296
        argp = (char *) ALIGN(argp, sizeof(int));
 
297
      }
 
298
 
 
299
      z = (*p_arg)->size;
 
300
 
 
301
      /* because we're little endian, this is what it turns into.   */
 
302
 
 
303
      *p_argv = (void*) argp;
 
304
 
 
305
      p_argv++;
 
306
      argp += z;
 
307
    }
 
308
  
 
309
  return;
 
310
}
 
311
 
 
312
/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
 
313
 
 
314
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
 
315
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
 
316
   unsigned int  __fun = (unsigned int)(FUN); \
 
317
   unsigned int  __ctx = (unsigned int)(CTX); \
 
318
   unsigned int  __dis = __fun - (__ctx + 10);  \
 
319
   *(unsigned char*) &__tramp[0] = 0xb8; \
 
320
   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
 
321
   *(unsigned char *)  &__tramp[5] = 0xe9; \
 
322
   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
 
323
 })
 
324
 
 
325
#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
 
326
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
 
327
   unsigned int  __fun = (unsigned int)(FUN); \
 
328
   unsigned int  __ctx = (unsigned int)(CTX); \
 
329
   unsigned int  __dis = __fun - (__ctx + 10); \
 
330
   unsigned short __size = (unsigned short)(SIZE); \
 
331
   *(unsigned char*) &__tramp[0] = 0xb8; \
 
332
   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
 
333
   *(unsigned char *)  &__tramp[5] = 0xe8; \
 
334
   *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
 
335
   *(unsigned char *)  &__tramp[10] = 0xc2; \
 
336
   *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
 
337
 })
 
338
 
 
339
/* the cif must already be prep'ed */
 
340
 
 
341
ffi_status
 
342
ffi_prep_closure_loc (ffi_closure* closure,
 
343
                      ffi_cif* cif,
 
344
                      void (*fun)(ffi_cif*,void*,void**,void*),
 
345
                      void *user_data,
 
346
                      void *codeloc)
 
347
{
 
348
  if (cif->abi == FFI_SYSV)
 
349
    {
 
350
      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
 
351
                           &ffi_closure_SYSV,
 
352
                           (void*)codeloc);
 
353
    }
 
354
#ifdef X86_WIN32
 
355
  else if (cif->abi == FFI_STDCALL)
 
356
    {
 
357
      FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
 
358
                                   &ffi_closure_STDCALL,
 
359
                                   (void*)codeloc, cif->bytes);
 
360
    }
 
361
#endif
 
362
  else
 
363
    {
 
364
      return FFI_BAD_ABI;
 
365
    }
 
366
    
 
367
  closure->cif  = cif;
 
368
  closure->user_data = user_data;
 
369
  closure->fun  = fun;
 
370
 
 
371
  return FFI_OK;
 
372
}
 
373
 
 
374
/* ------- Native raw API support -------------------------------- */
 
375
 
 
376
#if !FFI_NO_RAW_API
 
377
 
 
378
ffi_status
 
379
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
 
380
                          ffi_cif* cif,
 
381
                          void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
 
382
                          void *user_data,
 
383
                          void *codeloc)
 
384
{
 
385
  int i;
 
386
 
 
387
  if (cif->abi != FFI_SYSV) {
 
388
    return FFI_BAD_ABI;
 
389
  }
 
390
 
 
391
  /* we currently don't support certain kinds of arguments for raw
 
392
  // closures.  This should be implemented by a separate assembly language
 
393
  // routine, since it would require argument processing, something we
 
394
  // don't do now for performance. */
 
395
 
 
396
  for (i = cif->nargs-1; i >= 0; i--)
 
397
    {
 
398
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
 
399
      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
 
400
    }
 
401
  
 
402
 
 
403
  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
 
404
                       codeloc);
 
405
    
 
406
  closure->cif  = cif;
 
407
  closure->user_data = user_data;
 
408
  closure->fun  = fun;
 
409
 
 
410
  return FFI_OK;
 
411
}
 
412
 
 
413
static void 
 
414
ffi_prep_args_raw(char *stack, extended_cif *ecif)
 
415
{
 
416
  memcpy (stack, ecif->avalue, ecif->cif->bytes);
 
417
}
 
418
 
 
419
/* we borrow this routine from libffi (it must be changed, though, to
 
420
 * actually call the function passed in the first argument.  as of
 
421
 * libffi-1.20, this is not the case.)
 
422
 */
 
423
 
 
424
extern void
 
425
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, 
 
426
              unsigned, unsigned *, void (*fn)(void));
 
427
 
 
428
#ifdef X86_WIN32
 
429
extern void
 
430
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
 
431
                 unsigned, unsigned *, void (*fn)(void));
 
432
#endif /* X86_WIN32 */
 
433
 
 
434
void
 
435
ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
 
436
{
 
437
  extended_cif ecif;
 
438
  void **avalue = (void **)fake_avalue;
 
439
 
 
440
  ecif.cif = cif;
 
441
  ecif.avalue = avalue;
 
442
  
 
443
  /* If the return value is a struct and we don't have a return */
 
444
  /* value address then we need to make one                     */
 
445
 
 
446
  if ((rvalue == NULL) && 
 
447
      (cif->rtype->type == FFI_TYPE_STRUCT))
 
448
    {
 
449
      ecif.rvalue = alloca(cif->rtype->size);
 
450
    }
 
451
  else
 
452
    ecif.rvalue = rvalue;
 
453
    
 
454
  
 
455
  switch (cif->abi) 
 
456
    {
 
457
    case FFI_SYSV:
 
458
      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
 
459
                    ecif.rvalue, fn);
 
460
      break;
 
461
#ifdef X86_WIN32
 
462
    case FFI_STDCALL:
 
463
      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
 
464
                       ecif.rvalue, fn);
 
465
      break;
 
466
#endif /* X86_WIN32 */
 
467
    default:
 
468
      FFI_ASSERT(0);
 
469
      break;
 
470
    }
 
471
}
 
472
 
 
473
#endif
 
474
 
 
475
#endif /* __x86_64__  */