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