annotate libffi/src/aarch64/ffi.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 04ced10e8804
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
kono
parents:
diff changeset
2
kono
parents:
diff changeset
3 Permission is hereby granted, free of charge, to any person obtaining
kono
parents:
diff changeset
4 a copy of this software and associated documentation files (the
kono
parents:
diff changeset
5 ``Software''), to deal in the Software without restriction, including
kono
parents:
diff changeset
6 without limitation the rights to use, copy, modify, merge, publish,
kono
parents:
diff changeset
7 distribute, sublicense, and/or sell copies of the Software, and to
kono
parents:
diff changeset
8 permit persons to whom the Software is furnished to do so, subject to
kono
parents:
diff changeset
9 the following conditions:
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 The above copyright notice and this permission notice shall be
kono
parents:
diff changeset
12 included in all copies or substantial portions of the Software.
kono
parents:
diff changeset
13
kono
parents:
diff changeset
14 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
kono
parents:
diff changeset
15 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
kono
parents:
diff changeset
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
kono
parents:
diff changeset
17 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
kono
parents:
diff changeset
18 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
kono
parents:
diff changeset
19 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
kono
parents:
diff changeset
20 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 #include <stdio.h>
kono
parents:
diff changeset
23 #include <stdlib.h>
kono
parents:
diff changeset
24 #include <stdint.h>
kono
parents:
diff changeset
25 #include <ffi.h>
kono
parents:
diff changeset
26 #include <ffi_common.h>
kono
parents:
diff changeset
27 #include "internal.h"
kono
parents:
diff changeset
28
kono
parents:
diff changeset
29 /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
kono
parents:
diff changeset
30 all further uses in this file will refer to the 128-bit type. */
kono
parents:
diff changeset
31 #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
kono
parents:
diff changeset
32 # if FFI_TYPE_LONGDOUBLE != 4
kono
parents:
diff changeset
33 # error FFI_TYPE_LONGDOUBLE out of date
kono
parents:
diff changeset
34 # endif
kono
parents:
diff changeset
35 #else
kono
parents:
diff changeset
36 # undef FFI_TYPE_LONGDOUBLE
kono
parents:
diff changeset
37 # define FFI_TYPE_LONGDOUBLE 4
kono
parents:
diff changeset
38 #endif
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 union _d
kono
parents:
diff changeset
41 {
kono
parents:
diff changeset
42 UINT64 d;
kono
parents:
diff changeset
43 UINT32 s[2];
kono
parents:
diff changeset
44 };
kono
parents:
diff changeset
45
kono
parents:
diff changeset
46 struct _v
kono
parents:
diff changeset
47 {
kono
parents:
diff changeset
48 union _d d[2] __attribute__((aligned(16)));
kono
parents:
diff changeset
49 };
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 struct call_context
kono
parents:
diff changeset
52 {
kono
parents:
diff changeset
53 struct _v v[N_V_ARG_REG];
kono
parents:
diff changeset
54 UINT64 x[N_X_ARG_REG];
kono
parents:
diff changeset
55 };
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 #if defined (__clang__) && defined (__APPLE__)
kono
parents:
diff changeset
58 extern void sys_icache_invalidate (void *start, size_t len);
kono
parents:
diff changeset
59 #endif
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 static inline void
kono
parents:
diff changeset
62 ffi_clear_cache (void *start, void *end)
kono
parents:
diff changeset
63 {
kono
parents:
diff changeset
64 #if defined (__clang__) && defined (__APPLE__)
kono
parents:
diff changeset
65 sys_icache_invalidate (start, (char *)end - (char *)start);
kono
parents:
diff changeset
66 #elif defined (__GNUC__)
kono
parents:
diff changeset
67 __builtin___clear_cache (start, end);
kono
parents:
diff changeset
68 #else
kono
parents:
diff changeset
69 #error "Missing builtin to flush instruction cache"
kono
parents:
diff changeset
70 #endif
kono
parents:
diff changeset
71 }
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 /* A subroutine of is_vfp_type. Given a structure type, return the type code
kono
parents:
diff changeset
74 of the first non-structure element. Recurse for structure elements.
kono
parents:
diff changeset
75 Return -1 if the structure is in fact empty, i.e. no nested elements. */
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 static int
kono
parents:
diff changeset
78 is_hfa0 (const ffi_type *ty)
kono
parents:
diff changeset
79 {
kono
parents:
diff changeset
80 ffi_type **elements = ty->elements;
kono
parents:
diff changeset
81 int i, ret = -1;
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 if (elements != NULL)
kono
parents:
diff changeset
84 for (i = 0; elements[i]; ++i)
kono
parents:
diff changeset
85 {
kono
parents:
diff changeset
86 ret = elements[i]->type;
kono
parents:
diff changeset
87 if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
kono
parents:
diff changeset
88 {
kono
parents:
diff changeset
89 ret = is_hfa0 (elements[i]);
kono
parents:
diff changeset
90 if (ret < 0)
kono
parents:
diff changeset
91 continue;
kono
parents:
diff changeset
92 }
kono
parents:
diff changeset
93 break;
kono
parents:
diff changeset
94 }
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 return ret;
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 /* A subroutine of is_vfp_type. Given a structure type, return true if all
kono
parents:
diff changeset
100 of the non-structure elements are the same as CANDIDATE. */
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 static int
kono
parents:
diff changeset
103 is_hfa1 (const ffi_type *ty, int candidate)
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 ffi_type **elements = ty->elements;
kono
parents:
diff changeset
106 int i;
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 if (elements != NULL)
kono
parents:
diff changeset
109 for (i = 0; elements[i]; ++i)
kono
parents:
diff changeset
110 {
kono
parents:
diff changeset
111 int t = elements[i]->type;
kono
parents:
diff changeset
112 if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
kono
parents:
diff changeset
113 {
kono
parents:
diff changeset
114 if (!is_hfa1 (elements[i], candidate))
kono
parents:
diff changeset
115 return 0;
kono
parents:
diff changeset
116 }
kono
parents:
diff changeset
117 else if (t != candidate)
kono
parents:
diff changeset
118 return 0;
kono
parents:
diff changeset
119 }
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 return 1;
kono
parents:
diff changeset
122 }
kono
parents:
diff changeset
123
kono
parents:
diff changeset
124 /* Determine if TY may be allocated to the FP registers. This is both an
kono
parents:
diff changeset
125 fp scalar type as well as an homogenous floating point aggregate (HFA).
kono
parents:
diff changeset
126 That is, a structure consisting of 1 to 4 members of all the same type,
kono
parents:
diff changeset
127 where that type is an fp scalar.
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 Returns non-zero iff TY is an HFA. The result is the AARCH64_RET_*
kono
parents:
diff changeset
130 constant for the type. */
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 static int
kono
parents:
diff changeset
133 is_vfp_type (const ffi_type *ty)
kono
parents:
diff changeset
134 {
kono
parents:
diff changeset
135 ffi_type **elements;
kono
parents:
diff changeset
136 int candidate, i;
kono
parents:
diff changeset
137 size_t size, ele_count;
kono
parents:
diff changeset
138
kono
parents:
diff changeset
139 /* Quickest tests first. */
kono
parents:
diff changeset
140 candidate = ty->type;
kono
parents:
diff changeset
141 switch (candidate)
kono
parents:
diff changeset
142 {
kono
parents:
diff changeset
143 default:
kono
parents:
diff changeset
144 return 0;
kono
parents:
diff changeset
145 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
146 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
147 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
148 ele_count = 1;
kono
parents:
diff changeset
149 goto done;
kono
parents:
diff changeset
150 case FFI_TYPE_COMPLEX:
kono
parents:
diff changeset
151 candidate = ty->elements[0]->type;
kono
parents:
diff changeset
152 switch (candidate)
kono
parents:
diff changeset
153 {
kono
parents:
diff changeset
154 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
155 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
156 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
157 ele_count = 2;
kono
parents:
diff changeset
158 goto done;
kono
parents:
diff changeset
159 }
kono
parents:
diff changeset
160 return 0;
kono
parents:
diff changeset
161 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
162 break;
kono
parents:
diff changeset
163 }
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 /* No HFA types are smaller than 4 bytes, or larger than 64 bytes. */
kono
parents:
diff changeset
166 size = ty->size;
kono
parents:
diff changeset
167 if (size < 4 || size > 64)
kono
parents:
diff changeset
168 return 0;
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 /* Find the type of the first non-structure member. */
kono
parents:
diff changeset
171 elements = ty->elements;
kono
parents:
diff changeset
172 candidate = elements[0]->type;
kono
parents:
diff changeset
173 if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
kono
parents:
diff changeset
174 {
kono
parents:
diff changeset
175 for (i = 0; ; ++i)
kono
parents:
diff changeset
176 {
kono
parents:
diff changeset
177 candidate = is_hfa0 (elements[i]);
kono
parents:
diff changeset
178 if (candidate >= 0)
kono
parents:
diff changeset
179 break;
kono
parents:
diff changeset
180 }
kono
parents:
diff changeset
181 }
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 /* If the first member is not a floating point type, it's not an HFA.
kono
parents:
diff changeset
184 Also quickly re-check the size of the structure. */
kono
parents:
diff changeset
185 switch (candidate)
kono
parents:
diff changeset
186 {
kono
parents:
diff changeset
187 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
188 ele_count = size / sizeof(float);
kono
parents:
diff changeset
189 if (size != ele_count * sizeof(float))
kono
parents:
diff changeset
190 return 0;
kono
parents:
diff changeset
191 break;
kono
parents:
diff changeset
192 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
193 ele_count = size / sizeof(double);
kono
parents:
diff changeset
194 if (size != ele_count * sizeof(double))
kono
parents:
diff changeset
195 return 0;
kono
parents:
diff changeset
196 break;
kono
parents:
diff changeset
197 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
198 ele_count = size / sizeof(long double);
kono
parents:
diff changeset
199 if (size != ele_count * sizeof(long double))
kono
parents:
diff changeset
200 return 0;
kono
parents:
diff changeset
201 break;
kono
parents:
diff changeset
202 default:
kono
parents:
diff changeset
203 return 0;
kono
parents:
diff changeset
204 }
kono
parents:
diff changeset
205 if (ele_count > 4)
kono
parents:
diff changeset
206 return 0;
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 /* Finally, make sure that all scalar elements are the same type. */
kono
parents:
diff changeset
209 for (i = 0; elements[i]; ++i)
kono
parents:
diff changeset
210 {
kono
parents:
diff changeset
211 int t = elements[i]->type;
kono
parents:
diff changeset
212 if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
kono
parents:
diff changeset
213 {
kono
parents:
diff changeset
214 if (!is_hfa1 (elements[i], candidate))
kono
parents:
diff changeset
215 return 0;
kono
parents:
diff changeset
216 }
kono
parents:
diff changeset
217 else if (t != candidate)
kono
parents:
diff changeset
218 return 0;
kono
parents:
diff changeset
219 }
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 /* All tests succeeded. Encode the result. */
kono
parents:
diff changeset
222 done:
kono
parents:
diff changeset
223 return candidate * 4 + (4 - ele_count);
kono
parents:
diff changeset
224 }
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* Representation of the procedure call argument marshalling
kono
parents:
diff changeset
227 state.
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 The terse state variable names match the names used in the AARCH64
kono
parents:
diff changeset
230 PCS. */
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 struct arg_state
kono
parents:
diff changeset
233 {
kono
parents:
diff changeset
234 unsigned ngrn; /* Next general-purpose register number. */
kono
parents:
diff changeset
235 unsigned nsrn; /* Next vector register number. */
kono
parents:
diff changeset
236 size_t nsaa; /* Next stack offset. */
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 #if defined (__APPLE__)
kono
parents:
diff changeset
239 unsigned allocating_variadic;
kono
parents:
diff changeset
240 #endif
kono
parents:
diff changeset
241 };
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* Initialize a procedure call argument marshalling state. */
kono
parents:
diff changeset
244 static void
kono
parents:
diff changeset
245 arg_init (struct arg_state *state)
kono
parents:
diff changeset
246 {
kono
parents:
diff changeset
247 state->ngrn = 0;
kono
parents:
diff changeset
248 state->nsrn = 0;
kono
parents:
diff changeset
249 state->nsaa = 0;
kono
parents:
diff changeset
250 #if defined (__APPLE__)
kono
parents:
diff changeset
251 state->allocating_variadic = 0;
kono
parents:
diff changeset
252 #endif
kono
parents:
diff changeset
253 }
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 /* Allocate an aligned slot on the stack and return a pointer to it. */
kono
parents:
diff changeset
256 static void *
kono
parents:
diff changeset
257 allocate_to_stack (struct arg_state *state, void *stack,
kono
parents:
diff changeset
258 size_t alignment, size_t size)
kono
parents:
diff changeset
259 {
kono
parents:
diff changeset
260 size_t nsaa = state->nsaa;
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 /* Round up the NSAA to the larger of 8 or the natural
kono
parents:
diff changeset
263 alignment of the argument's type. */
kono
parents:
diff changeset
264 #if defined (__APPLE__)
kono
parents:
diff changeset
265 if (state->allocating_variadic && alignment < 8)
kono
parents:
diff changeset
266 alignment = 8;
kono
parents:
diff changeset
267 #else
kono
parents:
diff changeset
268 if (alignment < 8)
kono
parents:
diff changeset
269 alignment = 8;
kono
parents:
diff changeset
270 #endif
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 nsaa = ALIGN (nsaa, alignment);
kono
parents:
diff changeset
273 state->nsaa = nsaa + size;
kono
parents:
diff changeset
274
kono
parents:
diff changeset
275 return (char *)stack + nsaa;
kono
parents:
diff changeset
276 }
kono
parents:
diff changeset
277
kono
parents:
diff changeset
278 static ffi_arg
kono
parents:
diff changeset
279 extend_integer_type (void *source, int type)
kono
parents:
diff changeset
280 {
kono
parents:
diff changeset
281 switch (type)
kono
parents:
diff changeset
282 {
kono
parents:
diff changeset
283 case FFI_TYPE_UINT8:
kono
parents:
diff changeset
284 return *(UINT8 *) source;
kono
parents:
diff changeset
285 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
286 return *(SINT8 *) source;
kono
parents:
diff changeset
287 case FFI_TYPE_UINT16:
kono
parents:
diff changeset
288 return *(UINT16 *) source;
kono
parents:
diff changeset
289 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
290 return *(SINT16 *) source;
kono
parents:
diff changeset
291 case FFI_TYPE_UINT32:
kono
parents:
diff changeset
292 return *(UINT32 *) source;
kono
parents:
diff changeset
293 case FFI_TYPE_INT:
kono
parents:
diff changeset
294 case FFI_TYPE_SINT32:
kono
parents:
diff changeset
295 return *(SINT32 *) source;
kono
parents:
diff changeset
296 case FFI_TYPE_UINT64:
kono
parents:
diff changeset
297 case FFI_TYPE_SINT64:
kono
parents:
diff changeset
298 return *(UINT64 *) source;
kono
parents:
diff changeset
299 break;
kono
parents:
diff changeset
300 case FFI_TYPE_POINTER:
kono
parents:
diff changeset
301 return *(uintptr_t *) source;
kono
parents:
diff changeset
302 default:
kono
parents:
diff changeset
303 abort();
kono
parents:
diff changeset
304 }
kono
parents:
diff changeset
305 }
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 static void
kono
parents:
diff changeset
308 extend_hfa_type (void *dest, void *src, int h)
kono
parents:
diff changeset
309 {
kono
parents:
diff changeset
310 int f = h - AARCH64_RET_S4;
kono
parents:
diff changeset
311 void *x0;
kono
parents:
diff changeset
312
kono
parents:
diff changeset
313 asm volatile (
kono
parents:
diff changeset
314 "adr %0, 0f\n"
kono
parents:
diff changeset
315 " add %0, %0, %1\n"
kono
parents:
diff changeset
316 " br %0\n"
kono
parents:
diff changeset
317 "0: ldp s16, s17, [%3]\n" /* S4 */
kono
parents:
diff changeset
318 " ldp s18, s19, [%3, #8]\n"
kono
parents:
diff changeset
319 " b 4f\n"
kono
parents:
diff changeset
320 " ldp s16, s17, [%3]\n" /* S3 */
kono
parents:
diff changeset
321 " ldr s18, [%3, #8]\n"
kono
parents:
diff changeset
322 " b 3f\n"
kono
parents:
diff changeset
323 " ldp s16, s17, [%3]\n" /* S2 */
kono
parents:
diff changeset
324 " b 2f\n"
kono
parents:
diff changeset
325 " nop\n"
kono
parents:
diff changeset
326 " ldr s16, [%3]\n" /* S1 */
kono
parents:
diff changeset
327 " b 1f\n"
kono
parents:
diff changeset
328 " nop\n"
kono
parents:
diff changeset
329 " ldp d16, d17, [%3]\n" /* D4 */
kono
parents:
diff changeset
330 " ldp d18, d19, [%3, #16]\n"
kono
parents:
diff changeset
331 " b 4f\n"
kono
parents:
diff changeset
332 " ldp d16, d17, [%3]\n" /* D3 */
kono
parents:
diff changeset
333 " ldr d18, [%3, #16]\n"
kono
parents:
diff changeset
334 " b 3f\n"
kono
parents:
diff changeset
335 " ldp d16, d17, [%3]\n" /* D2 */
kono
parents:
diff changeset
336 " b 2f\n"
kono
parents:
diff changeset
337 " nop\n"
kono
parents:
diff changeset
338 " ldr d16, [%3]\n" /* D1 */
kono
parents:
diff changeset
339 " b 1f\n"
kono
parents:
diff changeset
340 " nop\n"
kono
parents:
diff changeset
341 " ldp q16, q17, [%3]\n" /* Q4 */
kono
parents:
diff changeset
342 " ldp q18, q19, [%3, #16]\n"
kono
parents:
diff changeset
343 " b 4f\n"
kono
parents:
diff changeset
344 " ldp q16, q17, [%3]\n" /* Q3 */
kono
parents:
diff changeset
345 " ldr q18, [%3, #16]\n"
kono
parents:
diff changeset
346 " b 3f\n"
kono
parents:
diff changeset
347 " ldp q16, q17, [%3]\n" /* Q2 */
kono
parents:
diff changeset
348 " b 2f\n"
kono
parents:
diff changeset
349 " nop\n"
kono
parents:
diff changeset
350 " ldr q16, [%3]\n" /* Q1 */
kono
parents:
diff changeset
351 " b 1f\n"
kono
parents:
diff changeset
352 "4: str q19, [%2, #48]\n"
kono
parents:
diff changeset
353 "3: str q18, [%2, #32]\n"
kono
parents:
diff changeset
354 "2: str q17, [%2, #16]\n"
kono
parents:
diff changeset
355 "1: str q16, [%2]"
kono
parents:
diff changeset
356 : "=&r"(x0)
kono
parents:
diff changeset
357 : "r"(f * 12), "r"(dest), "r"(src)
kono
parents:
diff changeset
358 : "memory", "v16", "v17", "v18", "v19");
kono
parents:
diff changeset
359 }
kono
parents:
diff changeset
360
kono
parents:
diff changeset
361 static void *
kono
parents:
diff changeset
362 compress_hfa_type (void *dest, void *reg, int h)
kono
parents:
diff changeset
363 {
kono
parents:
diff changeset
364 switch (h)
kono
parents:
diff changeset
365 {
kono
parents:
diff changeset
366 case AARCH64_RET_S1:
kono
parents:
diff changeset
367 if (dest == reg)
kono
parents:
diff changeset
368 {
kono
parents:
diff changeset
369 #ifdef __AARCH64EB__
kono
parents:
diff changeset
370 dest += 12;
kono
parents:
diff changeset
371 #endif
kono
parents:
diff changeset
372 }
kono
parents:
diff changeset
373 else
kono
parents:
diff changeset
374 *(float *)dest = *(float *)reg;
kono
parents:
diff changeset
375 break;
kono
parents:
diff changeset
376 case AARCH64_RET_S2:
kono
parents:
diff changeset
377 asm ("ldp q16, q17, [%1]\n\t"
kono
parents:
diff changeset
378 "st2 { v16.s, v17.s }[0], [%0]"
kono
parents:
diff changeset
379 : : "r"(dest), "r"(reg) : "memory", "v16", "v17");
kono
parents:
diff changeset
380 break;
kono
parents:
diff changeset
381 case AARCH64_RET_S3:
kono
parents:
diff changeset
382 asm ("ldp q16, q17, [%1]\n\t"
kono
parents:
diff changeset
383 "ldr q18, [%1, #32]\n\t"
kono
parents:
diff changeset
384 "st3 { v16.s, v17.s, v18.s }[0], [%0]"
kono
parents:
diff changeset
385 : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
kono
parents:
diff changeset
386 break;
kono
parents:
diff changeset
387 case AARCH64_RET_S4:
kono
parents:
diff changeset
388 asm ("ldp q16, q17, [%1]\n\t"
kono
parents:
diff changeset
389 "ldp q18, q19, [%1, #32]\n\t"
kono
parents:
diff changeset
390 "st4 { v16.s, v17.s, v18.s, v19.s }[0], [%0]"
kono
parents:
diff changeset
391 : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
kono
parents:
diff changeset
392 break;
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 case AARCH64_RET_D1:
kono
parents:
diff changeset
395 if (dest == reg)
kono
parents:
diff changeset
396 {
kono
parents:
diff changeset
397 #ifdef __AARCH64EB__
kono
parents:
diff changeset
398 dest += 8;
kono
parents:
diff changeset
399 #endif
kono
parents:
diff changeset
400 }
kono
parents:
diff changeset
401 else
kono
parents:
diff changeset
402 *(double *)dest = *(double *)reg;
kono
parents:
diff changeset
403 break;
kono
parents:
diff changeset
404 case AARCH64_RET_D2:
kono
parents:
diff changeset
405 asm ("ldp q16, q17, [%1]\n\t"
kono
parents:
diff changeset
406 "st2 { v16.d, v17.d }[0], [%0]"
kono
parents:
diff changeset
407 : : "r"(dest), "r"(reg) : "memory", "v16", "v17");
kono
parents:
diff changeset
408 break;
kono
parents:
diff changeset
409 case AARCH64_RET_D3:
kono
parents:
diff changeset
410 asm ("ldp q16, q17, [%1]\n\t"
kono
parents:
diff changeset
411 "ldr q18, [%1, #32]\n\t"
kono
parents:
diff changeset
412 "st3 { v16.d, v17.d, v18.d }[0], [%0]"
kono
parents:
diff changeset
413 : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18");
kono
parents:
diff changeset
414 break;
kono
parents:
diff changeset
415 case AARCH64_RET_D4:
kono
parents:
diff changeset
416 asm ("ldp q16, q17, [%1]\n\t"
kono
parents:
diff changeset
417 "ldp q18, q19, [%1, #32]\n\t"
kono
parents:
diff changeset
418 "st4 { v16.d, v17.d, v18.d, v19.d }[0], [%0]"
kono
parents:
diff changeset
419 : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19");
kono
parents:
diff changeset
420 break;
kono
parents:
diff changeset
421
kono
parents:
diff changeset
422 default:
kono
parents:
diff changeset
423 if (dest != reg)
kono
parents:
diff changeset
424 return memcpy (dest, reg, 16 * (4 - (h & 3)));
kono
parents:
diff changeset
425 break;
kono
parents:
diff changeset
426 }
kono
parents:
diff changeset
427 return dest;
kono
parents:
diff changeset
428 }
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 /* Either allocate an appropriate register for the argument type, or if
kono
parents:
diff changeset
431 none are available, allocate a stack slot and return a pointer
kono
parents:
diff changeset
432 to the allocated space. */
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 static void *
kono
parents:
diff changeset
435 allocate_int_to_reg_or_stack (struct call_context *context,
kono
parents:
diff changeset
436 struct arg_state *state,
kono
parents:
diff changeset
437 void *stack, size_t size)
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 if (state->ngrn < N_X_ARG_REG)
kono
parents:
diff changeset
440 return &context->x[state->ngrn++];
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 state->ngrn = N_X_ARG_REG;
kono
parents:
diff changeset
443 return allocate_to_stack (state, stack, size, size);
kono
parents:
diff changeset
444 }
kono
parents:
diff changeset
445
kono
parents:
diff changeset
446 ffi_status
kono
parents:
diff changeset
447 ffi_prep_cif_machdep (ffi_cif *cif)
kono
parents:
diff changeset
448 {
kono
parents:
diff changeset
449 ffi_type *rtype = cif->rtype;
kono
parents:
diff changeset
450 size_t bytes = cif->bytes;
kono
parents:
diff changeset
451 int flags, i, n;
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 switch (rtype->type)
kono
parents:
diff changeset
454 {
kono
parents:
diff changeset
455 case FFI_TYPE_VOID:
kono
parents:
diff changeset
456 flags = AARCH64_RET_VOID;
kono
parents:
diff changeset
457 break;
kono
parents:
diff changeset
458 case FFI_TYPE_UINT8:
kono
parents:
diff changeset
459 flags = AARCH64_RET_UINT8;
kono
parents:
diff changeset
460 break;
kono
parents:
diff changeset
461 case FFI_TYPE_UINT16:
kono
parents:
diff changeset
462 flags = AARCH64_RET_UINT16;
kono
parents:
diff changeset
463 break;
kono
parents:
diff changeset
464 case FFI_TYPE_UINT32:
kono
parents:
diff changeset
465 flags = AARCH64_RET_UINT32;
kono
parents:
diff changeset
466 break;
kono
parents:
diff changeset
467 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
468 flags = AARCH64_RET_SINT8;
kono
parents:
diff changeset
469 break;
kono
parents:
diff changeset
470 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
471 flags = AARCH64_RET_SINT16;
kono
parents:
diff changeset
472 break;
kono
parents:
diff changeset
473 case FFI_TYPE_INT:
kono
parents:
diff changeset
474 case FFI_TYPE_SINT32:
kono
parents:
diff changeset
475 flags = AARCH64_RET_SINT32;
kono
parents:
diff changeset
476 break;
kono
parents:
diff changeset
477 case FFI_TYPE_SINT64:
kono
parents:
diff changeset
478 case FFI_TYPE_UINT64:
kono
parents:
diff changeset
479 flags = AARCH64_RET_INT64;
kono
parents:
diff changeset
480 break;
kono
parents:
diff changeset
481 case FFI_TYPE_POINTER:
kono
parents:
diff changeset
482 flags = (sizeof(void *) == 4 ? AARCH64_RET_UINT32 : AARCH64_RET_INT64);
kono
parents:
diff changeset
483 break;
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
486 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
487 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
488 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
489 case FFI_TYPE_COMPLEX:
kono
parents:
diff changeset
490 flags = is_vfp_type (rtype);
kono
parents:
diff changeset
491 if (flags == 0)
kono
parents:
diff changeset
492 {
kono
parents:
diff changeset
493 size_t s = rtype->size;
kono
parents:
diff changeset
494 if (s > 16)
kono
parents:
diff changeset
495 {
kono
parents:
diff changeset
496 flags = AARCH64_RET_VOID | AARCH64_RET_IN_MEM;
kono
parents:
diff changeset
497 bytes += 8;
kono
parents:
diff changeset
498 }
kono
parents:
diff changeset
499 else if (s == 16)
kono
parents:
diff changeset
500 flags = AARCH64_RET_INT128;
kono
parents:
diff changeset
501 else if (s == 8)
kono
parents:
diff changeset
502 flags = AARCH64_RET_INT64;
kono
parents:
diff changeset
503 else
kono
parents:
diff changeset
504 flags = AARCH64_RET_INT128 | AARCH64_RET_NEED_COPY;
kono
parents:
diff changeset
505 }
kono
parents:
diff changeset
506 break;
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 default:
kono
parents:
diff changeset
509 abort();
kono
parents:
diff changeset
510 }
kono
parents:
diff changeset
511
kono
parents:
diff changeset
512 for (i = 0, n = cif->nargs; i < n; i++)
kono
parents:
diff changeset
513 if (is_vfp_type (cif->arg_types[i]))
kono
parents:
diff changeset
514 {
kono
parents:
diff changeset
515 flags |= AARCH64_FLAG_ARG_V;
kono
parents:
diff changeset
516 break;
kono
parents:
diff changeset
517 }
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 /* Round the stack up to a multiple of the stack alignment requirement. */
kono
parents:
diff changeset
520 cif->bytes = ALIGN(bytes, 16);
kono
parents:
diff changeset
521 cif->flags = flags;
kono
parents:
diff changeset
522 #if defined (__APPLE__)
kono
parents:
diff changeset
523 cif->aarch64_nfixedargs = 0;
kono
parents:
diff changeset
524 #endif
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 return FFI_OK;
kono
parents:
diff changeset
527 }
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 #if defined (__APPLE__)
kono
parents:
diff changeset
530 /* Perform Apple-specific cif processing for variadic calls */
kono
parents:
diff changeset
531 ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
kono
parents:
diff changeset
532 unsigned int nfixedargs,
kono
parents:
diff changeset
533 unsigned int ntotalargs)
kono
parents:
diff changeset
534 {
kono
parents:
diff changeset
535 ffi_status status = ffi_prep_cif_machdep (cif);
kono
parents:
diff changeset
536 cif->aarch64_nfixedargs = nfixedargs;
kono
parents:
diff changeset
537 return status;
kono
parents:
diff changeset
538 }
kono
parents:
diff changeset
539 #endif /* __APPLE__ */
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 extern void ffi_call_SYSV (struct call_context *context, void *frame,
kono
parents:
diff changeset
542 void (*fn)(void), void *rvalue, int flags,
kono
parents:
diff changeset
543 void *closure) FFI_HIDDEN;
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 /* Call a function with the provided arguments and capture the return
kono
parents:
diff changeset
546 value. */
kono
parents:
diff changeset
547 static void
kono
parents:
diff changeset
548 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
kono
parents:
diff changeset
549 void **avalue, void *closure)
kono
parents:
diff changeset
550 {
kono
parents:
diff changeset
551 struct call_context *context;
kono
parents:
diff changeset
552 void *stack, *frame, *rvalue;
kono
parents:
diff changeset
553 struct arg_state state;
kono
parents:
diff changeset
554 size_t stack_bytes, rtype_size, rsize;
kono
parents:
diff changeset
555 int i, nargs, flags;
kono
parents:
diff changeset
556 ffi_type *rtype;
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 flags = cif->flags;
kono
parents:
diff changeset
559 rtype = cif->rtype;
kono
parents:
diff changeset
560 rtype_size = rtype->size;
kono
parents:
diff changeset
561 stack_bytes = cif->bytes;
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 /* If the target function returns a structure via hidden pointer,
kono
parents:
diff changeset
564 then we cannot allow a null rvalue. Otherwise, mash a null
kono
parents:
diff changeset
565 rvalue to void return type. */
kono
parents:
diff changeset
566 rsize = 0;
kono
parents:
diff changeset
567 if (flags & AARCH64_RET_IN_MEM)
kono
parents:
diff changeset
568 {
kono
parents:
diff changeset
569 if (orig_rvalue == NULL)
kono
parents:
diff changeset
570 rsize = rtype_size;
kono
parents:
diff changeset
571 }
kono
parents:
diff changeset
572 else if (orig_rvalue == NULL)
kono
parents:
diff changeset
573 flags &= AARCH64_FLAG_ARG_V;
kono
parents:
diff changeset
574 else if (flags & AARCH64_RET_NEED_COPY)
kono
parents:
diff changeset
575 rsize = 16;
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 /* Allocate consectutive stack for everything we'll need. */
kono
parents:
diff changeset
578 context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize);
kono
parents:
diff changeset
579 stack = context + 1;
kono
parents:
diff changeset
580 frame = stack + stack_bytes;
kono
parents:
diff changeset
581 rvalue = (rsize ? frame + 32 : orig_rvalue);
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 arg_init (&state);
kono
parents:
diff changeset
584 for (i = 0, nargs = cif->nargs; i < nargs; i++)
kono
parents:
diff changeset
585 {
kono
parents:
diff changeset
586 ffi_type *ty = cif->arg_types[i];
kono
parents:
diff changeset
587 size_t s = ty->size;
kono
parents:
diff changeset
588 void *a = avalue[i];
kono
parents:
diff changeset
589 int h, t;
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 t = ty->type;
kono
parents:
diff changeset
592 switch (t)
kono
parents:
diff changeset
593 {
kono
parents:
diff changeset
594 case FFI_TYPE_VOID:
kono
parents:
diff changeset
595 FFI_ASSERT (0);
kono
parents:
diff changeset
596 break;
kono
parents:
diff changeset
597
kono
parents:
diff changeset
598 /* If the argument is a basic type the argument is allocated to an
kono
parents:
diff changeset
599 appropriate register, or if none are available, to the stack. */
kono
parents:
diff changeset
600 case FFI_TYPE_INT:
kono
parents:
diff changeset
601 case FFI_TYPE_UINT8:
kono
parents:
diff changeset
602 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
603 case FFI_TYPE_UINT16:
kono
parents:
diff changeset
604 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
605 case FFI_TYPE_UINT32:
kono
parents:
diff changeset
606 case FFI_TYPE_SINT32:
kono
parents:
diff changeset
607 case FFI_TYPE_UINT64:
kono
parents:
diff changeset
608 case FFI_TYPE_SINT64:
kono
parents:
diff changeset
609 case FFI_TYPE_POINTER:
kono
parents:
diff changeset
610 do_pointer:
kono
parents:
diff changeset
611 {
kono
parents:
diff changeset
612 ffi_arg ext = extend_integer_type (a, t);
kono
parents:
diff changeset
613 if (state.ngrn < N_X_ARG_REG)
kono
parents:
diff changeset
614 context->x[state.ngrn++] = ext;
kono
parents:
diff changeset
615 else
kono
parents:
diff changeset
616 {
kono
parents:
diff changeset
617 void *d = allocate_to_stack (&state, stack, ty->alignment, s);
kono
parents:
diff changeset
618 state.ngrn = N_X_ARG_REG;
kono
parents:
diff changeset
619 /* Note that the default abi extends each argument
kono
parents:
diff changeset
620 to a full 64-bit slot, while the iOS abi allocates
kono
parents:
diff changeset
621 only enough space. */
kono
parents:
diff changeset
622 #ifdef __APPLE__
kono
parents:
diff changeset
623 memcpy(d, a, s);
kono
parents:
diff changeset
624 #else
kono
parents:
diff changeset
625 *(ffi_arg *)d = ext;
kono
parents:
diff changeset
626 #endif
kono
parents:
diff changeset
627 }
kono
parents:
diff changeset
628 }
kono
parents:
diff changeset
629 break;
kono
parents:
diff changeset
630
kono
parents:
diff changeset
631 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
632 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
633 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
634 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
635 case FFI_TYPE_COMPLEX:
kono
parents:
diff changeset
636 {
kono
parents:
diff changeset
637 void *dest;
kono
parents:
diff changeset
638
kono
parents:
diff changeset
639 h = is_vfp_type (ty);
kono
parents:
diff changeset
640 if (h)
kono
parents:
diff changeset
641 {
kono
parents:
diff changeset
642 int elems = 4 - (h & 3);
kono
parents:
diff changeset
643 if (state.nsrn + elems <= N_V_ARG_REG)
kono
parents:
diff changeset
644 {
kono
parents:
diff changeset
645 dest = &context->v[state.nsrn];
kono
parents:
diff changeset
646 state.nsrn += elems;
kono
parents:
diff changeset
647 extend_hfa_type (dest, a, h);
kono
parents:
diff changeset
648 break;
kono
parents:
diff changeset
649 }
kono
parents:
diff changeset
650 state.nsrn = N_V_ARG_REG;
kono
parents:
diff changeset
651 dest = allocate_to_stack (&state, stack, ty->alignment, s);
kono
parents:
diff changeset
652 }
kono
parents:
diff changeset
653 else if (s > 16)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 /* If the argument is a composite type that is larger than 16
kono
parents:
diff changeset
656 bytes, then the argument has been copied to memory, and
kono
parents:
diff changeset
657 the argument is replaced by a pointer to the copy. */
kono
parents:
diff changeset
658 a = &avalue[i];
kono
parents:
diff changeset
659 t = FFI_TYPE_POINTER;
kono
parents:
diff changeset
660 goto do_pointer;
kono
parents:
diff changeset
661 }
kono
parents:
diff changeset
662 else
kono
parents:
diff changeset
663 {
kono
parents:
diff changeset
664 size_t n = (s + 7) / 8;
kono
parents:
diff changeset
665 if (state.ngrn + n <= N_X_ARG_REG)
kono
parents:
diff changeset
666 {
kono
parents:
diff changeset
667 /* If the argument is a composite type and the size in
kono
parents:
diff changeset
668 double-words is not more than the number of available
kono
parents:
diff changeset
669 X registers, then the argument is copied into
kono
parents:
diff changeset
670 consecutive X registers. */
kono
parents:
diff changeset
671 dest = &context->x[state.ngrn];
kono
parents:
diff changeset
672 state.ngrn += n;
kono
parents:
diff changeset
673 }
kono
parents:
diff changeset
674 else
kono
parents:
diff changeset
675 {
kono
parents:
diff changeset
676 /* Otherwise, there are insufficient X registers. Further
kono
parents:
diff changeset
677 X register allocations are prevented, the NSAA is
kono
parents:
diff changeset
678 adjusted and the argument is copied to memory at the
kono
parents:
diff changeset
679 adjusted NSAA. */
kono
parents:
diff changeset
680 state.ngrn = N_X_ARG_REG;
kono
parents:
diff changeset
681 dest = allocate_to_stack (&state, stack, ty->alignment, s);
kono
parents:
diff changeset
682 }
kono
parents:
diff changeset
683 }
kono
parents:
diff changeset
684 memcpy (dest, a, s);
kono
parents:
diff changeset
685 }
kono
parents:
diff changeset
686 break;
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 default:
kono
parents:
diff changeset
689 abort();
kono
parents:
diff changeset
690 }
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 #if defined (__APPLE__)
kono
parents:
diff changeset
693 if (i + 1 == cif->aarch64_nfixedargs)
kono
parents:
diff changeset
694 {
kono
parents:
diff changeset
695 state.ngrn = N_X_ARG_REG;
kono
parents:
diff changeset
696 state.nsrn = N_V_ARG_REG;
kono
parents:
diff changeset
697 state.allocating_variadic = 1;
kono
parents:
diff changeset
698 }
kono
parents:
diff changeset
699 #endif
kono
parents:
diff changeset
700 }
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 ffi_call_SYSV (context, frame, fn, rvalue, flags, closure);
kono
parents:
diff changeset
703
kono
parents:
diff changeset
704 if (flags & AARCH64_RET_NEED_COPY)
kono
parents:
diff changeset
705 memcpy (orig_rvalue, rvalue, rtype_size);
kono
parents:
diff changeset
706 }
kono
parents:
diff changeset
707
kono
parents:
diff changeset
708 void
kono
parents:
diff changeset
709 ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
kono
parents:
diff changeset
710 {
kono
parents:
diff changeset
711 ffi_call_int (cif, fn, rvalue, avalue, NULL);
kono
parents:
diff changeset
712 }
kono
parents:
diff changeset
713
kono
parents:
diff changeset
714 #ifdef FFI_GO_CLOSURES
kono
parents:
diff changeset
715 void
kono
parents:
diff changeset
716 ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
kono
parents:
diff changeset
717 void **avalue, void *closure)
kono
parents:
diff changeset
718 {
kono
parents:
diff changeset
719 ffi_call_int (cif, fn, rvalue, avalue, closure);
kono
parents:
diff changeset
720 }
kono
parents:
diff changeset
721 #endif /* FFI_GO_CLOSURES */
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 /* Build a trampoline. */
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 extern void ffi_closure_SYSV (void) FFI_HIDDEN;
kono
parents:
diff changeset
726 extern void ffi_closure_SYSV_V (void) FFI_HIDDEN;
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 #if FFI_EXEC_TRAMPOLINE_TABLE
kono
parents:
diff changeset
729
kono
parents:
diff changeset
730 #include <mach/mach.h>
kono
parents:
diff changeset
731 #include <pthread.h>
kono
parents:
diff changeset
732 #include <stdio.h>
kono
parents:
diff changeset
733 #include <stdlib.h>
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 extern void *ffi_closure_trampoline_table_page;
kono
parents:
diff changeset
736
kono
parents:
diff changeset
737 typedef struct ffi_trampoline_table ffi_trampoline_table;
kono
parents:
diff changeset
738 typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry;
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 struct ffi_trampoline_table
kono
parents:
diff changeset
741 {
kono
parents:
diff changeset
742 /* contiguous writable and executable pages */
kono
parents:
diff changeset
743 vm_address_t config_page;
kono
parents:
diff changeset
744 vm_address_t trampoline_page;
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 /* free list tracking */
kono
parents:
diff changeset
747 uint16_t free_count;
kono
parents:
diff changeset
748 ffi_trampoline_table_entry *free_list;
kono
parents:
diff changeset
749 ffi_trampoline_table_entry *free_list_pool;
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 ffi_trampoline_table *prev;
kono
parents:
diff changeset
752 ffi_trampoline_table *next;
kono
parents:
diff changeset
753 };
kono
parents:
diff changeset
754
kono
parents:
diff changeset
755 struct ffi_trampoline_table_entry
kono
parents:
diff changeset
756 {
kono
parents:
diff changeset
757 void *(*trampoline) ();
kono
parents:
diff changeset
758 ffi_trampoline_table_entry *next;
kono
parents:
diff changeset
759 };
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 /* The trampoline configuration is placed a page prior to the trampoline's entry point */
kono
parents:
diff changeset
762 #define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - PAGE_SIZE));
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 /* Total number of trampolines that fit in one trampoline table */
kono
parents:
diff changeset
765 #define FFI_TRAMPOLINE_COUNT (PAGE_SIZE / FFI_TRAMPOLINE_SIZE)
kono
parents:
diff changeset
766
kono
parents:
diff changeset
767 static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER;
kono
parents:
diff changeset
768 static ffi_trampoline_table *ffi_trampoline_tables = NULL;
kono
parents:
diff changeset
769
kono
parents:
diff changeset
770 static ffi_trampoline_table *
kono
parents:
diff changeset
771 ffi_trampoline_table_alloc ()
kono
parents:
diff changeset
772 {
kono
parents:
diff changeset
773 ffi_trampoline_table *table = NULL;
kono
parents:
diff changeset
774
kono
parents:
diff changeset
775 /* Loop until we can allocate two contiguous pages */
kono
parents:
diff changeset
776 while (table == NULL)
kono
parents:
diff changeset
777 {
kono
parents:
diff changeset
778 vm_address_t config_page = 0x0;
kono
parents:
diff changeset
779 kern_return_t kt;
kono
parents:
diff changeset
780
kono
parents:
diff changeset
781 /* Try to allocate two pages */
kono
parents:
diff changeset
782 kt =
kono
parents:
diff changeset
783 vm_allocate (mach_task_self (), &config_page, PAGE_SIZE * 2,
kono
parents:
diff changeset
784 VM_FLAGS_ANYWHERE);
kono
parents:
diff changeset
785 if (kt != KERN_SUCCESS)
kono
parents:
diff changeset
786 {
kono
parents:
diff changeset
787 fprintf (stderr, "vm_allocate() failure: %d at %s:%d\n", kt,
kono
parents:
diff changeset
788 __FILE__, __LINE__);
kono
parents:
diff changeset
789 break;
kono
parents:
diff changeset
790 }
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 /* Now drop the second half of the allocation to make room for the trampoline table */
kono
parents:
diff changeset
793 vm_address_t trampoline_page = config_page + PAGE_SIZE;
kono
parents:
diff changeset
794 kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE);
kono
parents:
diff changeset
795 if (kt != KERN_SUCCESS)
kono
parents:
diff changeset
796 {
kono
parents:
diff changeset
797 fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
kono
parents:
diff changeset
798 __FILE__, __LINE__);
kono
parents:
diff changeset
799 break;
kono
parents:
diff changeset
800 }
kono
parents:
diff changeset
801
kono
parents:
diff changeset
802 /* Remap the trampoline table to directly follow the config page */
kono
parents:
diff changeset
803 vm_prot_t cur_prot;
kono
parents:
diff changeset
804 vm_prot_t max_prot;
kono
parents:
diff changeset
805
kono
parents:
diff changeset
806 kt =
kono
parents:
diff changeset
807 vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE,
kono
parents:
diff changeset
808 mach_task_self (),
kono
parents:
diff changeset
809 (vm_address_t) & ffi_closure_trampoline_table_page, FALSE,
kono
parents:
diff changeset
810 &cur_prot, &max_prot, VM_INHERIT_SHARE);
kono
parents:
diff changeset
811
kono
parents:
diff changeset
812 /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */
kono
parents:
diff changeset
813 if (kt != KERN_SUCCESS)
kono
parents:
diff changeset
814 {
kono
parents:
diff changeset
815 /* Log unexpected failures */
kono
parents:
diff changeset
816 if (kt != KERN_NO_SPACE)
kono
parents:
diff changeset
817 {
kono
parents:
diff changeset
818 fprintf (stderr, "vm_remap() failure: %d at %s:%d\n", kt,
kono
parents:
diff changeset
819 __FILE__, __LINE__);
kono
parents:
diff changeset
820 }
kono
parents:
diff changeset
821
kono
parents:
diff changeset
822 vm_deallocate (mach_task_self (), config_page, PAGE_SIZE);
kono
parents:
diff changeset
823 continue;
kono
parents:
diff changeset
824 }
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 /* We have valid trampoline and config pages */
kono
parents:
diff changeset
827 table = calloc (1, sizeof (ffi_trampoline_table));
kono
parents:
diff changeset
828 table->free_count = FFI_TRAMPOLINE_COUNT;
kono
parents:
diff changeset
829 table->config_page = config_page;
kono
parents:
diff changeset
830 table->trampoline_page = trampoline_page;
kono
parents:
diff changeset
831
kono
parents:
diff changeset
832 /* Create and initialize the free list */
kono
parents:
diff changeset
833 table->free_list_pool =
kono
parents:
diff changeset
834 calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry));
kono
parents:
diff changeset
835
kono
parents:
diff changeset
836 uint16_t i;
kono
parents:
diff changeset
837 for (i = 0; i < table->free_count; i++)
kono
parents:
diff changeset
838 {
kono
parents:
diff changeset
839 ffi_trampoline_table_entry *entry = &table->free_list_pool[i];
kono
parents:
diff changeset
840 entry->trampoline =
kono
parents:
diff changeset
841 (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE));
kono
parents:
diff changeset
842
kono
parents:
diff changeset
843 if (i < table->free_count - 1)
kono
parents:
diff changeset
844 entry->next = &table->free_list_pool[i + 1];
kono
parents:
diff changeset
845 }
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 table->free_list = table->free_list_pool;
kono
parents:
diff changeset
848 }
kono
parents:
diff changeset
849
kono
parents:
diff changeset
850 return table;
kono
parents:
diff changeset
851 }
kono
parents:
diff changeset
852
kono
parents:
diff changeset
853 void *
kono
parents:
diff changeset
854 ffi_closure_alloc (size_t size, void **code)
kono
parents:
diff changeset
855 {
kono
parents:
diff changeset
856 /* Create the closure */
kono
parents:
diff changeset
857 ffi_closure *closure = malloc (size);
kono
parents:
diff changeset
858 if (closure == NULL)
kono
parents:
diff changeset
859 return NULL;
kono
parents:
diff changeset
860
kono
parents:
diff changeset
861 pthread_mutex_lock (&ffi_trampoline_lock);
kono
parents:
diff changeset
862
kono
parents:
diff changeset
863 /* Check for an active trampoline table with available entries. */
kono
parents:
diff changeset
864 ffi_trampoline_table *table = ffi_trampoline_tables;
kono
parents:
diff changeset
865 if (table == NULL || table->free_list == NULL)
kono
parents:
diff changeset
866 {
kono
parents:
diff changeset
867 table = ffi_trampoline_table_alloc ();
kono
parents:
diff changeset
868 if (table == NULL)
kono
parents:
diff changeset
869 {
kono
parents:
diff changeset
870 free (closure);
kono
parents:
diff changeset
871 return NULL;
kono
parents:
diff changeset
872 }
kono
parents:
diff changeset
873
kono
parents:
diff changeset
874 /* Insert the new table at the top of the list */
kono
parents:
diff changeset
875 table->next = ffi_trampoline_tables;
kono
parents:
diff changeset
876 if (table->next != NULL)
kono
parents:
diff changeset
877 table->next->prev = table;
kono
parents:
diff changeset
878
kono
parents:
diff changeset
879 ffi_trampoline_tables = table;
kono
parents:
diff changeset
880 }
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 /* Claim the free entry */
kono
parents:
diff changeset
883 ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list;
kono
parents:
diff changeset
884 ffi_trampoline_tables->free_list = entry->next;
kono
parents:
diff changeset
885 ffi_trampoline_tables->free_count--;
kono
parents:
diff changeset
886 entry->next = NULL;
kono
parents:
diff changeset
887
kono
parents:
diff changeset
888 pthread_mutex_unlock (&ffi_trampoline_lock);
kono
parents:
diff changeset
889
kono
parents:
diff changeset
890 /* Initialize the return values */
kono
parents:
diff changeset
891 *code = entry->trampoline;
kono
parents:
diff changeset
892 closure->trampoline_table = table;
kono
parents:
diff changeset
893 closure->trampoline_table_entry = entry;
kono
parents:
diff changeset
894
kono
parents:
diff changeset
895 return closure;
kono
parents:
diff changeset
896 }
kono
parents:
diff changeset
897
kono
parents:
diff changeset
898 void
kono
parents:
diff changeset
899 ffi_closure_free (void *ptr)
kono
parents:
diff changeset
900 {
kono
parents:
diff changeset
901 ffi_closure *closure = ptr;
kono
parents:
diff changeset
902
kono
parents:
diff changeset
903 pthread_mutex_lock (&ffi_trampoline_lock);
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 /* Fetch the table and entry references */
kono
parents:
diff changeset
906 ffi_trampoline_table *table = closure->trampoline_table;
kono
parents:
diff changeset
907 ffi_trampoline_table_entry *entry = closure->trampoline_table_entry;
kono
parents:
diff changeset
908
kono
parents:
diff changeset
909 /* Return the entry to the free list */
kono
parents:
diff changeset
910 entry->next = table->free_list;
kono
parents:
diff changeset
911 table->free_list = entry;
kono
parents:
diff changeset
912 table->free_count++;
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 /* If all trampolines within this table are free, and at least one other table exists, deallocate
kono
parents:
diff changeset
915 * the table */
kono
parents:
diff changeset
916 if (table->free_count == FFI_TRAMPOLINE_COUNT
kono
parents:
diff changeset
917 && ffi_trampoline_tables != table)
kono
parents:
diff changeset
918 {
kono
parents:
diff changeset
919 /* Remove from the list */
kono
parents:
diff changeset
920 if (table->prev != NULL)
kono
parents:
diff changeset
921 table->prev->next = table->next;
kono
parents:
diff changeset
922
kono
parents:
diff changeset
923 if (table->next != NULL)
kono
parents:
diff changeset
924 table->next->prev = table->prev;
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 /* Deallocate pages */
kono
parents:
diff changeset
927 kern_return_t kt;
kono
parents:
diff changeset
928 kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE);
kono
parents:
diff changeset
929 if (kt != KERN_SUCCESS)
kono
parents:
diff changeset
930 fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
kono
parents:
diff changeset
931 __FILE__, __LINE__);
kono
parents:
diff changeset
932
kono
parents:
diff changeset
933 kt =
kono
parents:
diff changeset
934 vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE);
kono
parents:
diff changeset
935 if (kt != KERN_SUCCESS)
kono
parents:
diff changeset
936 fprintf (stderr, "vm_deallocate() failure: %d at %s:%d\n", kt,
kono
parents:
diff changeset
937 __FILE__, __LINE__);
kono
parents:
diff changeset
938
kono
parents:
diff changeset
939 /* Deallocate free list */
kono
parents:
diff changeset
940 free (table->free_list_pool);
kono
parents:
diff changeset
941 free (table);
kono
parents:
diff changeset
942 }
kono
parents:
diff changeset
943 else if (ffi_trampoline_tables != table)
kono
parents:
diff changeset
944 {
kono
parents:
diff changeset
945 /* Otherwise, bump this table to the top of the list */
kono
parents:
diff changeset
946 table->prev = NULL;
kono
parents:
diff changeset
947 table->next = ffi_trampoline_tables;
kono
parents:
diff changeset
948 if (ffi_trampoline_tables != NULL)
kono
parents:
diff changeset
949 ffi_trampoline_tables->prev = table;
kono
parents:
diff changeset
950
kono
parents:
diff changeset
951 ffi_trampoline_tables = table;
kono
parents:
diff changeset
952 }
kono
parents:
diff changeset
953
kono
parents:
diff changeset
954 pthread_mutex_unlock (&ffi_trampoline_lock);
kono
parents:
diff changeset
955
kono
parents:
diff changeset
956 /* Free the closure */
kono
parents:
diff changeset
957 free (closure);
kono
parents:
diff changeset
958 }
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 #endif
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 ffi_status
kono
parents:
diff changeset
963 ffi_prep_closure_loc (ffi_closure *closure,
kono
parents:
diff changeset
964 ffi_cif* cif,
kono
parents:
diff changeset
965 void (*fun)(ffi_cif*,void*,void**,void*),
kono
parents:
diff changeset
966 void *user_data,
kono
parents:
diff changeset
967 void *codeloc)
kono
parents:
diff changeset
968 {
kono
parents:
diff changeset
969 if (cif->abi != FFI_SYSV)
kono
parents:
diff changeset
970 return FFI_BAD_ABI;
kono
parents:
diff changeset
971
kono
parents:
diff changeset
972 void (*start)(void);
kono
parents:
diff changeset
973
kono
parents:
diff changeset
974 if (cif->flags & AARCH64_FLAG_ARG_V)
kono
parents:
diff changeset
975 start = ffi_closure_SYSV_V;
kono
parents:
diff changeset
976 else
kono
parents:
diff changeset
977 start = ffi_closure_SYSV;
kono
parents:
diff changeset
978
kono
parents:
diff changeset
979 #if FFI_EXEC_TRAMPOLINE_TABLE
kono
parents:
diff changeset
980 void **config = FFI_TRAMPOLINE_CODELOC_CONFIG (codeloc);
kono
parents:
diff changeset
981 config[0] = closure;
kono
parents:
diff changeset
982 config[1] = start;
kono
parents:
diff changeset
983 #else
kono
parents:
diff changeset
984 static const unsigned char trampoline[16] = {
kono
parents:
diff changeset
985 0x90, 0x00, 0x00, 0x58, /* ldr x16, tramp+16 */
kono
parents:
diff changeset
986 0xf1, 0xff, 0xff, 0x10, /* adr x17, tramp+0 */
kono
parents:
diff changeset
987 0x00, 0x02, 0x1f, 0xd6 /* br x16 */
kono
parents:
diff changeset
988 };
kono
parents:
diff changeset
989 char *tramp = closure->tramp;
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 memcpy (tramp, trampoline, sizeof(trampoline));
kono
parents:
diff changeset
992
kono
parents:
diff changeset
993 *(UINT64 *)(tramp + 16) = (uintptr_t)start;
kono
parents:
diff changeset
994
kono
parents:
diff changeset
995 ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
kono
parents:
diff changeset
996 #endif
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 closure->cif = cif;
kono
parents:
diff changeset
999 closure->fun = fun;
kono
parents:
diff changeset
1000 closure->user_data = user_data;
kono
parents:
diff changeset
1001
kono
parents:
diff changeset
1002 return FFI_OK;
kono
parents:
diff changeset
1003 }
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 #ifdef FFI_GO_CLOSURES
kono
parents:
diff changeset
1006 extern void ffi_go_closure_SYSV (void) FFI_HIDDEN;
kono
parents:
diff changeset
1007 extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN;
kono
parents:
diff changeset
1008
kono
parents:
diff changeset
1009 ffi_status
kono
parents:
diff changeset
1010 ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif,
kono
parents:
diff changeset
1011 void (*fun)(ffi_cif*,void*,void**,void*))
kono
parents:
diff changeset
1012 {
kono
parents:
diff changeset
1013 void (*start)(void);
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 if (cif->abi != FFI_SYSV)
kono
parents:
diff changeset
1016 return FFI_BAD_ABI;
kono
parents:
diff changeset
1017
kono
parents:
diff changeset
1018 if (cif->flags & AARCH64_FLAG_ARG_V)
kono
parents:
diff changeset
1019 start = ffi_go_closure_SYSV_V;
kono
parents:
diff changeset
1020 else
kono
parents:
diff changeset
1021 start = ffi_go_closure_SYSV;
kono
parents:
diff changeset
1022
kono
parents:
diff changeset
1023 closure->tramp = start;
kono
parents:
diff changeset
1024 closure->cif = cif;
kono
parents:
diff changeset
1025 closure->fun = fun;
kono
parents:
diff changeset
1026
kono
parents:
diff changeset
1027 return FFI_OK;
kono
parents:
diff changeset
1028 }
kono
parents:
diff changeset
1029 #endif /* FFI_GO_CLOSURES */
kono
parents:
diff changeset
1030
kono
parents:
diff changeset
1031 /* Primary handler to setup and invoke a function within a closure.
kono
parents:
diff changeset
1032
kono
parents:
diff changeset
1033 A closure when invoked enters via the assembler wrapper
kono
parents:
diff changeset
1034 ffi_closure_SYSV(). The wrapper allocates a call context on the
kono
parents:
diff changeset
1035 stack, saves the interesting registers (from the perspective of
kono
parents:
diff changeset
1036 the calling convention) into the context then passes control to
kono
parents:
diff changeset
1037 ffi_closure_SYSV_inner() passing the saved context and a pointer to
kono
parents:
diff changeset
1038 the stack at the point ffi_closure_SYSV() was invoked.
kono
parents:
diff changeset
1039
kono
parents:
diff changeset
1040 On the return path the assembler wrapper will reload call context
kono
parents:
diff changeset
1041 registers.
kono
parents:
diff changeset
1042
kono
parents:
diff changeset
1043 ffi_closure_SYSV_inner() marshalls the call context into ffi value
kono
parents:
diff changeset
1044 descriptors, invokes the wrapped function, then marshalls the return
kono
parents:
diff changeset
1045 value back into the call context. */
kono
parents:
diff changeset
1046
kono
parents:
diff changeset
1047 int FFI_HIDDEN
kono
parents:
diff changeset
1048 ffi_closure_SYSV_inner (ffi_cif *cif,
kono
parents:
diff changeset
1049 void (*fun)(ffi_cif*,void*,void**,void*),
kono
parents:
diff changeset
1050 void *user_data,
kono
parents:
diff changeset
1051 struct call_context *context,
kono
parents:
diff changeset
1052 void *stack, void *rvalue, void *struct_rvalue)
kono
parents:
diff changeset
1053 {
kono
parents:
diff changeset
1054 void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
kono
parents:
diff changeset
1055 int i, h, nargs, flags;
kono
parents:
diff changeset
1056 struct arg_state state;
kono
parents:
diff changeset
1057
kono
parents:
diff changeset
1058 arg_init (&state);
kono
parents:
diff changeset
1059
kono
parents:
diff changeset
1060 for (i = 0, nargs = cif->nargs; i < nargs; i++)
kono
parents:
diff changeset
1061 {
kono
parents:
diff changeset
1062 ffi_type *ty = cif->arg_types[i];
kono
parents:
diff changeset
1063 int t = ty->type;
kono
parents:
diff changeset
1064 size_t n, s = ty->size;
kono
parents:
diff changeset
1065
kono
parents:
diff changeset
1066 switch (t)
kono
parents:
diff changeset
1067 {
kono
parents:
diff changeset
1068 case FFI_TYPE_VOID:
kono
parents:
diff changeset
1069 FFI_ASSERT (0);
kono
parents:
diff changeset
1070 break;
kono
parents:
diff changeset
1071
kono
parents:
diff changeset
1072 case FFI_TYPE_INT:
kono
parents:
diff changeset
1073 case FFI_TYPE_UINT8:
kono
parents:
diff changeset
1074 case FFI_TYPE_SINT8:
kono
parents:
diff changeset
1075 case FFI_TYPE_UINT16:
kono
parents:
diff changeset
1076 case FFI_TYPE_SINT16:
kono
parents:
diff changeset
1077 case FFI_TYPE_UINT32:
kono
parents:
diff changeset
1078 case FFI_TYPE_SINT32:
kono
parents:
diff changeset
1079 case FFI_TYPE_UINT64:
kono
parents:
diff changeset
1080 case FFI_TYPE_SINT64:
kono
parents:
diff changeset
1081 case FFI_TYPE_POINTER:
kono
parents:
diff changeset
1082 avalue[i] = allocate_int_to_reg_or_stack (context, &state, stack, s);
kono
parents:
diff changeset
1083 break;
kono
parents:
diff changeset
1084
kono
parents:
diff changeset
1085 case FFI_TYPE_FLOAT:
kono
parents:
diff changeset
1086 case FFI_TYPE_DOUBLE:
kono
parents:
diff changeset
1087 case FFI_TYPE_LONGDOUBLE:
kono
parents:
diff changeset
1088 case FFI_TYPE_STRUCT:
kono
parents:
diff changeset
1089 case FFI_TYPE_COMPLEX:
kono
parents:
diff changeset
1090 h = is_vfp_type (ty);
kono
parents:
diff changeset
1091 if (h)
kono
parents:
diff changeset
1092 {
kono
parents:
diff changeset
1093 n = 4 - (h & 3);
kono
parents:
diff changeset
1094 if (state.nsrn + n <= N_V_ARG_REG)
kono
parents:
diff changeset
1095 {
kono
parents:
diff changeset
1096 void *reg = &context->v[state.nsrn];
kono
parents:
diff changeset
1097 state.nsrn += n;
kono
parents:
diff changeset
1098
kono
parents:
diff changeset
1099 /* Eeek! We need a pointer to the structure, however the
kono
parents:
diff changeset
1100 homogeneous float elements are being passed in individual
kono
parents:
diff changeset
1101 registers, therefore for float and double the structure
kono
parents:
diff changeset
1102 is not represented as a contiguous sequence of bytes in
kono
parents:
diff changeset
1103 our saved register context. We don't need the original
kono
parents:
diff changeset
1104 contents of the register storage, so we reformat the
kono
parents:
diff changeset
1105 structure into the same memory. */
kono
parents:
diff changeset
1106 avalue[i] = compress_hfa_type (reg, reg, h);
kono
parents:
diff changeset
1107 }
kono
parents:
diff changeset
1108 else
kono
parents:
diff changeset
1109 {
kono
parents:
diff changeset
1110 state.nsrn = N_V_ARG_REG;
kono
parents:
diff changeset
1111 avalue[i] = allocate_to_stack (&state, stack,
kono
parents:
diff changeset
1112 ty->alignment, s);
kono
parents:
diff changeset
1113 }
kono
parents:
diff changeset
1114 }
kono
parents:
diff changeset
1115 else if (s > 16)
kono
parents:
diff changeset
1116 {
kono
parents:
diff changeset
1117 /* Replace Composite type of size greater than 16 with a
kono
parents:
diff changeset
1118 pointer. */
kono
parents:
diff changeset
1119 avalue[i] = *(void **)
kono
parents:
diff changeset
1120 allocate_int_to_reg_or_stack (context, &state, stack,
kono
parents:
diff changeset
1121 sizeof (void *));
kono
parents:
diff changeset
1122 }
kono
parents:
diff changeset
1123 else
kono
parents:
diff changeset
1124 {
kono
parents:
diff changeset
1125 n = (s + 7) / 8;
kono
parents:
diff changeset
1126 if (state.ngrn + n <= N_X_ARG_REG)
kono
parents:
diff changeset
1127 {
kono
parents:
diff changeset
1128 avalue[i] = &context->x[state.ngrn];
kono
parents:
diff changeset
1129 state.ngrn += n;
kono
parents:
diff changeset
1130 }
kono
parents:
diff changeset
1131 else
kono
parents:
diff changeset
1132 {
kono
parents:
diff changeset
1133 state.ngrn = N_X_ARG_REG;
kono
parents:
diff changeset
1134 avalue[i] = allocate_to_stack (&state, stack,
kono
parents:
diff changeset
1135 ty->alignment, s);
kono
parents:
diff changeset
1136 }
kono
parents:
diff changeset
1137 }
kono
parents:
diff changeset
1138 break;
kono
parents:
diff changeset
1139
kono
parents:
diff changeset
1140 default:
kono
parents:
diff changeset
1141 abort();
kono
parents:
diff changeset
1142 }
kono
parents:
diff changeset
1143 }
kono
parents:
diff changeset
1144
kono
parents:
diff changeset
1145 flags = cif->flags;
kono
parents:
diff changeset
1146 if (flags & AARCH64_RET_IN_MEM)
kono
parents:
diff changeset
1147 rvalue = struct_rvalue;
kono
parents:
diff changeset
1148
kono
parents:
diff changeset
1149 fun (cif, rvalue, avalue, user_data);
kono
parents:
diff changeset
1150
kono
parents:
diff changeset
1151 return flags;
kono
parents:
diff changeset
1152 }