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