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

« back to all changes in this revision

Viewing changes to Modules/_ctypes/libffi_osx/ffi.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
/* -----------------------------------------------------------------------
 
2
   prep_cif.c - Copyright (c) 1996, 1998  Red Hat, Inc.
 
3
 
 
4
   Permission is hereby granted, free of charge, to any person obtaining
 
5
   a copy of this software and associated documentation files (the
 
6
   ``Software''), to deal in the Software without restriction, including
 
7
   without limitation the rights to use, copy, modify, merge, publish,
 
8
   distribute, sublicense, and/or sell copies of the Software, and to
 
9
   permit persons to whom the Software is furnished to do so, subject to
 
10
   the following conditions:
 
11
 
 
12
   The above copyright notice and this permission notice shall be included
 
13
   in all copies or substantial portions of the Software.
 
14
 
 
15
   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
19
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
20
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
21
   OTHER DEALINGS IN THE SOFTWARE.
 
22
   ----------------------------------------------------------------------- */
 
23
 
 
24
#include <ffi.h>
 
25
#include <ffi_common.h>
 
26
 
 
27
#include <stdbool.h>
 
28
#include <stdlib.h>
 
29
 
 
30
/* Round up to FFI_SIZEOF_ARG. */
 
31
#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
 
32
 
 
33
/* Perform machine independent initialization of aggregate type
 
34
   specifications. */
 
35
 
 
36
static ffi_status
 
37
initialize_aggregate(
 
38
/*@out@*/       ffi_type*       arg)
 
39
{
 
40
/*@-usedef@*/
 
41
 
 
42
        if (arg == NULL || arg->elements == NULL ||
 
43
                arg->size != 0 || arg->alignment != 0)
 
44
                return FFI_BAD_TYPEDEF;
 
45
 
 
46
        ffi_type**      ptr = &(arg->elements[0]);
 
47
 
 
48
        while ((*ptr) != NULL)
 
49
        {
 
50
                if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK))
 
51
                        return FFI_BAD_TYPEDEF;
 
52
 
 
53
                /* Perform a sanity check on the argument type */
 
54
                FFI_ASSERT_VALID_TYPE(*ptr);
 
55
 
 
56
#ifdef POWERPC_DARWIN
 
57
                int curalign = (*ptr)->alignment;
 
58
 
 
59
                if (ptr != &(arg->elements[0]))
 
60
                {
 
61
                        if (curalign > 4 && curalign != 16)
 
62
                                curalign = 4;
 
63
                }
 
64
 
 
65
                arg->size               = ALIGN(arg->size, curalign);
 
66
                arg->size               += (*ptr)->size;
 
67
                arg->alignment  = (arg->alignment > curalign) ? 
 
68
                        arg->alignment : curalign;
 
69
#else
 
70
                arg->size               = ALIGN(arg->size, (*ptr)->alignment);
 
71
                arg->size               += (*ptr)->size;
 
72
                arg->alignment  = (arg->alignment > (*ptr)->alignment) ? 
 
73
                        arg->alignment : (*ptr)->alignment;
 
74
#endif
 
75
 
 
76
                ptr++;
 
77
    }
 
78
 
 
79
  /* Structure size includes tail padding.  This is important for
 
80
     structures that fit in one register on ABIs like the PowerPC64
 
81
     Linux ABI that right justify small structs in a register.
 
82
     It's also needed for nested structure layout, for example
 
83
     struct A { long a; char b; }; struct B { struct A x; char y; };
 
84
     should find y at an offset of 2*sizeof(long) and result in a
 
85
     total size of 3*sizeof(long).  */
 
86
        arg->size = ALIGN(arg->size, arg->alignment);
 
87
 
 
88
        if (arg->size == 0)
 
89
                return FFI_BAD_TYPEDEF;
 
90
 
 
91
        return FFI_OK;
 
92
 
 
93
/*@=usedef@*/
 
94
}
 
95
 
 
96
#ifndef __CRIS__
 
97
/* The CRIS ABI specifies structure elements to have byte
 
98
   alignment only, so it completely overrides this functions,
 
99
   which assumes "natural" alignment and padding.  */
 
100
 
 
101
/* Perform machine independent ffi_cif preparation, then call
 
102
   machine dependent routine. */
 
103
 
 
104
#if defined(X86_DARWIN)
 
105
 
 
106
static inline bool
 
107
struct_on_stack(
 
108
        int     size)
 
109
{
 
110
        if (size > 8)
 
111
                return true;
 
112
 
 
113
        /* This is not what the ABI says, but is what is really implemented */
 
114
        switch (size)
 
115
        {
 
116
                case 1:
 
117
                case 2:
 
118
                case 4:
 
119
                case 8:
 
120
                        return false;
 
121
 
 
122
                default:
 
123
                        return true;
 
124
        }
 
125
}
 
126
 
 
127
#endif  // defined(X86_DARWIN)
 
128
 
 
129
// Arguments' ffi_type->alignment must be nonzero.
 
130
ffi_status
 
131
ffi_prep_cif(
 
132
/*@out@*/ /*@partial@*/ ffi_cif*                cif, 
 
133
                                                ffi_abi                 abi,
 
134
                                                unsigned int    nargs, 
 
135
/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type*       rtype, 
 
136
/*@dependent@*/                 ffi_type**              atypes)
 
137
{
 
138
        if (cif == NULL)
 
139
                return FFI_BAD_TYPEDEF;
 
140
 
 
141
        if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI)
 
142
                return FFI_BAD_ABI;
 
143
 
 
144
        unsigned int    bytes   = 0;
 
145
        unsigned int    i;
 
146
        ffi_type**              ptr;
 
147
 
 
148
        cif->abi = abi;
 
149
        cif->arg_types = atypes;
 
150
        cif->nargs = nargs;
 
151
        cif->rtype = rtype;
 
152
        cif->flags = 0;
 
153
 
 
154
        /* Initialize the return type if necessary */
 
155
        /*@-usedef@*/
 
156
        if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
 
157
                return FFI_BAD_TYPEDEF;
 
158
        /*@=usedef@*/
 
159
 
 
160
        /* Perform a sanity check on the return type */
 
161
        FFI_ASSERT_VALID_TYPE(cif->rtype);
 
162
 
 
163
        /* x86-64 and s390 stack space allocation is handled in prep_machdep.  */
 
164
#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA
 
165
        /* Make space for the return structure pointer */
 
166
        if (cif->rtype->type == FFI_TYPE_STRUCT
 
167
#ifdef SPARC
 
168
                && (cif->abi != FFI_V9 || cif->rtype->size > 32)
 
169
#endif
 
170
#ifdef X86_DARWIN
 
171
                && (struct_on_stack(cif->rtype->size))
 
172
#endif
 
173
                )
 
174
                bytes = STACK_ARG_SIZE(sizeof(void*));
 
175
#endif
 
176
 
 
177
        for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
 
178
        {
 
179
                /* Initialize any uninitialized aggregate type definitions */
 
180
                if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
 
181
                        return FFI_BAD_TYPEDEF;
 
182
 
 
183
                if ((*ptr)->alignment == 0)
 
184
                        return FFI_BAD_TYPEDEF;
 
185
 
 
186
                /* Perform a sanity check on the argument type, do this 
 
187
                check after the initialization.  */
 
188
                FFI_ASSERT_VALID_TYPE(*ptr);
 
189
 
 
190
#if defined(X86_DARWIN)
 
191
                {
 
192
                        int align = (*ptr)->alignment;
 
193
 
 
194
                        if (align > 4)
 
195
                                align = 4;
 
196
 
 
197
                        if ((align - 1) & bytes)
 
198
                                bytes = ALIGN(bytes, align);
 
199
 
 
200
                        bytes += STACK_ARG_SIZE((*ptr)->size);
 
201
                }
 
202
#elif !defined __x86_64__ && !defined S390 && !defined PA
 
203
#ifdef SPARC
 
204
                if (((*ptr)->type == FFI_TYPE_STRUCT
 
205
                        && ((*ptr)->size > 16 || cif->abi != FFI_V9))
 
206
                        || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
 
207
                        && cif->abi != FFI_V9))
 
208
                                bytes += sizeof(void*);
 
209
                else
 
210
#endif
 
211
                {
 
212
                        /* Add any padding if necessary */
 
213
                        if (((*ptr)->alignment - 1) & bytes)
 
214
                                bytes = ALIGN(bytes, (*ptr)->alignment);
 
215
 
 
216
                        bytes += STACK_ARG_SIZE((*ptr)->size);
 
217
                }
 
218
#endif
 
219
        }
 
220
 
 
221
        cif->bytes = bytes;
 
222
 
 
223
        /* Perform machine dependent cif processing */
 
224
        return ffi_prep_cif_machdep(cif);
 
225
}
 
226
#endif /* not __CRIS__ */