~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifdef __i386__
 
2
/* -----------------------------------------------------------------------
 
3
   ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
 
4
           Copyright (c) 2002  Ranjit Mathew
 
5
           Copyright (c) 2002  Bo Thorsen
 
6
           Copyright (c) 2002  Roger Sayle
 
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, EXPRESS
 
22
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
23
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
24
   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
25
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
26
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
27
   OTHER DEALINGS IN THE SOFTWARE.
 
28
   ----------------------------------------------------------------------- */
 
29
 
 
30
//#ifndef __x86_64__
 
31
 
 
32
#include <ffi.h>
 
33
#include <ffi_common.h>
 
34
 
 
35
#include <stdlib.h>
 
36
 
 
37
//void ffi_prep_args(char *stack, extended_cif *ecif);
 
38
 
 
39
static inline int
 
40
retval_on_stack(
 
41
        ffi_type*       tp)
 
42
{
 
43
        if (tp->type == FFI_TYPE_STRUCT)
 
44
        {
 
45
//              int size = tp->size;
 
46
 
 
47
                if (tp->size > 8)
 
48
                        return 1;
 
49
 
 
50
                switch (tp->size)
 
51
                {
 
52
                        case 1: case 2: case 4: case 8:
 
53
                                return 0;
 
54
                        default:
 
55
                                return 1;
 
56
                }
 
57
        }
 
58
 
 
59
        return 0;
 
60
}
 
61
 
 
62
/* ffi_prep_args is called by the assembly routine once stack space
 
63
   has been allocated for the function's arguments */
 
64
/*@-exportheader@*/
 
65
extern void ffi_prep_args(char*, extended_cif*);
 
66
void
 
67
ffi_prep_args(
 
68
        char*                   stack,
 
69
        extended_cif*   ecif)
 
70
/*@=exportheader@*/
 
71
{
 
72
        register unsigned int   i;
 
73
        register void**                 p_argv = ecif->avalue;
 
74
        register char*                  argp = stack;
 
75
        register ffi_type**             p_arg;
 
76
 
 
77
        if (retval_on_stack(ecif->cif->rtype))
 
78
        {
 
79
                *(void**)argp = ecif->rvalue;
 
80
                argp += 4;
 
81
        }
 
82
 
 
83
        p_arg = ecif->cif->arg_types;
 
84
 
 
85
        for (i = ecif->cif->nargs; i > 0; i--, p_arg++, p_argv++)
 
86
    {
 
87
                size_t z = (*p_arg)->size;
 
88
 
 
89
                /* Align if necessary */
 
90
                if ((sizeof(int) - 1) & (unsigned)argp)
 
91
                        argp = (char*)ALIGN(argp, sizeof(int));
 
92
 
 
93
                if (z < sizeof(int))
 
94
                {
 
95
                        z = sizeof(int);
 
96
 
 
97
                        switch ((*p_arg)->type)
 
98
                        {
 
99
                                case FFI_TYPE_SINT8:
 
100
                                        *(signed int*)argp = (signed int)*(SINT8*)(*p_argv);
 
101
                                        break;
 
102
 
 
103
                                case FFI_TYPE_UINT8:
 
104
                                        *(unsigned int*)argp = (unsigned int)*(UINT8*)(*p_argv);
 
105
                                        break;
 
106
 
 
107
                                case FFI_TYPE_SINT16:
 
108
                                        *(signed int*)argp = (signed int)*(SINT16*)(*p_argv);
 
109
                                        break;
 
110
 
 
111
                                case FFI_TYPE_UINT16:
 
112
                                        *(unsigned int*)argp = (unsigned int)*(UINT16*)(*p_argv);
 
113
                                        break;
 
114
 
 
115
                                case FFI_TYPE_SINT32:
 
116
                                        *(signed int*)argp = (signed int)*(SINT32*)(*p_argv);
 
117
                                        break;
 
118
 
 
119
                                case FFI_TYPE_UINT32:
 
120
                                        *(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
 
121
                                        break;
 
122
 
 
123
                                case FFI_TYPE_STRUCT:
 
124
                                        *(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
 
125
                                        break;
 
126
 
 
127
                                default:
 
128
                                        FFI_ASSERT(0);
 
129
                                        break;
 
130
                        }
 
131
                }
 
132
                else
 
133
                        memcpy(argp, *p_argv, z);
 
134
 
 
135
                argp += z;
 
136
        }
 
137
}
 
138
 
 
139
/* Perform machine dependent cif processing */
 
140
ffi_status
 
141
ffi_prep_cif_machdep(
 
142
        ffi_cif*        cif)
 
143
{
 
144
        /* Set the return type flag */
 
145
        switch (cif->rtype->type)
 
146
        {
 
147
#if !defined(X86_WIN32)  && !defined(X86_DARWIN)
 
148
                case FFI_TYPE_STRUCT:
 
149
#endif
 
150
                case FFI_TYPE_VOID:
 
151
                case FFI_TYPE_SINT64:
 
152
                case FFI_TYPE_FLOAT:
 
153
                case FFI_TYPE_DOUBLE:
 
154
                case FFI_TYPE_LONGDOUBLE:
 
155
                        cif->flags = (unsigned)cif->rtype->type;
 
156
                        break;
 
157
 
 
158
                case FFI_TYPE_UINT64:
 
159
                        cif->flags = FFI_TYPE_SINT64;
 
160
                        break;
 
161
 
 
162
#if defined(X86_WIN32) || defined(X86_DARWIN)
 
163
                case FFI_TYPE_STRUCT:
 
164
                        switch (cif->rtype->size)
 
165
                        {
 
166
                                case 1:
 
167
                                        cif->flags = FFI_TYPE_SINT8;
 
168
                                        break;
 
169
 
 
170
                                case 2:
 
171
                                        cif->flags = FFI_TYPE_SINT16;
 
172
                                        break;
 
173
 
 
174
                                case 4:
 
175
                                        cif->flags = FFI_TYPE_INT;
 
176
                                        break;
 
177
 
 
178
                                case 8:
 
179
                                        cif->flags = FFI_TYPE_SINT64;
 
180
                                        break;
 
181
 
 
182
                                default:
 
183
                                        cif->flags = FFI_TYPE_STRUCT;
 
184
                                        break;
 
185
                        }
 
186
 
 
187
                        break;
 
188
#endif
 
189
 
 
190
                default:
 
191
                        cif->flags = FFI_TYPE_INT;
 
192
                        break;
 
193
        }
 
194
 
 
195
        /* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
 
196
        cif->bytes = (cif->bytes + 15) & ~0xF;
 
197
 
 
198
        return FFI_OK;
 
199
}
 
200
 
 
201
/*@-declundef@*/
 
202
/*@-exportheader@*/
 
203
extern void
 
204
ffi_call_SYSV(
 
205
                        void                    (*)(char *, extended_cif *), 
 
206
/*@out@*/       extended_cif*   , 
 
207
                        unsigned                ,
 
208
                        unsigned                , 
 
209
/*@out@*/       unsigned*               , 
 
210
                        void                    (*fn)(void));
 
211
/*@=declundef@*/
 
212
/*@=exportheader@*/
 
213
 
 
214
#ifdef X86_WIN32
 
215
/*@-declundef@*/
 
216
/*@-exportheader@*/
 
217
extern void
 
218
ffi_call_STDCALL(
 
219
                        void                    (char *, extended_cif *),
 
220
/*@out@*/       extended_cif*   ,
 
221
                        unsigned                ,
 
222
                        unsigned                ,
 
223
/*@out@*/       unsigned*               ,
 
224
                        void                    (*fn)(void));
 
225
/*@=declundef@*/
 
226
/*@=exportheader@*/
 
227
#endif /* X86_WIN32 */
 
228
 
 
229
void
 
230
ffi_call(
 
231
/*@dependent@*/ ffi_cif*        cif, 
 
232
                                void            (*fn)(void), 
 
233
/*@out@*/               void*           rvalue, 
 
234
/*@dependent@*/ void**          avalue)
 
235
{
 
236
        extended_cif ecif;
 
237
 
 
238
        ecif.cif = cif;
 
239
        ecif.avalue = avalue;
 
240
 
 
241
        /*      If the return value is a struct and we don't have a return
 
242
                value address then we need to make one. */
 
243
 
 
244
        if ((rvalue == NULL) && retval_on_stack(cif->rtype))
 
245
        {
 
246
                /*@-sysunrecog@*/
 
247
                ecif.rvalue = alloca(cif->rtype->size);
 
248
                /*@=sysunrecog@*/
 
249
        }
 
250
        else
 
251
                ecif.rvalue = rvalue;
 
252
 
 
253
        switch (cif->abi) 
 
254
        {
 
255
                case FFI_SYSV:
 
256
                        /*@-usedef@*/
 
257
                        /*      To avoid changing the assembly code make sure the size of the argument 
 
258
                                block is a multiple of 16. Then add 8 to compensate for local variables
 
259
                                in ffi_call_SYSV.       */
 
260
                        ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
 
261
                                cif->flags, ecif.rvalue, fn);
 
262
                        /*@=usedef@*/
 
263
                        break;
 
264
 
 
265
#ifdef X86_WIN32
 
266
                case FFI_STDCALL:
 
267
                        /*@-usedef@*/
 
268
                        ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
 
269
                                cif->flags, ecif.rvalue, fn);
 
270
                        /*@=usedef@*/
 
271
                        break;
 
272
#endif /* X86_WIN32 */
 
273
 
 
274
                default:
 
275
                        FFI_ASSERT(0);
 
276
                        break;
 
277
        }
 
278
}
 
279
 
 
280
/** private members **/
 
281
 
 
282
static void
 
283
ffi_closure_SYSV(
 
284
        ffi_closure*    closure) __attribute__((regparm(1)));
 
285
 
 
286
#if !FFI_NO_RAW_API
 
287
static void
 
288
ffi_closure_raw_SYSV(
 
289
        ffi_raw_closure*        closure) __attribute__((regparm(1)));
 
290
#endif
 
291
 
 
292
/*@-exportheader@*/
 
293
static inline
 
294
void 
 
295
ffi_prep_incoming_args_SYSV(
 
296
        char*           stack,
 
297
        void**          rvalue,
 
298
        void**          avalue,
 
299
        ffi_cif*        cif)
 
300
/*@=exportheader@*/
 
301
{
 
302
        register unsigned int   i;
 
303
        register void**                 p_argv = avalue;
 
304
        register char*                  argp = stack;
 
305
        register ffi_type**             p_arg;
 
306
 
 
307
        if (retval_on_stack(cif->rtype))
 
308
        {
 
309
                *rvalue = *(void**)argp;
 
310
                argp += 4;
 
311
        }
 
312
 
 
313
        for (i = cif->nargs, p_arg = cif->arg_types; i > 0; i--, p_arg++, p_argv++)
 
314
        {
 
315
//              size_t z;
 
316
 
 
317
                /* Align if necessary */
 
318
                if ((sizeof(int) - 1) & (unsigned)argp)
 
319
                        argp = (char*)ALIGN(argp, sizeof(int));
 
320
 
 
321
//              z = (*p_arg)->size;
 
322
 
 
323
                /* because we're little endian, this is what it turns into.   */
 
324
                *p_argv = (void*)argp;
 
325
 
 
326
                argp += (*p_arg)->size;
 
327
        }
 
328
}
 
329
 
 
330
/* This function is jumped to by the trampoline */
 
331
__attribute__((regparm(1)))
 
332
static void
 
333
ffi_closure_SYSV(
 
334
        ffi_closure*    closure)
 
335
{
 
336
        long double     res;
 
337
        ffi_cif*        cif = closure->cif;
 
338
        void**          arg_area = (void**)alloca(cif->nargs * sizeof(void*));
 
339
        void*           resp = (void*)&res;
 
340
        void*           args = __builtin_dwarf_cfa();
 
341
 
 
342
        /*      This call will initialize ARG_AREA, such that each
 
343
                element in that array points to the corresponding 
 
344
                value on the stack; and if the function returns
 
345
                a structure, it will reset RESP to point to the
 
346
                structure return address.       */
 
347
        ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
 
348
 
 
349
        (closure->fun)(cif, resp, arg_area, closure->user_data);
 
350
 
 
351
        /* now, do a generic return based on the value of rtype */
 
352
        if (cif->flags == FFI_TYPE_INT)
 
353
                asm("movl       (%0),%%eax"
 
354
                        : : "r" (resp) : "eax");
 
355
        else if (cif->flags == FFI_TYPE_FLOAT)
 
356
                asm("flds       (%0)"
 
357
                        : : "r" (resp) : "st");
 
358
        else if (cif->flags == FFI_TYPE_DOUBLE)
 
359
                asm("fldl       (%0)"
 
360
                        : : "r" (resp) : "st", "st(1)");
 
361
        else if (cif->flags == FFI_TYPE_LONGDOUBLE)
 
362
                asm("fldt       (%0)"
 
363
                        : : "r" (resp) : "st", "st(1)");
 
364
        else if (cif->flags == FFI_TYPE_SINT64)
 
365
                asm("movl       0(%0),%%eax;"
 
366
                        "movl   4(%0),%%edx" 
 
367
                        : : "r" (resp)
 
368
                        : "eax", "edx");
 
369
 
 
370
#if defined(X86_WIN32) || defined(X86_DARWIN)
 
371
        else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct  */
 
372
                asm("movsbl     (%0),%%eax"
 
373
                        : : "r" (resp) : "eax");
 
374
        else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
 
375
                asm("movswl     (%0),%%eax"
 
376
                        : : "r" (resp) : "eax");
 
377
#endif
 
378
 
 
379
        else if (cif->flags == FFI_TYPE_STRUCT)
 
380
                asm("lea -8(%ebp),%esp;"
 
381
                        "pop %esi;"
 
382
                        "pop %edi;"
 
383
                        "pop %ebp;"
 
384
                        "ret $4");
 
385
}
 
386
 
 
387
 
 
388
/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
 
389
#define FFI_INIT_TRAMPOLINE(TRAMP, FUN, CTX)                                                                                    \
 
390
        ({                                                                                                                                                                      \
 
391
                unsigned char*  __tramp = (unsigned char*)(TRAMP);                                                              \
 
392
                unsigned int    __fun = (unsigned int)(FUN);                                                                    \
 
393
                unsigned int    __ctx = (unsigned int)(CTX);                                                                    \
 
394
                unsigned int    __dis = __fun - ((unsigned int)__tramp + FFI_TRAMPOLINE_SIZE);  \
 
395
                *(unsigned char*)&__tramp[0] = 0xb8;                                                                                    \
 
396
                *(unsigned int*)&__tramp[1] = __ctx;    /* movl __ctx, %eax */                                  \
 
397
                *(unsigned char*)&__tramp[5] = 0xe9;                                                                                    \
 
398
                *(unsigned int*)&__tramp[6] = __dis;    /* jmp __fun  */                                                \
 
399
        })
 
400
 
 
401
/* the cif must already be prep'ed */
 
402
ffi_status
 
403
ffi_prep_closure(
 
404
        ffi_closure*    closure,
 
405
        ffi_cif*                cif,
 
406
        void                    (*fun)(ffi_cif*,void*,void**,void*),
 
407
        void*                   user_data)
 
408
{
 
409
//      FFI_ASSERT(cif->abi == FFI_SYSV);
 
410
        if (cif->abi != FFI_SYSV)
 
411
                return FFI_BAD_ABI;
 
412
 
 
413
        FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_SYSV, (void*)closure);
 
414
 
 
415
        closure->cif            = cif;
 
416
        closure->user_data      = user_data;
 
417
        closure->fun            = fun;
 
418
 
 
419
        return FFI_OK;
 
420
}
 
421
 
 
422
/* ------- Native raw API support -------------------------------- */
 
423
 
 
424
#if !FFI_NO_RAW_API
 
425
 
 
426
__attribute__((regparm(1)))
 
427
static void
 
428
ffi_closure_raw_SYSV(
 
429
        ffi_raw_closure*        closure)
 
430
{
 
431
        long double             res;
 
432
        ffi_raw*                raw_args = (ffi_raw*)__builtin_dwarf_cfa();
 
433
        ffi_cif*                cif = closure->cif;
 
434
        unsigned short  rtype = cif->flags;
 
435
        void*                   resp = (void*)&res;
 
436
 
 
437
        (closure->fun)(cif, resp, raw_args, closure->user_data);
 
438
 
 
439
        /* now, do a generic return based on the value of rtype */
 
440
        if (rtype == FFI_TYPE_INT)
 
441
                asm("movl       (%0),%%eax"
 
442
                        : : "r" (resp) : "eax");
 
443
        else if (rtype == FFI_TYPE_FLOAT)
 
444
                asm("flds       (%0)"
 
445
                        : : "r" (resp) : "st");
 
446
        else if (rtype == FFI_TYPE_DOUBLE)
 
447
                asm("fldl       (%0)"
 
448
                        : : "r" (resp) : "st", "st(1)");
 
449
        else if (rtype == FFI_TYPE_LONGDOUBLE)
 
450
                asm("fldt       (%0)"
 
451
                        : : "r" (resp) : "st", "st(1)");
 
452
        else if (rtype == FFI_TYPE_SINT64)
 
453
                asm("movl       0(%0),%%eax;"
 
454
                        "movl   4(%0),%%edx" 
 
455
                        : : "r" (resp) : "eax", "edx");
 
456
}
 
457
 
 
458
ffi_status
 
459
ffi_prep_raw_closure(
 
460
        ffi_raw_closure*        closure,
 
461
        ffi_cif*                        cif,
 
462
        void                            (*fun)(ffi_cif*,void*,ffi_raw*,void*),
 
463
        void*                           user_data)
 
464
{
 
465
//      FFI_ASSERT (cif->abi == FFI_SYSV);
 
466
        if (cif->abi != FFI_SYSV)
 
467
                return FFI_BAD_ABI;
 
468
 
 
469
        int i;
 
470
 
 
471
/*      We currently don't support certain kinds of arguments for raw
 
472
        closures.  This should be implemented by a separate assembly language
 
473
        routine, since it would require argument processing, something we
 
474
        don't do now for performance.   */
 
475
        for (i = cif->nargs - 1; i >= 0; i--)
 
476
        {
 
477
                FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_STRUCT);
 
478
                FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
 
479
        }
 
480
 
 
481
        FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_raw_SYSV, (void*)closure);
 
482
 
 
483
        closure->cif            = cif;
 
484
        closure->user_data      = user_data;
 
485
        closure->fun            = fun;
 
486
 
 
487
        return FFI_OK;
 
488
}
 
489
 
 
490
static void 
 
491
ffi_prep_args_raw(
 
492
        char*                   stack,
 
493
        extended_cif*   ecif)
 
494
{
 
495
        memcpy(stack, ecif->avalue, ecif->cif->bytes);
 
496
}
 
497
 
 
498
/*      We borrow this routine from libffi (it must be changed, though, to
 
499
        actually call the function passed in the first argument.  as of
 
500
        libffi-1.20, this is not the case.)     */
 
501
//extern void 
 
502
//ffi_call_SYSV(
 
503
//                      void                    (*)(char *, extended_cif *), 
 
504
///*@out@*/     extended_cif*   , 
 
505
//                      unsigned                ,
 
506
//                      unsigned                , 
 
507
//*@out@*/      unsigned*               , 
 
508
//                      void                    (*fn)());
 
509
 
 
510
#ifdef X86_WIN32
 
511
extern void
 
512
ffi_call_STDCALL(
 
513
                        void                    (*)(char *, extended_cif *),
 
514
/*@out@*/       extended_cif*   ,
 
515
                        unsigned                ,
 
516
                        unsigned                ,
 
517
/*@out@*/       unsigned*               ,
 
518
                        void                    (*fn)());
 
519
#endif // X86_WIN32
 
520
 
 
521
void
 
522
ffi_raw_call(
 
523
/*@dependent@*/ ffi_cif*        cif, 
 
524
                                void            (*fn)(), 
 
525
/*@out@*/               void*           rvalue, 
 
526
/*@dependent@*/ ffi_raw*        fake_avalue)
 
527
{
 
528
        extended_cif ecif;
 
529
        void **avalue = (void **)fake_avalue;
 
530
 
 
531
        ecif.cif = cif;
 
532
        ecif.avalue = avalue;
 
533
 
 
534
        /*      If the return value is a struct and we don't have a return
 
535
                value address then we need to make one  */
 
536
        if ((rvalue == NULL) && retval_on_stack(cif->rtype)) 
 
537
        {
 
538
                /*@-sysunrecog@*/
 
539
                ecif.rvalue = alloca(cif->rtype->size);
 
540
                /*@=sysunrecog@*/
 
541
        }
 
542
        else
 
543
                ecif.rvalue = rvalue;
 
544
 
 
545
        switch (cif->abi) 
 
546
        {
 
547
                case FFI_SYSV:
 
548
                        /*@-usedef@*/
 
549
                        ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, 
 
550
                                cif->flags, ecif.rvalue, fn);
 
551
                        /*@=usedef@*/
 
552
                        break;
 
553
#ifdef X86_WIN32
 
554
                case FFI_STDCALL:
 
555
                        /*@-usedef@*/
 
556
                        ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
 
557
                                cif->flags, ecif.rvalue, fn);
 
558
                        /*@=usedef@*/
 
559
                        break;
 
560
#endif /* X86_WIN32 */
 
561
                default:
 
562
                        FFI_ASSERT(0);
 
563
                        break;
 
564
    }
 
565
}
 
566
 
 
567
#endif  // !FFI_NO_RAW_API
 
568
//#endif        // !__x86_64__
 
569
#endif  // __i386__