1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan ffi_darwin.c
3*1fd5a2e1SPrashanth Swaminathan
4*1fd5a2e1SPrashanth Swaminathan Copyright (C) 1998 Geoffrey Keating
5*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2001 John Hornkvist
6*1fd5a2e1SPrashanth Swaminathan Copyright (C) 2002, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
7*1fd5a2e1SPrashanth Swaminathan
8*1fd5a2e1SPrashanth Swaminathan FFI support for Darwin and AIX.
9*1fd5a2e1SPrashanth Swaminathan
10*1fd5a2e1SPrashanth Swaminathan Permission is hereby granted, free of charge, to any person obtaining
11*1fd5a2e1SPrashanth Swaminathan a copy of this software and associated documentation files (the
12*1fd5a2e1SPrashanth Swaminathan ``Software''), to deal in the Software without restriction, including
13*1fd5a2e1SPrashanth Swaminathan without limitation the rights to use, copy, modify, merge, publish,
14*1fd5a2e1SPrashanth Swaminathan distribute, sublicense, and/or sell copies of the Software, and to
15*1fd5a2e1SPrashanth Swaminathan permit persons to whom the Software is furnished to do so, subject to
16*1fd5a2e1SPrashanth Swaminathan the following conditions:
17*1fd5a2e1SPrashanth Swaminathan
18*1fd5a2e1SPrashanth Swaminathan The above copyright notice and this permission notice shall be included
19*1fd5a2e1SPrashanth Swaminathan in all copies or substantial portions of the Software.
20*1fd5a2e1SPrashanth Swaminathan
21*1fd5a2e1SPrashanth Swaminathan THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
22*1fd5a2e1SPrashanth Swaminathan OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23*1fd5a2e1SPrashanth Swaminathan MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24*1fd5a2e1SPrashanth Swaminathan IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
25*1fd5a2e1SPrashanth Swaminathan OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26*1fd5a2e1SPrashanth Swaminathan ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27*1fd5a2e1SPrashanth Swaminathan OTHER DEALINGS IN THE SOFTWARE.
28*1fd5a2e1SPrashanth Swaminathan ----------------------------------------------------------------------- */
29*1fd5a2e1SPrashanth Swaminathan
30*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
31*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
32*1fd5a2e1SPrashanth Swaminathan
33*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
34*1fd5a2e1SPrashanth Swaminathan
35*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_ASM (void);
36*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_ASM (void);
37*1fd5a2e1SPrashanth Swaminathan
38*1fd5a2e1SPrashanth Swaminathan enum {
39*1fd5a2e1SPrashanth Swaminathan /* The assembly depends on these exact flags.
40*1fd5a2e1SPrashanth Swaminathan For Darwin64 (when FLAG_RETURNS_STRUCT is set):
41*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_FP indicates that the structure embeds FP data.
42*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_128BITS signals a special struct size that is not
43*1fd5a2e1SPrashanth Swaminathan expanded for float content. */
44*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_128BITS = 1 << (31-31), /* These go in cr7 */
45*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_NOTHING = 1 << (31-30),
46*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_FP = 1 << (31-29),
47*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_64BITS = 1 << (31-28),
48*1fd5a2e1SPrashanth Swaminathan
49*1fd5a2e1SPrashanth Swaminathan FLAG_RETURNS_STRUCT = 1 << (31-27), /* This goes in cr6 */
50*1fd5a2e1SPrashanth Swaminathan
51*1fd5a2e1SPrashanth Swaminathan FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
52*1fd5a2e1SPrashanth Swaminathan FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
53*1fd5a2e1SPrashanth Swaminathan FLAG_4_GPR_ARGUMENTS = 1 << (31- 5),
54*1fd5a2e1SPrashanth Swaminathan FLAG_RETVAL_REFERENCE = 1 << (31- 4)
55*1fd5a2e1SPrashanth Swaminathan };
56*1fd5a2e1SPrashanth Swaminathan
57*1fd5a2e1SPrashanth Swaminathan /* About the DARWIN ABI. */
58*1fd5a2e1SPrashanth Swaminathan enum {
59*1fd5a2e1SPrashanth Swaminathan NUM_GPR_ARG_REGISTERS = 8,
60*1fd5a2e1SPrashanth Swaminathan NUM_FPR_ARG_REGISTERS = 13,
61*1fd5a2e1SPrashanth Swaminathan LINKAGE_AREA_GPRS = 6
62*1fd5a2e1SPrashanth Swaminathan };
63*1fd5a2e1SPrashanth Swaminathan
64*1fd5a2e1SPrashanth Swaminathan enum { ASM_NEEDS_REGISTERS = 4 }; /* r28-r31 */
65*1fd5a2e1SPrashanth Swaminathan
66*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
67*1fd5a2e1SPrashanth Swaminathan has been allocated for the function's arguments.
68*1fd5a2e1SPrashanth Swaminathan
69*1fd5a2e1SPrashanth Swaminathan m32/m64
70*1fd5a2e1SPrashanth Swaminathan
71*1fd5a2e1SPrashanth Swaminathan The stack layout we want looks like this:
72*1fd5a2e1SPrashanth Swaminathan
73*1fd5a2e1SPrashanth Swaminathan | Return address from ffi_call_DARWIN | higher addresses
74*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|
75*1fd5a2e1SPrashanth Swaminathan | Previous backchain pointer 4/8 | stack pointer here
76*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------|<+ <<< on entry to
77*1fd5a2e1SPrashanth Swaminathan | ASM_NEEDS_REGISTERS=r28-r31 4*(4/8) | | ffi_call_DARWIN
78*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
79*1fd5a2e1SPrashanth Swaminathan | When we have any FP activity... the | |
80*1fd5a2e1SPrashanth Swaminathan | FPRs occupy NUM_FPR_ARG_REGISTERS slots | |
81*1fd5a2e1SPrashanth Swaminathan | here fp13 .. fp1 from high to low addr. | |
82*1fd5a2e1SPrashanth Swaminathan ~ ~ ~
83*1fd5a2e1SPrashanth Swaminathan | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS
84*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
85*1fd5a2e1SPrashanth Swaminathan | TOC=R2 (AIX) Reserved (Darwin) 4/8 | |
86*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack |
87*1fd5a2e1SPrashanth Swaminathan | Reserved 2*4/8 | | grows |
88*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | down V
89*1fd5a2e1SPrashanth Swaminathan | Space for callee's LR 4/8 | |
90*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | lower addresses
91*1fd5a2e1SPrashanth Swaminathan | Saved CR [low word for m64] 4/8 | |
92*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack pointer here
93*1fd5a2e1SPrashanth Swaminathan | Current backchain pointer 4/8 |-/ during
94*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| <<< ffi_call_DARWIN
95*1fd5a2e1SPrashanth Swaminathan
96*1fd5a2e1SPrashanth Swaminathan */
97*1fd5a2e1SPrashanth Swaminathan
98*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
99*1fd5a2e1SPrashanth Swaminathan static void
100*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_by_value
101*1fd5a2e1SPrashanth Swaminathan (ffi_type *, char *, unsigned, unsigned *, double **, unsigned long **);
102*1fd5a2e1SPrashanth Swaminathan #endif
103*1fd5a2e1SPrashanth Swaminathan
104*1fd5a2e1SPrashanth Swaminathan /* This depends on GPR_SIZE = sizeof (unsigned long) */
105*1fd5a2e1SPrashanth Swaminathan
106*1fd5a2e1SPrashanth Swaminathan void
ffi_prep_args(extended_cif * ecif,unsigned long * const stack)107*1fd5a2e1SPrashanth Swaminathan ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
108*1fd5a2e1SPrashanth Swaminathan {
109*1fd5a2e1SPrashanth Swaminathan const unsigned bytes = ecif->cif->bytes;
110*1fd5a2e1SPrashanth Swaminathan const unsigned flags = ecif->cif->flags;
111*1fd5a2e1SPrashanth Swaminathan const unsigned nargs = ecif->cif->nargs;
112*1fd5a2e1SPrashanth Swaminathan #if !defined(POWERPC_DARWIN64)
113*1fd5a2e1SPrashanth Swaminathan const ffi_abi abi = ecif->cif->abi;
114*1fd5a2e1SPrashanth Swaminathan #endif
115*1fd5a2e1SPrashanth Swaminathan
116*1fd5a2e1SPrashanth Swaminathan /* 'stacktop' points at the previous backchain pointer. */
117*1fd5a2e1SPrashanth Swaminathan unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
118*1fd5a2e1SPrashanth Swaminathan
119*1fd5a2e1SPrashanth Swaminathan /* 'fpr_base' points at the space for fpr1, and grows upwards as
120*1fd5a2e1SPrashanth Swaminathan we use FPR registers. */
121*1fd5a2e1SPrashanth Swaminathan double *fpr_base = (double *) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
122*1fd5a2e1SPrashanth Swaminathan int gp_count = 0, fparg_count = 0;
123*1fd5a2e1SPrashanth Swaminathan
124*1fd5a2e1SPrashanth Swaminathan /* 'next_arg' grows up as we put parameters in it. */
125*1fd5a2e1SPrashanth Swaminathan unsigned long *next_arg = stack + LINKAGE_AREA_GPRS; /* 6 reserved positions. */
126*1fd5a2e1SPrashanth Swaminathan
127*1fd5a2e1SPrashanth Swaminathan int i;
128*1fd5a2e1SPrashanth Swaminathan double double_tmp;
129*1fd5a2e1SPrashanth Swaminathan void **p_argv = ecif->avalue;
130*1fd5a2e1SPrashanth Swaminathan unsigned long gprvalue;
131*1fd5a2e1SPrashanth Swaminathan ffi_type** ptr = ecif->cif->arg_types;
132*1fd5a2e1SPrashanth Swaminathan #if !defined(POWERPC_DARWIN64)
133*1fd5a2e1SPrashanth Swaminathan char *dest_cpy;
134*1fd5a2e1SPrashanth Swaminathan #endif
135*1fd5a2e1SPrashanth Swaminathan unsigned size_al = 0;
136*1fd5a2e1SPrashanth Swaminathan
137*1fd5a2e1SPrashanth Swaminathan /* Check that everything starts aligned properly. */
138*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(((unsigned) (char *) stack & 0xF) == 0);
139*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(((unsigned) (char *) stacktop & 0xF) == 0);
140*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT((bytes & 0xF) == 0);
141*1fd5a2e1SPrashanth Swaminathan
142*1fd5a2e1SPrashanth Swaminathan /* Deal with return values that are actually pass-by-reference.
143*1fd5a2e1SPrashanth Swaminathan Rule:
144*1fd5a2e1SPrashanth Swaminathan Return values are referenced by r3, so r4 is the first parameter. */
145*1fd5a2e1SPrashanth Swaminathan
146*1fd5a2e1SPrashanth Swaminathan if (flags & FLAG_RETVAL_REFERENCE)
147*1fd5a2e1SPrashanth Swaminathan *next_arg++ = (unsigned long) (char *) ecif->rvalue;
148*1fd5a2e1SPrashanth Swaminathan
149*1fd5a2e1SPrashanth Swaminathan /* Now for the arguments. */
150*1fd5a2e1SPrashanth Swaminathan for (i = nargs; i > 0; i--, ptr++, p_argv++)
151*1fd5a2e1SPrashanth Swaminathan {
152*1fd5a2e1SPrashanth Swaminathan switch ((*ptr)->type)
153*1fd5a2e1SPrashanth Swaminathan {
154*1fd5a2e1SPrashanth Swaminathan /* If a floating-point parameter appears before all of the general-
155*1fd5a2e1SPrashanth Swaminathan purpose registers are filled, the corresponding GPRs that match
156*1fd5a2e1SPrashanth Swaminathan the size of the floating-point parameter are skipped. */
157*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
158*1fd5a2e1SPrashanth Swaminathan double_tmp = *(float *) *p_argv;
159*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS)
160*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = double_tmp;
161*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN)
162*1fd5a2e1SPrashanth Swaminathan *(float *)next_arg = *(float *) *p_argv;
163*1fd5a2e1SPrashanth Swaminathan #else
164*1fd5a2e1SPrashanth Swaminathan *(double *)next_arg = double_tmp;
165*1fd5a2e1SPrashanth Swaminathan #endif
166*1fd5a2e1SPrashanth Swaminathan next_arg++;
167*1fd5a2e1SPrashanth Swaminathan gp_count++;
168*1fd5a2e1SPrashanth Swaminathan fparg_count++;
169*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
170*1fd5a2e1SPrashanth Swaminathan break;
171*1fd5a2e1SPrashanth Swaminathan
172*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
173*1fd5a2e1SPrashanth Swaminathan double_tmp = *(double *) *p_argv;
174*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS)
175*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = double_tmp;
176*1fd5a2e1SPrashanth Swaminathan *(double *)next_arg = double_tmp;
177*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
178*1fd5a2e1SPrashanth Swaminathan next_arg++;
179*1fd5a2e1SPrashanth Swaminathan gp_count++;
180*1fd5a2e1SPrashanth Swaminathan #else
181*1fd5a2e1SPrashanth Swaminathan next_arg += 2;
182*1fd5a2e1SPrashanth Swaminathan gp_count += 2;
183*1fd5a2e1SPrashanth Swaminathan #endif
184*1fd5a2e1SPrashanth Swaminathan fparg_count++;
185*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
186*1fd5a2e1SPrashanth Swaminathan break;
187*1fd5a2e1SPrashanth Swaminathan
188*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
189*1fd5a2e1SPrashanth Swaminathan
190*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
191*1fd5a2e1SPrashanth Swaminathan # if defined(POWERPC64) && !defined(POWERPC_DARWIN64)
192*1fd5a2e1SPrashanth Swaminathan /* ??? This will exceed the regs count when the value starts at fp13
193*1fd5a2e1SPrashanth Swaminathan and it will not put the extra bit on the stack. */
194*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS)
195*1fd5a2e1SPrashanth Swaminathan *(long double *) fpr_base++ = *(long double *) *p_argv;
196*1fd5a2e1SPrashanth Swaminathan else
197*1fd5a2e1SPrashanth Swaminathan *(long double *) next_arg = *(long double *) *p_argv;
198*1fd5a2e1SPrashanth Swaminathan next_arg += 2;
199*1fd5a2e1SPrashanth Swaminathan fparg_count += 2;
200*1fd5a2e1SPrashanth Swaminathan # else
201*1fd5a2e1SPrashanth Swaminathan double_tmp = ((double *) *p_argv)[0];
202*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS)
203*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = double_tmp;
204*1fd5a2e1SPrashanth Swaminathan *(double *) next_arg = double_tmp;
205*1fd5a2e1SPrashanth Swaminathan # if defined(POWERPC_DARWIN64)
206*1fd5a2e1SPrashanth Swaminathan next_arg++;
207*1fd5a2e1SPrashanth Swaminathan gp_count++;
208*1fd5a2e1SPrashanth Swaminathan # else
209*1fd5a2e1SPrashanth Swaminathan next_arg += 2;
210*1fd5a2e1SPrashanth Swaminathan gp_count += 2;
211*1fd5a2e1SPrashanth Swaminathan # endif
212*1fd5a2e1SPrashanth Swaminathan fparg_count++;
213*1fd5a2e1SPrashanth Swaminathan double_tmp = ((double *) *p_argv)[1];
214*1fd5a2e1SPrashanth Swaminathan if (fparg_count < NUM_FPR_ARG_REGISTERS)
215*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = double_tmp;
216*1fd5a2e1SPrashanth Swaminathan *(double *) next_arg = double_tmp;
217*1fd5a2e1SPrashanth Swaminathan # if defined(POWERPC_DARWIN64)
218*1fd5a2e1SPrashanth Swaminathan next_arg++;
219*1fd5a2e1SPrashanth Swaminathan gp_count++;
220*1fd5a2e1SPrashanth Swaminathan # else
221*1fd5a2e1SPrashanth Swaminathan next_arg += 2;
222*1fd5a2e1SPrashanth Swaminathan gp_count += 2;
223*1fd5a2e1SPrashanth Swaminathan # endif
224*1fd5a2e1SPrashanth Swaminathan fparg_count++;
225*1fd5a2e1SPrashanth Swaminathan # endif
226*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
227*1fd5a2e1SPrashanth Swaminathan break;
228*1fd5a2e1SPrashanth Swaminathan #endif
229*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
230*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
231*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
232*1fd5a2e1SPrashanth Swaminathan gprvalue = *(long long *) *p_argv;
233*1fd5a2e1SPrashanth Swaminathan goto putgpr;
234*1fd5a2e1SPrashanth Swaminathan #else
235*1fd5a2e1SPrashanth Swaminathan *(long long *) next_arg = *(long long *) *p_argv;
236*1fd5a2e1SPrashanth Swaminathan next_arg += 2;
237*1fd5a2e1SPrashanth Swaminathan gp_count += 2;
238*1fd5a2e1SPrashanth Swaminathan #endif
239*1fd5a2e1SPrashanth Swaminathan break;
240*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
241*1fd5a2e1SPrashanth Swaminathan gprvalue = *(unsigned long *) *p_argv;
242*1fd5a2e1SPrashanth Swaminathan goto putgpr;
243*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
244*1fd5a2e1SPrashanth Swaminathan gprvalue = *(unsigned char *) *p_argv;
245*1fd5a2e1SPrashanth Swaminathan goto putgpr;
246*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
247*1fd5a2e1SPrashanth Swaminathan gprvalue = *(signed char *) *p_argv;
248*1fd5a2e1SPrashanth Swaminathan goto putgpr;
249*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
250*1fd5a2e1SPrashanth Swaminathan gprvalue = *(unsigned short *) *p_argv;
251*1fd5a2e1SPrashanth Swaminathan goto putgpr;
252*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
253*1fd5a2e1SPrashanth Swaminathan gprvalue = *(signed short *) *p_argv;
254*1fd5a2e1SPrashanth Swaminathan goto putgpr;
255*1fd5a2e1SPrashanth Swaminathan
256*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
257*1fd5a2e1SPrashanth Swaminathan size_al = (*ptr)->size;
258*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
259*1fd5a2e1SPrashanth Swaminathan next_arg = (unsigned long *)FFI_ALIGN((char *)next_arg, (*ptr)->alignment);
260*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_by_value (*ptr, (char *) *p_argv,
261*1fd5a2e1SPrashanth Swaminathan (unsigned) size_al,
262*1fd5a2e1SPrashanth Swaminathan (unsigned int *) &fparg_count,
263*1fd5a2e1SPrashanth Swaminathan &fpr_base, &next_arg);
264*1fd5a2e1SPrashanth Swaminathan #else
265*1fd5a2e1SPrashanth Swaminathan dest_cpy = (char *) next_arg;
266*1fd5a2e1SPrashanth Swaminathan
267*1fd5a2e1SPrashanth Swaminathan /* If the first member of the struct is a double, then include enough
268*1fd5a2e1SPrashanth Swaminathan padding in the struct size to align it to double-word. */
269*1fd5a2e1SPrashanth Swaminathan if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
270*1fd5a2e1SPrashanth Swaminathan size_al = FFI_ALIGN((*ptr)->size, 8);
271*1fd5a2e1SPrashanth Swaminathan
272*1fd5a2e1SPrashanth Swaminathan # if defined(POWERPC64)
273*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (abi != FFI_DARWIN);
274*1fd5a2e1SPrashanth Swaminathan memcpy ((char *) dest_cpy, (char *) *p_argv, size_al);
275*1fd5a2e1SPrashanth Swaminathan next_arg += (size_al + 7) / 8;
276*1fd5a2e1SPrashanth Swaminathan # else
277*1fd5a2e1SPrashanth Swaminathan /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
278*1fd5a2e1SPrashanth Swaminathan SI 4 bytes) are aligned as if they were those modes.
279*1fd5a2e1SPrashanth Swaminathan Structures with 3 byte in size are padded upwards. */
280*1fd5a2e1SPrashanth Swaminathan if (size_al < 3 && abi == FFI_DARWIN)
281*1fd5a2e1SPrashanth Swaminathan dest_cpy += 4 - size_al;
282*1fd5a2e1SPrashanth Swaminathan
283*1fd5a2e1SPrashanth Swaminathan memcpy((char *) dest_cpy, (char *) *p_argv, size_al);
284*1fd5a2e1SPrashanth Swaminathan next_arg += (size_al + 3) / 4;
285*1fd5a2e1SPrashanth Swaminathan # endif
286*1fd5a2e1SPrashanth Swaminathan #endif
287*1fd5a2e1SPrashanth Swaminathan break;
288*1fd5a2e1SPrashanth Swaminathan
289*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_INT:
290*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
291*1fd5a2e1SPrashanth Swaminathan gprvalue = *(signed int *) *p_argv;
292*1fd5a2e1SPrashanth Swaminathan goto putgpr;
293*1fd5a2e1SPrashanth Swaminathan
294*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
295*1fd5a2e1SPrashanth Swaminathan gprvalue = *(unsigned int *) *p_argv;
296*1fd5a2e1SPrashanth Swaminathan putgpr:
297*1fd5a2e1SPrashanth Swaminathan *next_arg++ = gprvalue;
298*1fd5a2e1SPrashanth Swaminathan gp_count++;
299*1fd5a2e1SPrashanth Swaminathan break;
300*1fd5a2e1SPrashanth Swaminathan default:
301*1fd5a2e1SPrashanth Swaminathan break;
302*1fd5a2e1SPrashanth Swaminathan }
303*1fd5a2e1SPrashanth Swaminathan }
304*1fd5a2e1SPrashanth Swaminathan
305*1fd5a2e1SPrashanth Swaminathan /* Check that we didn't overrun the stack... */
306*1fd5a2e1SPrashanth Swaminathan /* FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS);
307*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT((unsigned *)fpr_base
308*1fd5a2e1SPrashanth Swaminathan <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
309*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); */
310*1fd5a2e1SPrashanth Swaminathan }
311*1fd5a2e1SPrashanth Swaminathan
312*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
313*1fd5a2e1SPrashanth Swaminathan
314*1fd5a2e1SPrashanth Swaminathan /* See if we can put some of the struct into fprs.
315*1fd5a2e1SPrashanth Swaminathan This should not be called for structures of size 16 bytes, since these are not
316*1fd5a2e1SPrashanth Swaminathan broken out this way. */
317*1fd5a2e1SPrashanth Swaminathan static void
darwin64_scan_struct_for_floats(ffi_type * s,unsigned * nfpr)318*1fd5a2e1SPrashanth Swaminathan darwin64_scan_struct_for_floats (ffi_type *s, unsigned *nfpr)
319*1fd5a2e1SPrashanth Swaminathan {
320*1fd5a2e1SPrashanth Swaminathan int i;
321*1fd5a2e1SPrashanth Swaminathan
322*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
323*1fd5a2e1SPrashanth Swaminathan
324*1fd5a2e1SPrashanth Swaminathan for (i = 0; s->elements[i] != NULL; i++)
325*1fd5a2e1SPrashanth Swaminathan {
326*1fd5a2e1SPrashanth Swaminathan ffi_type *p = s->elements[i];
327*1fd5a2e1SPrashanth Swaminathan switch (p->type)
328*1fd5a2e1SPrashanth Swaminathan {
329*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
330*1fd5a2e1SPrashanth Swaminathan darwin64_scan_struct_for_floats (p, nfpr);
331*1fd5a2e1SPrashanth Swaminathan break;
332*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
333*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 2;
334*1fd5a2e1SPrashanth Swaminathan break;
335*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
336*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
337*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
338*1fd5a2e1SPrashanth Swaminathan break;
339*1fd5a2e1SPrashanth Swaminathan default:
340*1fd5a2e1SPrashanth Swaminathan break;
341*1fd5a2e1SPrashanth Swaminathan }
342*1fd5a2e1SPrashanth Swaminathan }
343*1fd5a2e1SPrashanth Swaminathan }
344*1fd5a2e1SPrashanth Swaminathan
345*1fd5a2e1SPrashanth Swaminathan static int
darwin64_struct_size_exceeds_gprs_p(ffi_type * s,char * src,unsigned * nfpr)346*1fd5a2e1SPrashanth Swaminathan darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr)
347*1fd5a2e1SPrashanth Swaminathan {
348*1fd5a2e1SPrashanth Swaminathan unsigned struct_offset=0, i;
349*1fd5a2e1SPrashanth Swaminathan
350*1fd5a2e1SPrashanth Swaminathan for (i = 0; s->elements[i] != NULL; i++)
351*1fd5a2e1SPrashanth Swaminathan {
352*1fd5a2e1SPrashanth Swaminathan char *item_base;
353*1fd5a2e1SPrashanth Swaminathan ffi_type *p = s->elements[i];
354*1fd5a2e1SPrashanth Swaminathan /* Find the start of this item (0 for the first one). */
355*1fd5a2e1SPrashanth Swaminathan if (i > 0)
356*1fd5a2e1SPrashanth Swaminathan struct_offset = FFI_ALIGN(struct_offset, p->alignment);
357*1fd5a2e1SPrashanth Swaminathan
358*1fd5a2e1SPrashanth Swaminathan item_base = src + struct_offset;
359*1fd5a2e1SPrashanth Swaminathan
360*1fd5a2e1SPrashanth Swaminathan switch (p->type)
361*1fd5a2e1SPrashanth Swaminathan {
362*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
363*1fd5a2e1SPrashanth Swaminathan if (darwin64_struct_size_exceeds_gprs_p (p, item_base, nfpr))
364*1fd5a2e1SPrashanth Swaminathan return 1;
365*1fd5a2e1SPrashanth Swaminathan break;
366*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
367*1fd5a2e1SPrashanth Swaminathan if (*nfpr >= NUM_FPR_ARG_REGISTERS)
368*1fd5a2e1SPrashanth Swaminathan return 1;
369*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
370*1fd5a2e1SPrashanth Swaminathan item_base += 8;
371*1fd5a2e1SPrashanth Swaminathan /* FALL THROUGH */
372*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
373*1fd5a2e1SPrashanth Swaminathan if (*nfpr >= NUM_FPR_ARG_REGISTERS)
374*1fd5a2e1SPrashanth Swaminathan return 1;
375*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
376*1fd5a2e1SPrashanth Swaminathan break;
377*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
378*1fd5a2e1SPrashanth Swaminathan if (*nfpr >= NUM_FPR_ARG_REGISTERS)
379*1fd5a2e1SPrashanth Swaminathan return 1;
380*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
381*1fd5a2e1SPrashanth Swaminathan break;
382*1fd5a2e1SPrashanth Swaminathan default:
383*1fd5a2e1SPrashanth Swaminathan /* If we try and place any item, that is non-float, once we've
384*1fd5a2e1SPrashanth Swaminathan exceeded the 8 GPR mark, then we can't fit the struct. */
385*1fd5a2e1SPrashanth Swaminathan if ((unsigned long)item_base >= 8*8)
386*1fd5a2e1SPrashanth Swaminathan return 1;
387*1fd5a2e1SPrashanth Swaminathan break;
388*1fd5a2e1SPrashanth Swaminathan }
389*1fd5a2e1SPrashanth Swaminathan /* now count the size of what we just used. */
390*1fd5a2e1SPrashanth Swaminathan struct_offset += p->size;
391*1fd5a2e1SPrashanth Swaminathan }
392*1fd5a2e1SPrashanth Swaminathan return 0;
393*1fd5a2e1SPrashanth Swaminathan }
394*1fd5a2e1SPrashanth Swaminathan
395*1fd5a2e1SPrashanth Swaminathan /* Can this struct be returned by value? */
396*1fd5a2e1SPrashanth Swaminathan int
darwin64_struct_ret_by_value_p(ffi_type * s)397*1fd5a2e1SPrashanth Swaminathan darwin64_struct_ret_by_value_p (ffi_type *s)
398*1fd5a2e1SPrashanth Swaminathan {
399*1fd5a2e1SPrashanth Swaminathan unsigned nfp = 0;
400*1fd5a2e1SPrashanth Swaminathan
401*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (s && s->type == FFI_TYPE_STRUCT);
402*1fd5a2e1SPrashanth Swaminathan
403*1fd5a2e1SPrashanth Swaminathan /* The largest structure we can return is 8long + 13 doubles. */
404*1fd5a2e1SPrashanth Swaminathan if (s->size > 168)
405*1fd5a2e1SPrashanth Swaminathan return 0;
406*1fd5a2e1SPrashanth Swaminathan
407*1fd5a2e1SPrashanth Swaminathan /* We can't pass more than 13 floats. */
408*1fd5a2e1SPrashanth Swaminathan darwin64_scan_struct_for_floats (s, &nfp);
409*1fd5a2e1SPrashanth Swaminathan if (nfp > 13)
410*1fd5a2e1SPrashanth Swaminathan return 0;
411*1fd5a2e1SPrashanth Swaminathan
412*1fd5a2e1SPrashanth Swaminathan /* If there are not too many floats, and the struct is
413*1fd5a2e1SPrashanth Swaminathan small enough to accommodate in the GPRs, then it must be OK. */
414*1fd5a2e1SPrashanth Swaminathan if (s->size <= 64)
415*1fd5a2e1SPrashanth Swaminathan return 1;
416*1fd5a2e1SPrashanth Swaminathan
417*1fd5a2e1SPrashanth Swaminathan /* Well, we have to look harder. */
418*1fd5a2e1SPrashanth Swaminathan nfp = 0;
419*1fd5a2e1SPrashanth Swaminathan if (darwin64_struct_size_exceeds_gprs_p (s, NULL, &nfp))
420*1fd5a2e1SPrashanth Swaminathan return 0;
421*1fd5a2e1SPrashanth Swaminathan
422*1fd5a2e1SPrashanth Swaminathan return 1;
423*1fd5a2e1SPrashanth Swaminathan }
424*1fd5a2e1SPrashanth Swaminathan
425*1fd5a2e1SPrashanth Swaminathan void
darwin64_pass_struct_floats(ffi_type * s,char * src,unsigned * nfpr,double ** fprs)426*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_floats (ffi_type *s, char *src,
427*1fd5a2e1SPrashanth Swaminathan unsigned *nfpr, double **fprs)
428*1fd5a2e1SPrashanth Swaminathan {
429*1fd5a2e1SPrashanth Swaminathan int i;
430*1fd5a2e1SPrashanth Swaminathan double *fpr_base = *fprs;
431*1fd5a2e1SPrashanth Swaminathan unsigned struct_offset = 0;
432*1fd5a2e1SPrashanth Swaminathan
433*1fd5a2e1SPrashanth Swaminathan /* We don't assume anything about the alignment of the source. */
434*1fd5a2e1SPrashanth Swaminathan for (i = 0; s->elements[i] != NULL; i++)
435*1fd5a2e1SPrashanth Swaminathan {
436*1fd5a2e1SPrashanth Swaminathan char *item_base;
437*1fd5a2e1SPrashanth Swaminathan ffi_type *p = s->elements[i];
438*1fd5a2e1SPrashanth Swaminathan /* Find the start of this item (0 for the first one). */
439*1fd5a2e1SPrashanth Swaminathan if (i > 0)
440*1fd5a2e1SPrashanth Swaminathan struct_offset = FFI_ALIGN(struct_offset, p->alignment);
441*1fd5a2e1SPrashanth Swaminathan item_base = src + struct_offset;
442*1fd5a2e1SPrashanth Swaminathan
443*1fd5a2e1SPrashanth Swaminathan switch (p->type)
444*1fd5a2e1SPrashanth Swaminathan {
445*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
446*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_floats (p, item_base, nfpr,
447*1fd5a2e1SPrashanth Swaminathan &fpr_base);
448*1fd5a2e1SPrashanth Swaminathan break;
449*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
450*1fd5a2e1SPrashanth Swaminathan if (*nfpr < NUM_FPR_ARG_REGISTERS)
451*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = *(double *)item_base;
452*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
453*1fd5a2e1SPrashanth Swaminathan item_base += 8;
454*1fd5a2e1SPrashanth Swaminathan /* FALL THROUGH */
455*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
456*1fd5a2e1SPrashanth Swaminathan if (*nfpr < NUM_FPR_ARG_REGISTERS)
457*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = *(double *)item_base;
458*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
459*1fd5a2e1SPrashanth Swaminathan break;
460*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
461*1fd5a2e1SPrashanth Swaminathan if (*nfpr < NUM_FPR_ARG_REGISTERS)
462*1fd5a2e1SPrashanth Swaminathan *fpr_base++ = (double) *(float *)item_base;
463*1fd5a2e1SPrashanth Swaminathan (*nfpr) += 1;
464*1fd5a2e1SPrashanth Swaminathan break;
465*1fd5a2e1SPrashanth Swaminathan default:
466*1fd5a2e1SPrashanth Swaminathan break;
467*1fd5a2e1SPrashanth Swaminathan }
468*1fd5a2e1SPrashanth Swaminathan /* now count the size of what we just used. */
469*1fd5a2e1SPrashanth Swaminathan struct_offset += p->size;
470*1fd5a2e1SPrashanth Swaminathan }
471*1fd5a2e1SPrashanth Swaminathan /* Update the scores. */
472*1fd5a2e1SPrashanth Swaminathan *fprs = fpr_base;
473*1fd5a2e1SPrashanth Swaminathan }
474*1fd5a2e1SPrashanth Swaminathan
475*1fd5a2e1SPrashanth Swaminathan /* Darwin64 special rules.
476*1fd5a2e1SPrashanth Swaminathan Break out a struct into params and float registers. */
477*1fd5a2e1SPrashanth Swaminathan static void
darwin64_pass_struct_by_value(ffi_type * s,char * src,unsigned size,unsigned * nfpr,double ** fprs,unsigned long ** arg)478*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_by_value (ffi_type *s, char *src, unsigned size,
479*1fd5a2e1SPrashanth Swaminathan unsigned *nfpr, double **fprs, unsigned long **arg)
480*1fd5a2e1SPrashanth Swaminathan {
481*1fd5a2e1SPrashanth Swaminathan unsigned long *next_arg = *arg;
482*1fd5a2e1SPrashanth Swaminathan char *dest_cpy = (char *)next_arg;
483*1fd5a2e1SPrashanth Swaminathan
484*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
485*1fd5a2e1SPrashanth Swaminathan
486*1fd5a2e1SPrashanth Swaminathan if (!size)
487*1fd5a2e1SPrashanth Swaminathan return;
488*1fd5a2e1SPrashanth Swaminathan
489*1fd5a2e1SPrashanth Swaminathan /* First... special cases. */
490*1fd5a2e1SPrashanth Swaminathan if (size < 3
491*1fd5a2e1SPrashanth Swaminathan || (size == 4
492*1fd5a2e1SPrashanth Swaminathan && s->elements[0]
493*1fd5a2e1SPrashanth Swaminathan && s->elements[0]->type != FFI_TYPE_FLOAT))
494*1fd5a2e1SPrashanth Swaminathan {
495*1fd5a2e1SPrashanth Swaminathan /* Must be at least one GPR, padding is unspecified in value,
496*1fd5a2e1SPrashanth Swaminathan let's make it zero. */
497*1fd5a2e1SPrashanth Swaminathan *next_arg = 0UL;
498*1fd5a2e1SPrashanth Swaminathan dest_cpy += 8 - size;
499*1fd5a2e1SPrashanth Swaminathan memcpy ((char *) dest_cpy, src, size);
500*1fd5a2e1SPrashanth Swaminathan next_arg++;
501*1fd5a2e1SPrashanth Swaminathan }
502*1fd5a2e1SPrashanth Swaminathan else if (size == 16)
503*1fd5a2e1SPrashanth Swaminathan {
504*1fd5a2e1SPrashanth Swaminathan memcpy ((char *) dest_cpy, src, size);
505*1fd5a2e1SPrashanth Swaminathan next_arg += 2;
506*1fd5a2e1SPrashanth Swaminathan }
507*1fd5a2e1SPrashanth Swaminathan else
508*1fd5a2e1SPrashanth Swaminathan {
509*1fd5a2e1SPrashanth Swaminathan /* now the general case, we consider embedded floats. */
510*1fd5a2e1SPrashanth Swaminathan memcpy ((char *) dest_cpy, src, size);
511*1fd5a2e1SPrashanth Swaminathan darwin64_pass_struct_floats (s, src, nfpr, fprs);
512*1fd5a2e1SPrashanth Swaminathan next_arg += (size+7)/8;
513*1fd5a2e1SPrashanth Swaminathan }
514*1fd5a2e1SPrashanth Swaminathan
515*1fd5a2e1SPrashanth Swaminathan *arg = next_arg;
516*1fd5a2e1SPrashanth Swaminathan }
517*1fd5a2e1SPrashanth Swaminathan
518*1fd5a2e1SPrashanth Swaminathan double *
darwin64_struct_floats_to_mem(ffi_type * s,char * dest,double * fprs,unsigned * nf)519*1fd5a2e1SPrashanth Swaminathan darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned *nf)
520*1fd5a2e1SPrashanth Swaminathan {
521*1fd5a2e1SPrashanth Swaminathan int i;
522*1fd5a2e1SPrashanth Swaminathan unsigned struct_offset = 0;
523*1fd5a2e1SPrashanth Swaminathan
524*1fd5a2e1SPrashanth Swaminathan /* We don't assume anything about the alignment of the source. */
525*1fd5a2e1SPrashanth Swaminathan for (i = 0; s->elements[i] != NULL; i++)
526*1fd5a2e1SPrashanth Swaminathan {
527*1fd5a2e1SPrashanth Swaminathan char *item_base;
528*1fd5a2e1SPrashanth Swaminathan ffi_type *p = s->elements[i];
529*1fd5a2e1SPrashanth Swaminathan /* Find the start of this item (0 for the first one). */
530*1fd5a2e1SPrashanth Swaminathan if (i > 0)
531*1fd5a2e1SPrashanth Swaminathan struct_offset = FFI_ALIGN(struct_offset, p->alignment);
532*1fd5a2e1SPrashanth Swaminathan item_base = dest + struct_offset;
533*1fd5a2e1SPrashanth Swaminathan
534*1fd5a2e1SPrashanth Swaminathan switch (p->type)
535*1fd5a2e1SPrashanth Swaminathan {
536*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
537*1fd5a2e1SPrashanth Swaminathan fprs = darwin64_struct_floats_to_mem (p, item_base, fprs, nf);
538*1fd5a2e1SPrashanth Swaminathan break;
539*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
540*1fd5a2e1SPrashanth Swaminathan if (*nf < NUM_FPR_ARG_REGISTERS)
541*1fd5a2e1SPrashanth Swaminathan {
542*1fd5a2e1SPrashanth Swaminathan *(double *)item_base = *fprs++ ;
543*1fd5a2e1SPrashanth Swaminathan (*nf) += 1;
544*1fd5a2e1SPrashanth Swaminathan }
545*1fd5a2e1SPrashanth Swaminathan item_base += 8;
546*1fd5a2e1SPrashanth Swaminathan /* FALL THROUGH */
547*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
548*1fd5a2e1SPrashanth Swaminathan if (*nf < NUM_FPR_ARG_REGISTERS)
549*1fd5a2e1SPrashanth Swaminathan {
550*1fd5a2e1SPrashanth Swaminathan *(double *)item_base = *fprs++ ;
551*1fd5a2e1SPrashanth Swaminathan (*nf) += 1;
552*1fd5a2e1SPrashanth Swaminathan }
553*1fd5a2e1SPrashanth Swaminathan break;
554*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
555*1fd5a2e1SPrashanth Swaminathan if (*nf < NUM_FPR_ARG_REGISTERS)
556*1fd5a2e1SPrashanth Swaminathan {
557*1fd5a2e1SPrashanth Swaminathan *(float *)item_base = (float) *fprs++ ;
558*1fd5a2e1SPrashanth Swaminathan (*nf) += 1;
559*1fd5a2e1SPrashanth Swaminathan }
560*1fd5a2e1SPrashanth Swaminathan break;
561*1fd5a2e1SPrashanth Swaminathan default:
562*1fd5a2e1SPrashanth Swaminathan break;
563*1fd5a2e1SPrashanth Swaminathan }
564*1fd5a2e1SPrashanth Swaminathan /* now count the size of what we just used. */
565*1fd5a2e1SPrashanth Swaminathan struct_offset += p->size;
566*1fd5a2e1SPrashanth Swaminathan }
567*1fd5a2e1SPrashanth Swaminathan return fprs;
568*1fd5a2e1SPrashanth Swaminathan }
569*1fd5a2e1SPrashanth Swaminathan
570*1fd5a2e1SPrashanth Swaminathan #endif
571*1fd5a2e1SPrashanth Swaminathan
572*1fd5a2e1SPrashanth Swaminathan /* Adjust the size of S to be correct for Darwin.
573*1fd5a2e1SPrashanth Swaminathan On Darwin m32, the first field of a structure has natural alignment.
574*1fd5a2e1SPrashanth Swaminathan On Darwin m64, all fields have natural alignment. */
575*1fd5a2e1SPrashanth Swaminathan
576*1fd5a2e1SPrashanth Swaminathan static void
darwin_adjust_aggregate_sizes(ffi_type * s)577*1fd5a2e1SPrashanth Swaminathan darwin_adjust_aggregate_sizes (ffi_type *s)
578*1fd5a2e1SPrashanth Swaminathan {
579*1fd5a2e1SPrashanth Swaminathan int i;
580*1fd5a2e1SPrashanth Swaminathan
581*1fd5a2e1SPrashanth Swaminathan if (s->type != FFI_TYPE_STRUCT)
582*1fd5a2e1SPrashanth Swaminathan return;
583*1fd5a2e1SPrashanth Swaminathan
584*1fd5a2e1SPrashanth Swaminathan s->size = 0;
585*1fd5a2e1SPrashanth Swaminathan for (i = 0; s->elements[i] != NULL; i++)
586*1fd5a2e1SPrashanth Swaminathan {
587*1fd5a2e1SPrashanth Swaminathan ffi_type *p;
588*1fd5a2e1SPrashanth Swaminathan int align;
589*1fd5a2e1SPrashanth Swaminathan
590*1fd5a2e1SPrashanth Swaminathan p = s->elements[i];
591*1fd5a2e1SPrashanth Swaminathan if (p->type == FFI_TYPE_STRUCT)
592*1fd5a2e1SPrashanth Swaminathan darwin_adjust_aggregate_sizes (p);
593*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
594*1fd5a2e1SPrashanth Swaminathan /* Natural alignment for all items. */
595*1fd5a2e1SPrashanth Swaminathan align = p->alignment;
596*1fd5a2e1SPrashanth Swaminathan #else
597*1fd5a2e1SPrashanth Swaminathan /* Natural alignment for the first item... */
598*1fd5a2e1SPrashanth Swaminathan if (i == 0)
599*1fd5a2e1SPrashanth Swaminathan align = p->alignment;
600*1fd5a2e1SPrashanth Swaminathan else if (p->alignment == 16 || p->alignment < 4)
601*1fd5a2e1SPrashanth Swaminathan /* .. subsequent items with vector or align < 4 have natural align. */
602*1fd5a2e1SPrashanth Swaminathan align = p->alignment;
603*1fd5a2e1SPrashanth Swaminathan else
604*1fd5a2e1SPrashanth Swaminathan /* .. or align is 4. */
605*1fd5a2e1SPrashanth Swaminathan align = 4;
606*1fd5a2e1SPrashanth Swaminathan #endif
607*1fd5a2e1SPrashanth Swaminathan /* Pad, if necessary, before adding the current item. */
608*1fd5a2e1SPrashanth Swaminathan s->size = FFI_ALIGN(s->size, align) + p->size;
609*1fd5a2e1SPrashanth Swaminathan }
610*1fd5a2e1SPrashanth Swaminathan
611*1fd5a2e1SPrashanth Swaminathan s->size = FFI_ALIGN(s->size, s->alignment);
612*1fd5a2e1SPrashanth Swaminathan
613*1fd5a2e1SPrashanth Swaminathan /* This should not be necessary on m64, but harmless. */
614*1fd5a2e1SPrashanth Swaminathan if (s->elements[0]->type == FFI_TYPE_UINT64
615*1fd5a2e1SPrashanth Swaminathan || s->elements[0]->type == FFI_TYPE_SINT64
616*1fd5a2e1SPrashanth Swaminathan || s->elements[0]->type == FFI_TYPE_DOUBLE
617*1fd5a2e1SPrashanth Swaminathan || s->elements[0]->alignment == 8)
618*1fd5a2e1SPrashanth Swaminathan s->alignment = s->alignment > 8 ? s->alignment : 8;
619*1fd5a2e1SPrashanth Swaminathan /* Do not add additional tail padding. */
620*1fd5a2e1SPrashanth Swaminathan }
621*1fd5a2e1SPrashanth Swaminathan
622*1fd5a2e1SPrashanth Swaminathan /* Adjust the size of S to be correct for AIX.
623*1fd5a2e1SPrashanth Swaminathan Word-align double unless it is the first member of a structure. */
624*1fd5a2e1SPrashanth Swaminathan
625*1fd5a2e1SPrashanth Swaminathan static void
aix_adjust_aggregate_sizes(ffi_type * s)626*1fd5a2e1SPrashanth Swaminathan aix_adjust_aggregate_sizes (ffi_type *s)
627*1fd5a2e1SPrashanth Swaminathan {
628*1fd5a2e1SPrashanth Swaminathan int i;
629*1fd5a2e1SPrashanth Swaminathan
630*1fd5a2e1SPrashanth Swaminathan if (s->type != FFI_TYPE_STRUCT)
631*1fd5a2e1SPrashanth Swaminathan return;
632*1fd5a2e1SPrashanth Swaminathan
633*1fd5a2e1SPrashanth Swaminathan s->size = 0;
634*1fd5a2e1SPrashanth Swaminathan for (i = 0; s->elements[i] != NULL; i++)
635*1fd5a2e1SPrashanth Swaminathan {
636*1fd5a2e1SPrashanth Swaminathan ffi_type *p;
637*1fd5a2e1SPrashanth Swaminathan int align;
638*1fd5a2e1SPrashanth Swaminathan
639*1fd5a2e1SPrashanth Swaminathan p = s->elements[i];
640*1fd5a2e1SPrashanth Swaminathan aix_adjust_aggregate_sizes (p);
641*1fd5a2e1SPrashanth Swaminathan align = p->alignment;
642*1fd5a2e1SPrashanth Swaminathan if (i != 0 && p->type == FFI_TYPE_DOUBLE)
643*1fd5a2e1SPrashanth Swaminathan align = 4;
644*1fd5a2e1SPrashanth Swaminathan s->size = FFI_ALIGN(s->size, align) + p->size;
645*1fd5a2e1SPrashanth Swaminathan }
646*1fd5a2e1SPrashanth Swaminathan
647*1fd5a2e1SPrashanth Swaminathan s->size = FFI_ALIGN(s->size, s->alignment);
648*1fd5a2e1SPrashanth Swaminathan
649*1fd5a2e1SPrashanth Swaminathan if (s->elements[0]->type == FFI_TYPE_UINT64
650*1fd5a2e1SPrashanth Swaminathan || s->elements[0]->type == FFI_TYPE_SINT64
651*1fd5a2e1SPrashanth Swaminathan || s->elements[0]->type == FFI_TYPE_DOUBLE
652*1fd5a2e1SPrashanth Swaminathan || s->elements[0]->alignment == 8)
653*1fd5a2e1SPrashanth Swaminathan s->alignment = s->alignment > 8 ? s->alignment : 8;
654*1fd5a2e1SPrashanth Swaminathan /* Do not add additional tail padding. */
655*1fd5a2e1SPrashanth Swaminathan }
656*1fd5a2e1SPrashanth Swaminathan
657*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing. */
658*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_cif_machdep(ffi_cif * cif)659*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep (ffi_cif *cif)
660*1fd5a2e1SPrashanth Swaminathan {
661*1fd5a2e1SPrashanth Swaminathan /* All this is for the DARWIN ABI. */
662*1fd5a2e1SPrashanth Swaminathan unsigned i;
663*1fd5a2e1SPrashanth Swaminathan ffi_type **ptr;
664*1fd5a2e1SPrashanth Swaminathan unsigned bytes;
665*1fd5a2e1SPrashanth Swaminathan unsigned fparg_count = 0, intarg_count = 0;
666*1fd5a2e1SPrashanth Swaminathan unsigned flags = 0;
667*1fd5a2e1SPrashanth Swaminathan unsigned size_al = 0;
668*1fd5a2e1SPrashanth Swaminathan
669*1fd5a2e1SPrashanth Swaminathan /* All the machine-independent calculation of cif->bytes will be wrong.
670*1fd5a2e1SPrashanth Swaminathan All the calculation of structure sizes will also be wrong.
671*1fd5a2e1SPrashanth Swaminathan Redo the calculation for DARWIN. */
672*1fd5a2e1SPrashanth Swaminathan
673*1fd5a2e1SPrashanth Swaminathan if (cif->abi == FFI_DARWIN)
674*1fd5a2e1SPrashanth Swaminathan {
675*1fd5a2e1SPrashanth Swaminathan darwin_adjust_aggregate_sizes (cif->rtype);
676*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++)
677*1fd5a2e1SPrashanth Swaminathan darwin_adjust_aggregate_sizes (cif->arg_types[i]);
678*1fd5a2e1SPrashanth Swaminathan }
679*1fd5a2e1SPrashanth Swaminathan
680*1fd5a2e1SPrashanth Swaminathan if (cif->abi == FFI_AIX)
681*1fd5a2e1SPrashanth Swaminathan {
682*1fd5a2e1SPrashanth Swaminathan aix_adjust_aggregate_sizes (cif->rtype);
683*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < cif->nargs; i++)
684*1fd5a2e1SPrashanth Swaminathan aix_adjust_aggregate_sizes (cif->arg_types[i]);
685*1fd5a2e1SPrashanth Swaminathan }
686*1fd5a2e1SPrashanth Swaminathan
687*1fd5a2e1SPrashanth Swaminathan /* Space for the frame pointer, callee's LR, CR, etc, and for
688*1fd5a2e1SPrashanth Swaminathan the asm's temp regs. */
689*1fd5a2e1SPrashanth Swaminathan
690*1fd5a2e1SPrashanth Swaminathan bytes = (LINKAGE_AREA_GPRS + ASM_NEEDS_REGISTERS) * sizeof(unsigned long);
691*1fd5a2e1SPrashanth Swaminathan
692*1fd5a2e1SPrashanth Swaminathan /* Return value handling.
693*1fd5a2e1SPrashanth Swaminathan The rules m32 are as follows:
694*1fd5a2e1SPrashanth Swaminathan - 32-bit (or less) integer values are returned in gpr3;
695*1fd5a2e1SPrashanth Swaminathan - structures of size <= 4 bytes also returned in gpr3;
696*1fd5a2e1SPrashanth Swaminathan - 64-bit integer values [??? and structures between 5 and 8 bytes] are
697*1fd5a2e1SPrashanth Swaminathan returned in gpr3 and gpr4;
698*1fd5a2e1SPrashanth Swaminathan - Single/double FP values are returned in fpr1;
699*1fd5a2e1SPrashanth Swaminathan - Long double FP (if not equivalent to double) values are returned in
700*1fd5a2e1SPrashanth Swaminathan fpr1 and fpr2;
701*1fd5a2e1SPrashanth Swaminathan m64:
702*1fd5a2e1SPrashanth Swaminathan - 64-bit or smaller integral values are returned in GPR3
703*1fd5a2e1SPrashanth Swaminathan - Single/double FP values are returned in fpr1;
704*1fd5a2e1SPrashanth Swaminathan - Long double FP values are returned in fpr1 and fpr2;
705*1fd5a2e1SPrashanth Swaminathan m64 Structures:
706*1fd5a2e1SPrashanth Swaminathan - If the structure could be accommodated in registers were it to be the
707*1fd5a2e1SPrashanth Swaminathan first argument to a routine, then it is returned in those registers.
708*1fd5a2e1SPrashanth Swaminathan m32/m64 structures otherwise:
709*1fd5a2e1SPrashanth Swaminathan - Larger structures values are allocated space and a pointer is passed
710*1fd5a2e1SPrashanth Swaminathan as the first argument. */
711*1fd5a2e1SPrashanth Swaminathan switch (cif->rtype->type)
712*1fd5a2e1SPrashanth Swaminathan {
713*1fd5a2e1SPrashanth Swaminathan
714*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
715*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
716*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_128BITS;
717*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_FP;
718*1fd5a2e1SPrashanth Swaminathan break;
719*1fd5a2e1SPrashanth Swaminathan #endif
720*1fd5a2e1SPrashanth Swaminathan
721*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
722*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_64BITS;
723*1fd5a2e1SPrashanth Swaminathan /* Fall through. */
724*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
725*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_FP;
726*1fd5a2e1SPrashanth Swaminathan break;
727*1fd5a2e1SPrashanth Swaminathan
728*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
729*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
730*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
731*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
732*1fd5a2e1SPrashanth Swaminathan #endif
733*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_64BITS;
734*1fd5a2e1SPrashanth Swaminathan break;
735*1fd5a2e1SPrashanth Swaminathan
736*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
737*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
738*1fd5a2e1SPrashanth Swaminathan {
739*1fd5a2e1SPrashanth Swaminathan /* Can we fit the struct into regs? */
740*1fd5a2e1SPrashanth Swaminathan if (darwin64_struct_ret_by_value_p (cif->rtype))
741*1fd5a2e1SPrashanth Swaminathan {
742*1fd5a2e1SPrashanth Swaminathan unsigned nfpr = 0;
743*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_STRUCT;
744*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->size != 16)
745*1fd5a2e1SPrashanth Swaminathan darwin64_scan_struct_for_floats (cif->rtype, &nfpr) ;
746*1fd5a2e1SPrashanth Swaminathan else
747*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_128BITS;
748*1fd5a2e1SPrashanth Swaminathan /* Will be 0 for 16byte struct. */
749*1fd5a2e1SPrashanth Swaminathan if (nfpr)
750*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_FP;
751*1fd5a2e1SPrashanth Swaminathan }
752*1fd5a2e1SPrashanth Swaminathan else /* By ref. */
753*1fd5a2e1SPrashanth Swaminathan {
754*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETVAL_REFERENCE;
755*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_NOTHING;
756*1fd5a2e1SPrashanth Swaminathan intarg_count++;
757*1fd5a2e1SPrashanth Swaminathan }
758*1fd5a2e1SPrashanth Swaminathan }
759*1fd5a2e1SPrashanth Swaminathan #elif defined(DARWIN_PPC)
760*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->size <= 4)
761*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_STRUCT;
762*1fd5a2e1SPrashanth Swaminathan else /* else by reference. */
763*1fd5a2e1SPrashanth Swaminathan {
764*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETVAL_REFERENCE;
765*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_NOTHING;
766*1fd5a2e1SPrashanth Swaminathan intarg_count++;
767*1fd5a2e1SPrashanth Swaminathan }
768*1fd5a2e1SPrashanth Swaminathan #else /* assume we pass by ref. */
769*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETVAL_REFERENCE;
770*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_NOTHING;
771*1fd5a2e1SPrashanth Swaminathan intarg_count++;
772*1fd5a2e1SPrashanth Swaminathan #endif
773*1fd5a2e1SPrashanth Swaminathan break;
774*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_VOID:
775*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_RETURNS_NOTHING;
776*1fd5a2e1SPrashanth Swaminathan break;
777*1fd5a2e1SPrashanth Swaminathan
778*1fd5a2e1SPrashanth Swaminathan default:
779*1fd5a2e1SPrashanth Swaminathan /* Returns 32-bit integer, or similar. Nothing to do here. */
780*1fd5a2e1SPrashanth Swaminathan break;
781*1fd5a2e1SPrashanth Swaminathan }
782*1fd5a2e1SPrashanth Swaminathan
783*1fd5a2e1SPrashanth Swaminathan /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
784*1fd5a2e1SPrashanth Swaminathan first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
785*1fd5a2e1SPrashanth Swaminathan goes on the stack.
786*1fd5a2e1SPrashanth Swaminathan ??? Structures are passed as a pointer to a copy of the structure.
787*1fd5a2e1SPrashanth Swaminathan Stuff on the stack needs to keep proper alignment.
788*1fd5a2e1SPrashanth Swaminathan For m64 the count is effectively of half-GPRs. */
789*1fd5a2e1SPrashanth Swaminathan for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
790*1fd5a2e1SPrashanth Swaminathan {
791*1fd5a2e1SPrashanth Swaminathan unsigned align_words;
792*1fd5a2e1SPrashanth Swaminathan switch ((*ptr)->type)
793*1fd5a2e1SPrashanth Swaminathan {
794*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
795*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
796*1fd5a2e1SPrashanth Swaminathan fparg_count++;
797*1fd5a2e1SPrashanth Swaminathan #if !defined(POWERPC_DARWIN64)
798*1fd5a2e1SPrashanth Swaminathan /* If this FP arg is going on the stack, it must be
799*1fd5a2e1SPrashanth Swaminathan 8-byte-aligned. */
800*1fd5a2e1SPrashanth Swaminathan if (fparg_count > NUM_FPR_ARG_REGISTERS
801*1fd5a2e1SPrashanth Swaminathan && (intarg_count & 0x01) != 0)
802*1fd5a2e1SPrashanth Swaminathan intarg_count++;
803*1fd5a2e1SPrashanth Swaminathan #endif
804*1fd5a2e1SPrashanth Swaminathan break;
805*1fd5a2e1SPrashanth Swaminathan
806*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
807*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
808*1fd5a2e1SPrashanth Swaminathan fparg_count += 2;
809*1fd5a2e1SPrashanth Swaminathan /* If this FP arg is going on the stack, it must be
810*1fd5a2e1SPrashanth Swaminathan 16-byte-aligned. */
811*1fd5a2e1SPrashanth Swaminathan if (fparg_count >= NUM_FPR_ARG_REGISTERS)
812*1fd5a2e1SPrashanth Swaminathan #if defined (POWERPC64)
813*1fd5a2e1SPrashanth Swaminathan intarg_count = FFI_ALIGN(intarg_count, 2);
814*1fd5a2e1SPrashanth Swaminathan #else
815*1fd5a2e1SPrashanth Swaminathan intarg_count = FFI_ALIGN(intarg_count, 4);
816*1fd5a2e1SPrashanth Swaminathan #endif
817*1fd5a2e1SPrashanth Swaminathan break;
818*1fd5a2e1SPrashanth Swaminathan #endif
819*1fd5a2e1SPrashanth Swaminathan
820*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
821*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
822*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC64)
823*1fd5a2e1SPrashanth Swaminathan intarg_count++;
824*1fd5a2e1SPrashanth Swaminathan #else
825*1fd5a2e1SPrashanth Swaminathan /* 'long long' arguments are passed as two words, but
826*1fd5a2e1SPrashanth Swaminathan either both words must fit in registers or both go
827*1fd5a2e1SPrashanth Swaminathan on the stack. If they go on the stack, they must
828*1fd5a2e1SPrashanth Swaminathan be 8-byte-aligned. */
829*1fd5a2e1SPrashanth Swaminathan if (intarg_count == NUM_GPR_ARG_REGISTERS-1
830*1fd5a2e1SPrashanth Swaminathan || (intarg_count >= NUM_GPR_ARG_REGISTERS
831*1fd5a2e1SPrashanth Swaminathan && (intarg_count & 0x01) != 0))
832*1fd5a2e1SPrashanth Swaminathan intarg_count++;
833*1fd5a2e1SPrashanth Swaminathan intarg_count += 2;
834*1fd5a2e1SPrashanth Swaminathan #endif
835*1fd5a2e1SPrashanth Swaminathan break;
836*1fd5a2e1SPrashanth Swaminathan
837*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
838*1fd5a2e1SPrashanth Swaminathan size_al = (*ptr)->size;
839*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
840*1fd5a2e1SPrashanth Swaminathan align_words = (*ptr)->alignment >> 3;
841*1fd5a2e1SPrashanth Swaminathan if (align_words)
842*1fd5a2e1SPrashanth Swaminathan intarg_count = FFI_ALIGN(intarg_count, align_words);
843*1fd5a2e1SPrashanth Swaminathan /* Base size of the struct. */
844*1fd5a2e1SPrashanth Swaminathan intarg_count += (size_al + 7) / 8;
845*1fd5a2e1SPrashanth Swaminathan /* If 16 bytes then don't worry about floats. */
846*1fd5a2e1SPrashanth Swaminathan if (size_al != 16)
847*1fd5a2e1SPrashanth Swaminathan /* Scan through for floats to be placed in regs. */
848*1fd5a2e1SPrashanth Swaminathan darwin64_scan_struct_for_floats (*ptr, &fparg_count) ;
849*1fd5a2e1SPrashanth Swaminathan #else
850*1fd5a2e1SPrashanth Swaminathan align_words = (*ptr)->alignment >> 2;
851*1fd5a2e1SPrashanth Swaminathan if (align_words)
852*1fd5a2e1SPrashanth Swaminathan intarg_count = FFI_ALIGN(intarg_count, align_words);
853*1fd5a2e1SPrashanth Swaminathan /* If the first member of the struct is a double, then align
854*1fd5a2e1SPrashanth Swaminathan the struct to double-word.
855*1fd5a2e1SPrashanth Swaminathan if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
856*1fd5a2e1SPrashanth Swaminathan size_al = FFI_ALIGN((*ptr)->size, 8); */
857*1fd5a2e1SPrashanth Swaminathan # ifdef POWERPC64
858*1fd5a2e1SPrashanth Swaminathan intarg_count += (size_al + 7) / 8;
859*1fd5a2e1SPrashanth Swaminathan # else
860*1fd5a2e1SPrashanth Swaminathan intarg_count += (size_al + 3) / 4;
861*1fd5a2e1SPrashanth Swaminathan # endif
862*1fd5a2e1SPrashanth Swaminathan #endif
863*1fd5a2e1SPrashanth Swaminathan break;
864*1fd5a2e1SPrashanth Swaminathan
865*1fd5a2e1SPrashanth Swaminathan default:
866*1fd5a2e1SPrashanth Swaminathan /* Everything else is passed as a 4-byte word in a GPR, either
867*1fd5a2e1SPrashanth Swaminathan the object itself or a pointer to it. */
868*1fd5a2e1SPrashanth Swaminathan intarg_count++;
869*1fd5a2e1SPrashanth Swaminathan break;
870*1fd5a2e1SPrashanth Swaminathan }
871*1fd5a2e1SPrashanth Swaminathan }
872*1fd5a2e1SPrashanth Swaminathan
873*1fd5a2e1SPrashanth Swaminathan if (fparg_count != 0)
874*1fd5a2e1SPrashanth Swaminathan flags |= FLAG_FP_ARGUMENTS;
875*1fd5a2e1SPrashanth Swaminathan
876*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
877*1fd5a2e1SPrashanth Swaminathan /* Space to image the FPR registers, if needed - which includes when they might be
878*1fd5a2e1SPrashanth Swaminathan used in a struct return. */
879*1fd5a2e1SPrashanth Swaminathan if (fparg_count != 0
880*1fd5a2e1SPrashanth Swaminathan || ((flags & FLAG_RETURNS_STRUCT)
881*1fd5a2e1SPrashanth Swaminathan && (flags & FLAG_RETURNS_FP)))
882*1fd5a2e1SPrashanth Swaminathan bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
883*1fd5a2e1SPrashanth Swaminathan #else
884*1fd5a2e1SPrashanth Swaminathan /* Space for the FPR registers, if needed. */
885*1fd5a2e1SPrashanth Swaminathan if (fparg_count != 0)
886*1fd5a2e1SPrashanth Swaminathan bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
887*1fd5a2e1SPrashanth Swaminathan #endif
888*1fd5a2e1SPrashanth Swaminathan
889*1fd5a2e1SPrashanth Swaminathan /* Stack space. */
890*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
891*1fd5a2e1SPrashanth Swaminathan if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS)
892*1fd5a2e1SPrashanth Swaminathan bytes += (intarg_count + fparg_count) * sizeof(long);
893*1fd5a2e1SPrashanth Swaminathan #else
894*1fd5a2e1SPrashanth Swaminathan if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS)
895*1fd5a2e1SPrashanth Swaminathan bytes += (intarg_count + 2 * fparg_count) * sizeof(long);
896*1fd5a2e1SPrashanth Swaminathan #endif
897*1fd5a2e1SPrashanth Swaminathan else
898*1fd5a2e1SPrashanth Swaminathan bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
899*1fd5a2e1SPrashanth Swaminathan
900*1fd5a2e1SPrashanth Swaminathan /* The stack space allocated needs to be a multiple of 16 bytes. */
901*1fd5a2e1SPrashanth Swaminathan bytes = FFI_ALIGN(bytes, 16) ;
902*1fd5a2e1SPrashanth Swaminathan
903*1fd5a2e1SPrashanth Swaminathan cif->flags = flags;
904*1fd5a2e1SPrashanth Swaminathan cif->bytes = bytes;
905*1fd5a2e1SPrashanth Swaminathan
906*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
907*1fd5a2e1SPrashanth Swaminathan }
908*1fd5a2e1SPrashanth Swaminathan
909*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
910*1fd5a2e1SPrashanth Swaminathan void (*fn)(void), void (*fn2)(void));
911*1fd5a2e1SPrashanth Swaminathan
912*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_go_AIX(extended_cif *, long, unsigned, unsigned *,
913*1fd5a2e1SPrashanth Swaminathan void (*fn)(void), void (*fn2)(void), void *closure);
914*1fd5a2e1SPrashanth Swaminathan
915*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
916*1fd5a2e1SPrashanth Swaminathan void (*fn)(void), void (*fn2)(void), ffi_type*);
917*1fd5a2e1SPrashanth Swaminathan
918*1fd5a2e1SPrashanth Swaminathan void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)919*1fd5a2e1SPrashanth Swaminathan ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
920*1fd5a2e1SPrashanth Swaminathan {
921*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
922*1fd5a2e1SPrashanth Swaminathan
923*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
924*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
925*1fd5a2e1SPrashanth Swaminathan
926*1fd5a2e1SPrashanth Swaminathan /* If the return value is a struct and we don't have a return
927*1fd5a2e1SPrashanth Swaminathan value address then we need to make one. */
928*1fd5a2e1SPrashanth Swaminathan
929*1fd5a2e1SPrashanth Swaminathan if ((rvalue == NULL) &&
930*1fd5a2e1SPrashanth Swaminathan (cif->rtype->type == FFI_TYPE_STRUCT))
931*1fd5a2e1SPrashanth Swaminathan {
932*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = alloca (cif->rtype->size);
933*1fd5a2e1SPrashanth Swaminathan }
934*1fd5a2e1SPrashanth Swaminathan else
935*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
936*1fd5a2e1SPrashanth Swaminathan
937*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
938*1fd5a2e1SPrashanth Swaminathan {
939*1fd5a2e1SPrashanth Swaminathan case FFI_AIX:
940*1fd5a2e1SPrashanth Swaminathan ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
941*1fd5a2e1SPrashanth Swaminathan FFI_FN(ffi_prep_args));
942*1fd5a2e1SPrashanth Swaminathan break;
943*1fd5a2e1SPrashanth Swaminathan case FFI_DARWIN:
944*1fd5a2e1SPrashanth Swaminathan ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
945*1fd5a2e1SPrashanth Swaminathan FFI_FN(ffi_prep_args), cif->rtype);
946*1fd5a2e1SPrashanth Swaminathan break;
947*1fd5a2e1SPrashanth Swaminathan default:
948*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
949*1fd5a2e1SPrashanth Swaminathan break;
950*1fd5a2e1SPrashanth Swaminathan }
951*1fd5a2e1SPrashanth Swaminathan }
952*1fd5a2e1SPrashanth Swaminathan
953*1fd5a2e1SPrashanth Swaminathan void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)954*1fd5a2e1SPrashanth Swaminathan ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
955*1fd5a2e1SPrashanth Swaminathan void *closure)
956*1fd5a2e1SPrashanth Swaminathan {
957*1fd5a2e1SPrashanth Swaminathan extended_cif ecif;
958*1fd5a2e1SPrashanth Swaminathan
959*1fd5a2e1SPrashanth Swaminathan ecif.cif = cif;
960*1fd5a2e1SPrashanth Swaminathan ecif.avalue = avalue;
961*1fd5a2e1SPrashanth Swaminathan
962*1fd5a2e1SPrashanth Swaminathan /* If the return value is a struct and we don't have a return
963*1fd5a2e1SPrashanth Swaminathan value address then we need to make one. */
964*1fd5a2e1SPrashanth Swaminathan
965*1fd5a2e1SPrashanth Swaminathan if ((rvalue == NULL) &&
966*1fd5a2e1SPrashanth Swaminathan (cif->rtype->type == FFI_TYPE_STRUCT))
967*1fd5a2e1SPrashanth Swaminathan {
968*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = alloca (cif->rtype->size);
969*1fd5a2e1SPrashanth Swaminathan }
970*1fd5a2e1SPrashanth Swaminathan else
971*1fd5a2e1SPrashanth Swaminathan ecif.rvalue = rvalue;
972*1fd5a2e1SPrashanth Swaminathan
973*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
974*1fd5a2e1SPrashanth Swaminathan {
975*1fd5a2e1SPrashanth Swaminathan case FFI_AIX:
976*1fd5a2e1SPrashanth Swaminathan ffi_call_go_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
977*1fd5a2e1SPrashanth Swaminathan FFI_FN(ffi_prep_args), closure);
978*1fd5a2e1SPrashanth Swaminathan break;
979*1fd5a2e1SPrashanth Swaminathan default:
980*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
981*1fd5a2e1SPrashanth Swaminathan break;
982*1fd5a2e1SPrashanth Swaminathan }
983*1fd5a2e1SPrashanth Swaminathan }
984*1fd5a2e1SPrashanth Swaminathan
985*1fd5a2e1SPrashanth Swaminathan static void flush_icache(char *);
986*1fd5a2e1SPrashanth Swaminathan static void flush_range(char *, int);
987*1fd5a2e1SPrashanth Swaminathan
988*1fd5a2e1SPrashanth Swaminathan /* The layout of a function descriptor. A C function pointer really
989*1fd5a2e1SPrashanth Swaminathan points to one of these. */
990*1fd5a2e1SPrashanth Swaminathan
991*1fd5a2e1SPrashanth Swaminathan typedef struct aix_fd_struct {
992*1fd5a2e1SPrashanth Swaminathan void *code_pointer;
993*1fd5a2e1SPrashanth Swaminathan void *toc;
994*1fd5a2e1SPrashanth Swaminathan } aix_fd;
995*1fd5a2e1SPrashanth Swaminathan
996*1fd5a2e1SPrashanth Swaminathan /* here I'd like to add the stack frame layout we use in darwin_closure.S
997*1fd5a2e1SPrashanth Swaminathan and aix_closure.S
998*1fd5a2e1SPrashanth Swaminathan
999*1fd5a2e1SPrashanth Swaminathan m32/m64
1000*1fd5a2e1SPrashanth Swaminathan
1001*1fd5a2e1SPrashanth Swaminathan The stack layout looks like this:
1002*1fd5a2e1SPrashanth Swaminathan
1003*1fd5a2e1SPrashanth Swaminathan | Additional params... | | Higher address
1004*1fd5a2e1SPrashanth Swaminathan ~ ~ ~
1005*1fd5a2e1SPrashanth Swaminathan | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS
1006*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1007*1fd5a2e1SPrashanth Swaminathan | TOC=R2 (AIX) Reserved (Darwin) 4/8 | |
1008*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1009*1fd5a2e1SPrashanth Swaminathan | Reserved 2*4/8 | |
1010*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1011*1fd5a2e1SPrashanth Swaminathan | Space for callee's LR 4/8 | |
1012*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1013*1fd5a2e1SPrashanth Swaminathan | Saved CR [low word for m64] 4/8 | |
1014*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1015*1fd5a2e1SPrashanth Swaminathan | Current backchain pointer 4/8 |-/ Parent's frame.
1016*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| <+ <<< on entry to ffi_closure_ASM
1017*1fd5a2e1SPrashanth Swaminathan | Result Bytes 16 | |
1018*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1019*1fd5a2e1SPrashanth Swaminathan ~ padding to 16-byte alignment ~ ~
1020*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1021*1fd5a2e1SPrashanth Swaminathan | NUM_FPR_ARG_REGISTERS slots | |
1022*1fd5a2e1SPrashanth Swaminathan | here fp13 .. fp1 13*8 | |
1023*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1024*1fd5a2e1SPrashanth Swaminathan | R3..R10 8*4/8=32/64 | | NUM_GPR_ARG_REGISTERS
1025*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| |
1026*1fd5a2e1SPrashanth Swaminathan | TOC=R2 (AIX) Reserved (Darwin) 4/8 | |
1027*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack |
1028*1fd5a2e1SPrashanth Swaminathan | Reserved [compiler,binder] 2*4/8 | | grows |
1029*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | down V
1030*1fd5a2e1SPrashanth Swaminathan | Space for callee's LR 4/8 | |
1031*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | lower addresses
1032*1fd5a2e1SPrashanth Swaminathan | Saved CR [low word for m64] 4/8 | |
1033*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| | stack pointer here
1034*1fd5a2e1SPrashanth Swaminathan | Current backchain pointer 4/8 |-/ during
1035*1fd5a2e1SPrashanth Swaminathan |--------------------------------------------| <<< ffi_closure_ASM.
1036*1fd5a2e1SPrashanth Swaminathan
1037*1fd5a2e1SPrashanth Swaminathan */
1038*1fd5a2e1SPrashanth Swaminathan
1039*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)1040*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
1041*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
1042*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
1043*1fd5a2e1SPrashanth Swaminathan void *user_data,
1044*1fd5a2e1SPrashanth Swaminathan void *codeloc)
1045*1fd5a2e1SPrashanth Swaminathan {
1046*1fd5a2e1SPrashanth Swaminathan unsigned int *tramp;
1047*1fd5a2e1SPrashanth Swaminathan struct ffi_aix_trampoline_struct *tramp_aix;
1048*1fd5a2e1SPrashanth Swaminathan aix_fd *fd;
1049*1fd5a2e1SPrashanth Swaminathan
1050*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
1051*1fd5a2e1SPrashanth Swaminathan {
1052*1fd5a2e1SPrashanth Swaminathan case FFI_DARWIN:
1053*1fd5a2e1SPrashanth Swaminathan
1054*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (cif->abi == FFI_DARWIN);
1055*1fd5a2e1SPrashanth Swaminathan
1056*1fd5a2e1SPrashanth Swaminathan tramp = (unsigned int *) &closure->tramp[0];
1057*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1058*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x7c0802a6; /* mflr r0 */
1059*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0x429f0015; /* bcl- 20,4*cr7+so, +0x18 (L1) */
1060*1fd5a2e1SPrashanth Swaminathan /* We put the addresses here. */
1061*1fd5a2e1SPrashanth Swaminathan tramp[6] = 0x7d6802a6; /*L1: mflr r11 */
1062*1fd5a2e1SPrashanth Swaminathan tramp[7] = 0xe98b0000; /* ld r12,0(r11) function address */
1063*1fd5a2e1SPrashanth Swaminathan tramp[8] = 0x7c0803a6; /* mtlr r0 */
1064*1fd5a2e1SPrashanth Swaminathan tramp[9] = 0x7d8903a6; /* mtctr r12 */
1065*1fd5a2e1SPrashanth Swaminathan tramp[10] = 0xe96b0008; /* lwz r11,8(r11) static chain */
1066*1fd5a2e1SPrashanth Swaminathan tramp[11] = 0x4e800420; /* bctr */
1067*1fd5a2e1SPrashanth Swaminathan
1068*1fd5a2e1SPrashanth Swaminathan *((unsigned long *)&tramp[2]) = (unsigned long) ffi_closure_ASM; /* function */
1069*1fd5a2e1SPrashanth Swaminathan *((unsigned long *)&tramp[4]) = (unsigned long) codeloc; /* context */
1070*1fd5a2e1SPrashanth Swaminathan #else
1071*1fd5a2e1SPrashanth Swaminathan tramp[0] = 0x7c0802a6; /* mflr r0 */
1072*1fd5a2e1SPrashanth Swaminathan tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
1073*1fd5a2e1SPrashanth Swaminathan tramp[4] = 0x7d6802a6; /* mflr r11 */
1074*1fd5a2e1SPrashanth Swaminathan tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
1075*1fd5a2e1SPrashanth Swaminathan tramp[6] = 0x7c0803a6; /* mtlr r0 */
1076*1fd5a2e1SPrashanth Swaminathan tramp[7] = 0x7d8903a6; /* mtctr r12 */
1077*1fd5a2e1SPrashanth Swaminathan tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
1078*1fd5a2e1SPrashanth Swaminathan tramp[9] = 0x4e800420; /* bctr */
1079*1fd5a2e1SPrashanth Swaminathan tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
1080*1fd5a2e1SPrashanth Swaminathan tramp[3] = (unsigned long) codeloc; /* context */
1081*1fd5a2e1SPrashanth Swaminathan #endif
1082*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
1083*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
1084*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
1085*1fd5a2e1SPrashanth Swaminathan
1086*1fd5a2e1SPrashanth Swaminathan /* Flush the icache. Only necessary on Darwin. */
1087*1fd5a2e1SPrashanth Swaminathan flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
1088*1fd5a2e1SPrashanth Swaminathan
1089*1fd5a2e1SPrashanth Swaminathan break;
1090*1fd5a2e1SPrashanth Swaminathan
1091*1fd5a2e1SPrashanth Swaminathan case FFI_AIX:
1092*1fd5a2e1SPrashanth Swaminathan
1093*1fd5a2e1SPrashanth Swaminathan tramp_aix = (struct ffi_aix_trampoline_struct *) (closure->tramp);
1094*1fd5a2e1SPrashanth Swaminathan fd = (aix_fd *)(void *)ffi_closure_ASM;
1095*1fd5a2e1SPrashanth Swaminathan
1096*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (cif->abi == FFI_AIX);
1097*1fd5a2e1SPrashanth Swaminathan
1098*1fd5a2e1SPrashanth Swaminathan tramp_aix->code_pointer = fd->code_pointer;
1099*1fd5a2e1SPrashanth Swaminathan tramp_aix->toc = fd->toc;
1100*1fd5a2e1SPrashanth Swaminathan tramp_aix->static_chain = codeloc;
1101*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
1102*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
1103*1fd5a2e1SPrashanth Swaminathan closure->user_data = user_data;
1104*1fd5a2e1SPrashanth Swaminathan break;
1105*1fd5a2e1SPrashanth Swaminathan
1106*1fd5a2e1SPrashanth Swaminathan default:
1107*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
1108*1fd5a2e1SPrashanth Swaminathan break;
1109*1fd5a2e1SPrashanth Swaminathan }
1110*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
1111*1fd5a2e1SPrashanth Swaminathan }
1112*1fd5a2e1SPrashanth Swaminathan
1113*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))1114*1fd5a2e1SPrashanth Swaminathan ffi_prep_go_closure (ffi_go_closure* closure,
1115*1fd5a2e1SPrashanth Swaminathan ffi_cif* cif,
1116*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*))
1117*1fd5a2e1SPrashanth Swaminathan {
1118*1fd5a2e1SPrashanth Swaminathan switch (cif->abi)
1119*1fd5a2e1SPrashanth Swaminathan {
1120*1fd5a2e1SPrashanth Swaminathan case FFI_AIX:
1121*1fd5a2e1SPrashanth Swaminathan
1122*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (cif->abi == FFI_AIX);
1123*1fd5a2e1SPrashanth Swaminathan
1124*1fd5a2e1SPrashanth Swaminathan closure->tramp = (void *)ffi_go_closure_ASM;
1125*1fd5a2e1SPrashanth Swaminathan closure->cif = cif;
1126*1fd5a2e1SPrashanth Swaminathan closure->fun = fun;
1127*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
1128*1fd5a2e1SPrashanth Swaminathan
1129*1fd5a2e1SPrashanth Swaminathan // For now, ffi_prep_go_closure is only implemented for AIX, not for Darwin
1130*1fd5a2e1SPrashanth Swaminathan default:
1131*1fd5a2e1SPrashanth Swaminathan return FFI_BAD_ABI;
1132*1fd5a2e1SPrashanth Swaminathan break;
1133*1fd5a2e1SPrashanth Swaminathan }
1134*1fd5a2e1SPrashanth Swaminathan return FFI_OK;
1135*1fd5a2e1SPrashanth Swaminathan }
1136*1fd5a2e1SPrashanth Swaminathan
1137*1fd5a2e1SPrashanth Swaminathan static void
flush_icache(char * addr)1138*1fd5a2e1SPrashanth Swaminathan flush_icache(char *addr)
1139*1fd5a2e1SPrashanth Swaminathan {
1140*1fd5a2e1SPrashanth Swaminathan #ifndef _AIX
1141*1fd5a2e1SPrashanth Swaminathan __asm__ volatile (
1142*1fd5a2e1SPrashanth Swaminathan "dcbf 0,%0\n"
1143*1fd5a2e1SPrashanth Swaminathan "\tsync\n"
1144*1fd5a2e1SPrashanth Swaminathan "\ticbi 0,%0\n"
1145*1fd5a2e1SPrashanth Swaminathan "\tsync\n"
1146*1fd5a2e1SPrashanth Swaminathan "\tisync"
1147*1fd5a2e1SPrashanth Swaminathan : : "r"(addr) : "memory");
1148*1fd5a2e1SPrashanth Swaminathan #endif
1149*1fd5a2e1SPrashanth Swaminathan }
1150*1fd5a2e1SPrashanth Swaminathan
1151*1fd5a2e1SPrashanth Swaminathan static void
flush_range(char * addr1,int size)1152*1fd5a2e1SPrashanth Swaminathan flush_range(char * addr1, int size)
1153*1fd5a2e1SPrashanth Swaminathan {
1154*1fd5a2e1SPrashanth Swaminathan #define MIN_LINE_SIZE 32
1155*1fd5a2e1SPrashanth Swaminathan int i;
1156*1fd5a2e1SPrashanth Swaminathan for (i = 0; i < size; i += MIN_LINE_SIZE)
1157*1fd5a2e1SPrashanth Swaminathan flush_icache(addr1+i);
1158*1fd5a2e1SPrashanth Swaminathan flush_icache(addr1+size-1);
1159*1fd5a2e1SPrashanth Swaminathan }
1160*1fd5a2e1SPrashanth Swaminathan
1161*1fd5a2e1SPrashanth Swaminathan typedef union
1162*1fd5a2e1SPrashanth Swaminathan {
1163*1fd5a2e1SPrashanth Swaminathan float f;
1164*1fd5a2e1SPrashanth Swaminathan double d;
1165*1fd5a2e1SPrashanth Swaminathan } ffi_dblfl;
1166*1fd5a2e1SPrashanth Swaminathan
1167*1fd5a2e1SPrashanth Swaminathan ffi_type *
1168*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_DARWIN (ffi_closure *, void *,
1169*1fd5a2e1SPrashanth Swaminathan unsigned long *, ffi_dblfl *);
1170*1fd5a2e1SPrashanth Swaminathan
1171*1fd5a2e1SPrashanth Swaminathan ffi_type *
1172*1fd5a2e1SPrashanth Swaminathan ffi_go_closure_helper_DARWIN (ffi_go_closure*, void *,
1173*1fd5a2e1SPrashanth Swaminathan unsigned long *, ffi_dblfl *);
1174*1fd5a2e1SPrashanth Swaminathan
1175*1fd5a2e1SPrashanth Swaminathan /* Basically the trampoline invokes ffi_closure_ASM, and on
1176*1fd5a2e1SPrashanth Swaminathan entry, r11 holds the address of the closure.
1177*1fd5a2e1SPrashanth Swaminathan After storing the registers that could possibly contain
1178*1fd5a2e1SPrashanth Swaminathan parameters to be passed into the stack frame and setting
1179*1fd5a2e1SPrashanth Swaminathan up space for a return value, ffi_closure_ASM invokes the
1180*1fd5a2e1SPrashanth Swaminathan following helper function to do most of the work. */
1181*1fd5a2e1SPrashanth Swaminathan
1182*1fd5a2e1SPrashanth Swaminathan static ffi_type *
ffi_closure_helper_common(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr)1183*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_common (ffi_cif* cif,
1184*1fd5a2e1SPrashanth Swaminathan void (*fun)(ffi_cif*, void*, void**, void*),
1185*1fd5a2e1SPrashanth Swaminathan void *user_data, void *rvalue,
1186*1fd5a2e1SPrashanth Swaminathan unsigned long *pgr, ffi_dblfl *pfr)
1187*1fd5a2e1SPrashanth Swaminathan {
1188*1fd5a2e1SPrashanth Swaminathan /* rvalue is the pointer to space for return value in closure assembly
1189*1fd5a2e1SPrashanth Swaminathan pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM
1190*1fd5a2e1SPrashanth Swaminathan pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */
1191*1fd5a2e1SPrashanth Swaminathan
1192*1fd5a2e1SPrashanth Swaminathan typedef double ldbits[2];
1193*1fd5a2e1SPrashanth Swaminathan
1194*1fd5a2e1SPrashanth Swaminathan union ldu
1195*1fd5a2e1SPrashanth Swaminathan {
1196*1fd5a2e1SPrashanth Swaminathan ldbits lb;
1197*1fd5a2e1SPrashanth Swaminathan long double ld;
1198*1fd5a2e1SPrashanth Swaminathan };
1199*1fd5a2e1SPrashanth Swaminathan
1200*1fd5a2e1SPrashanth Swaminathan void ** avalue;
1201*1fd5a2e1SPrashanth Swaminathan ffi_type ** arg_types;
1202*1fd5a2e1SPrashanth Swaminathan long i, avn;
1203*1fd5a2e1SPrashanth Swaminathan ffi_dblfl * end_pfr = pfr + NUM_FPR_ARG_REGISTERS;
1204*1fd5a2e1SPrashanth Swaminathan unsigned size_al;
1205*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1206*1fd5a2e1SPrashanth Swaminathan unsigned fpsused = 0;
1207*1fd5a2e1SPrashanth Swaminathan #endif
1208*1fd5a2e1SPrashanth Swaminathan
1209*1fd5a2e1SPrashanth Swaminathan avalue = alloca (cif->nargs * sizeof(void *));
1210*1fd5a2e1SPrashanth Swaminathan
1211*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->type == FFI_TYPE_STRUCT)
1212*1fd5a2e1SPrashanth Swaminathan {
1213*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1214*1fd5a2e1SPrashanth Swaminathan if (!darwin64_struct_ret_by_value_p (cif->rtype))
1215*1fd5a2e1SPrashanth Swaminathan {
1216*1fd5a2e1SPrashanth Swaminathan /* Won't fit into the regs - return by ref. */
1217*1fd5a2e1SPrashanth Swaminathan rvalue = (void *) *pgr;
1218*1fd5a2e1SPrashanth Swaminathan pgr++;
1219*1fd5a2e1SPrashanth Swaminathan }
1220*1fd5a2e1SPrashanth Swaminathan #elif defined(DARWIN_PPC)
1221*1fd5a2e1SPrashanth Swaminathan if (cif->rtype->size > 4)
1222*1fd5a2e1SPrashanth Swaminathan {
1223*1fd5a2e1SPrashanth Swaminathan rvalue = (void *) *pgr;
1224*1fd5a2e1SPrashanth Swaminathan pgr++;
1225*1fd5a2e1SPrashanth Swaminathan }
1226*1fd5a2e1SPrashanth Swaminathan #else /* assume we return by ref. */
1227*1fd5a2e1SPrashanth Swaminathan rvalue = (void *) *pgr;
1228*1fd5a2e1SPrashanth Swaminathan pgr++;
1229*1fd5a2e1SPrashanth Swaminathan #endif
1230*1fd5a2e1SPrashanth Swaminathan }
1231*1fd5a2e1SPrashanth Swaminathan
1232*1fd5a2e1SPrashanth Swaminathan i = 0;
1233*1fd5a2e1SPrashanth Swaminathan avn = cif->nargs;
1234*1fd5a2e1SPrashanth Swaminathan arg_types = cif->arg_types;
1235*1fd5a2e1SPrashanth Swaminathan
1236*1fd5a2e1SPrashanth Swaminathan /* Grab the addresses of the arguments from the stack frame. */
1237*1fd5a2e1SPrashanth Swaminathan while (i < avn)
1238*1fd5a2e1SPrashanth Swaminathan {
1239*1fd5a2e1SPrashanth Swaminathan switch (arg_types[i]->type)
1240*1fd5a2e1SPrashanth Swaminathan {
1241*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT8:
1242*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT8:
1243*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC64)
1244*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 7;
1245*1fd5a2e1SPrashanth Swaminathan #else
1246*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 3;
1247*1fd5a2e1SPrashanth Swaminathan #endif
1248*1fd5a2e1SPrashanth Swaminathan pgr++;
1249*1fd5a2e1SPrashanth Swaminathan break;
1250*1fd5a2e1SPrashanth Swaminathan
1251*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT16:
1252*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT16:
1253*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC64)
1254*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 6;
1255*1fd5a2e1SPrashanth Swaminathan #else
1256*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 2;
1257*1fd5a2e1SPrashanth Swaminathan #endif
1258*1fd5a2e1SPrashanth Swaminathan pgr++;
1259*1fd5a2e1SPrashanth Swaminathan break;
1260*1fd5a2e1SPrashanth Swaminathan
1261*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT32:
1262*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT32:
1263*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC64)
1264*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char *) pgr + 4;
1265*1fd5a2e1SPrashanth Swaminathan #else
1266*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
1267*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1268*1fd5a2e1SPrashanth Swaminathan #endif
1269*1fd5a2e1SPrashanth Swaminathan pgr++;
1270*1fd5a2e1SPrashanth Swaminathan break;
1271*1fd5a2e1SPrashanth Swaminathan
1272*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_STRUCT:
1273*1fd5a2e1SPrashanth Swaminathan size_al = arg_types[i]->size;
1274*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC_DARWIN64)
1275*1fd5a2e1SPrashanth Swaminathan pgr = (unsigned long *)FFI_ALIGN((char *)pgr, arg_types[i]->alignment);
1276*1fd5a2e1SPrashanth Swaminathan if (size_al < 3 || size_al == 4)
1277*1fd5a2e1SPrashanth Swaminathan {
1278*1fd5a2e1SPrashanth Swaminathan avalue[i] = ((char *)pgr)+8-size_al;
1279*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT
1280*1fd5a2e1SPrashanth Swaminathan && fpsused < NUM_FPR_ARG_REGISTERS)
1281*1fd5a2e1SPrashanth Swaminathan {
1282*1fd5a2e1SPrashanth Swaminathan *(float *)pgr = (float) *(double *)pfr;
1283*1fd5a2e1SPrashanth Swaminathan pfr++;
1284*1fd5a2e1SPrashanth Swaminathan fpsused++;
1285*1fd5a2e1SPrashanth Swaminathan }
1286*1fd5a2e1SPrashanth Swaminathan }
1287*1fd5a2e1SPrashanth Swaminathan else
1288*1fd5a2e1SPrashanth Swaminathan {
1289*1fd5a2e1SPrashanth Swaminathan if (size_al != 16)
1290*1fd5a2e1SPrashanth Swaminathan pfr = (ffi_dblfl *)
1291*1fd5a2e1SPrashanth Swaminathan darwin64_struct_floats_to_mem (arg_types[i], (char *)pgr,
1292*1fd5a2e1SPrashanth Swaminathan (double *)pfr, &fpsused);
1293*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1294*1fd5a2e1SPrashanth Swaminathan }
1295*1fd5a2e1SPrashanth Swaminathan pgr += (size_al + 7) / 8;
1296*1fd5a2e1SPrashanth Swaminathan #else
1297*1fd5a2e1SPrashanth Swaminathan /* If the first member of the struct is a double, then align
1298*1fd5a2e1SPrashanth Swaminathan the struct to double-word. */
1299*1fd5a2e1SPrashanth Swaminathan if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
1300*1fd5a2e1SPrashanth Swaminathan size_al = FFI_ALIGN(arg_types[i]->size, 8);
1301*1fd5a2e1SPrashanth Swaminathan # if defined(POWERPC64)
1302*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT (cif->abi != FFI_DARWIN);
1303*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1304*1fd5a2e1SPrashanth Swaminathan pgr += (size_al + 7) / 8;
1305*1fd5a2e1SPrashanth Swaminathan # else
1306*1fd5a2e1SPrashanth Swaminathan /* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
1307*1fd5a2e1SPrashanth Swaminathan SI 4 bytes) are aligned as if they were those modes. */
1308*1fd5a2e1SPrashanth Swaminathan if (size_al < 3 && cif->abi == FFI_DARWIN)
1309*1fd5a2e1SPrashanth Swaminathan avalue[i] = (char*) pgr + 4 - size_al;
1310*1fd5a2e1SPrashanth Swaminathan else
1311*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1312*1fd5a2e1SPrashanth Swaminathan pgr += (size_al + 3) / 4;
1313*1fd5a2e1SPrashanth Swaminathan # endif
1314*1fd5a2e1SPrashanth Swaminathan #endif
1315*1fd5a2e1SPrashanth Swaminathan break;
1316*1fd5a2e1SPrashanth Swaminathan
1317*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_SINT64:
1318*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_UINT64:
1319*1fd5a2e1SPrashanth Swaminathan #if defined(POWERPC64)
1320*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_POINTER:
1321*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1322*1fd5a2e1SPrashanth Swaminathan pgr++;
1323*1fd5a2e1SPrashanth Swaminathan break;
1324*1fd5a2e1SPrashanth Swaminathan #else
1325*1fd5a2e1SPrashanth Swaminathan /* Long long ints are passed in two gpr's. */
1326*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1327*1fd5a2e1SPrashanth Swaminathan pgr += 2;
1328*1fd5a2e1SPrashanth Swaminathan break;
1329*1fd5a2e1SPrashanth Swaminathan #endif
1330*1fd5a2e1SPrashanth Swaminathan
1331*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_FLOAT:
1332*1fd5a2e1SPrashanth Swaminathan /* A float value consumes a GPR.
1333*1fd5a2e1SPrashanth Swaminathan There are 13 64bit floating point registers. */
1334*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr)
1335*1fd5a2e1SPrashanth Swaminathan {
1336*1fd5a2e1SPrashanth Swaminathan double temp = pfr->d;
1337*1fd5a2e1SPrashanth Swaminathan pfr->f = (float) temp;
1338*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1339*1fd5a2e1SPrashanth Swaminathan pfr++;
1340*1fd5a2e1SPrashanth Swaminathan }
1341*1fd5a2e1SPrashanth Swaminathan else
1342*1fd5a2e1SPrashanth Swaminathan {
1343*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1344*1fd5a2e1SPrashanth Swaminathan }
1345*1fd5a2e1SPrashanth Swaminathan pgr++;
1346*1fd5a2e1SPrashanth Swaminathan break;
1347*1fd5a2e1SPrashanth Swaminathan
1348*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_DOUBLE:
1349*1fd5a2e1SPrashanth Swaminathan /* A double value consumes two GPRs.
1350*1fd5a2e1SPrashanth Swaminathan There are 13 64bit floating point registers. */
1351*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr)
1352*1fd5a2e1SPrashanth Swaminathan {
1353*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1354*1fd5a2e1SPrashanth Swaminathan pfr++;
1355*1fd5a2e1SPrashanth Swaminathan }
1356*1fd5a2e1SPrashanth Swaminathan else
1357*1fd5a2e1SPrashanth Swaminathan {
1358*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1359*1fd5a2e1SPrashanth Swaminathan }
1360*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
1361*1fd5a2e1SPrashanth Swaminathan pgr++;
1362*1fd5a2e1SPrashanth Swaminathan #else
1363*1fd5a2e1SPrashanth Swaminathan pgr += 2;
1364*1fd5a2e1SPrashanth Swaminathan #endif
1365*1fd5a2e1SPrashanth Swaminathan break;
1366*1fd5a2e1SPrashanth Swaminathan
1367*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1368*1fd5a2e1SPrashanth Swaminathan
1369*1fd5a2e1SPrashanth Swaminathan case FFI_TYPE_LONGDOUBLE:
1370*1fd5a2e1SPrashanth Swaminathan #ifdef POWERPC64
1371*1fd5a2e1SPrashanth Swaminathan if (pfr + 1 < end_pfr)
1372*1fd5a2e1SPrashanth Swaminathan {
1373*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1374*1fd5a2e1SPrashanth Swaminathan pfr += 2;
1375*1fd5a2e1SPrashanth Swaminathan }
1376*1fd5a2e1SPrashanth Swaminathan else
1377*1fd5a2e1SPrashanth Swaminathan {
1378*1fd5a2e1SPrashanth Swaminathan if (pfr < end_pfr)
1379*1fd5a2e1SPrashanth Swaminathan {
1380*1fd5a2e1SPrashanth Swaminathan *pgr = *(unsigned long *) pfr;
1381*1fd5a2e1SPrashanth Swaminathan pfr++;
1382*1fd5a2e1SPrashanth Swaminathan }
1383*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1384*1fd5a2e1SPrashanth Swaminathan }
1385*1fd5a2e1SPrashanth Swaminathan pgr += 2;
1386*1fd5a2e1SPrashanth Swaminathan #else /* POWERPC64 */
1387*1fd5a2e1SPrashanth Swaminathan /* A long double value consumes four GPRs and two FPRs.
1388*1fd5a2e1SPrashanth Swaminathan There are 13 64bit floating point registers. */
1389*1fd5a2e1SPrashanth Swaminathan if (pfr + 1 < end_pfr)
1390*1fd5a2e1SPrashanth Swaminathan {
1391*1fd5a2e1SPrashanth Swaminathan avalue[i] = pfr;
1392*1fd5a2e1SPrashanth Swaminathan pfr += 2;
1393*1fd5a2e1SPrashanth Swaminathan }
1394*1fd5a2e1SPrashanth Swaminathan /* Here we have the situation where one part of the long double
1395*1fd5a2e1SPrashanth Swaminathan is stored in fpr13 and the other part is already on the stack.
1396*1fd5a2e1SPrashanth Swaminathan We use a union to pass the long double to avalue[i]. */
1397*1fd5a2e1SPrashanth Swaminathan else if (pfr + 1 == end_pfr)
1398*1fd5a2e1SPrashanth Swaminathan {
1399*1fd5a2e1SPrashanth Swaminathan union ldu temp_ld;
1400*1fd5a2e1SPrashanth Swaminathan memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
1401*1fd5a2e1SPrashanth Swaminathan memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
1402*1fd5a2e1SPrashanth Swaminathan avalue[i] = &temp_ld.ld;
1403*1fd5a2e1SPrashanth Swaminathan pfr++;
1404*1fd5a2e1SPrashanth Swaminathan }
1405*1fd5a2e1SPrashanth Swaminathan else
1406*1fd5a2e1SPrashanth Swaminathan {
1407*1fd5a2e1SPrashanth Swaminathan avalue[i] = pgr;
1408*1fd5a2e1SPrashanth Swaminathan }
1409*1fd5a2e1SPrashanth Swaminathan pgr += 4;
1410*1fd5a2e1SPrashanth Swaminathan #endif /* POWERPC64 */
1411*1fd5a2e1SPrashanth Swaminathan break;
1412*1fd5a2e1SPrashanth Swaminathan #endif
1413*1fd5a2e1SPrashanth Swaminathan default:
1414*1fd5a2e1SPrashanth Swaminathan FFI_ASSERT(0);
1415*1fd5a2e1SPrashanth Swaminathan }
1416*1fd5a2e1SPrashanth Swaminathan i++;
1417*1fd5a2e1SPrashanth Swaminathan }
1418*1fd5a2e1SPrashanth Swaminathan
1419*1fd5a2e1SPrashanth Swaminathan (fun) (cif, rvalue, avalue, user_data);
1420*1fd5a2e1SPrashanth Swaminathan
1421*1fd5a2e1SPrashanth Swaminathan /* Tell ffi_closure_ASM to perform return type promotions. */
1422*1fd5a2e1SPrashanth Swaminathan return cif->rtype;
1423*1fd5a2e1SPrashanth Swaminathan }
1424*1fd5a2e1SPrashanth Swaminathan
1425*1fd5a2e1SPrashanth Swaminathan ffi_type *
ffi_closure_helper_DARWIN(ffi_closure * closure,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr)1426*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
1427*1fd5a2e1SPrashanth Swaminathan unsigned long *pgr, ffi_dblfl *pfr)
1428*1fd5a2e1SPrashanth Swaminathan {
1429*1fd5a2e1SPrashanth Swaminathan return ffi_closure_helper_common (closure->cif, closure->fun,
1430*1fd5a2e1SPrashanth Swaminathan closure->user_data, rvalue, pgr, pfr);
1431*1fd5a2e1SPrashanth Swaminathan }
1432*1fd5a2e1SPrashanth Swaminathan
1433*1fd5a2e1SPrashanth Swaminathan ffi_type *
ffi_go_closure_helper_DARWIN(ffi_go_closure * closure,void * rvalue,unsigned long * pgr,ffi_dblfl * pfr)1434*1fd5a2e1SPrashanth Swaminathan ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue,
1435*1fd5a2e1SPrashanth Swaminathan unsigned long *pgr, ffi_dblfl *pfr)
1436*1fd5a2e1SPrashanth Swaminathan {
1437*1fd5a2e1SPrashanth Swaminathan return ffi_closure_helper_common (closure->cif, closure->fun,
1438*1fd5a2e1SPrashanth Swaminathan closure, rvalue, pgr, pfr);
1439*1fd5a2e1SPrashanth Swaminathan }
1440*1fd5a2e1SPrashanth Swaminathan
1441