1/*	Area:			ffi_call, closure_call
2	Purpose:		Check large structure returns.
3	Limitations:	none.
4	PR:				none.
5	Originator:		Blake Chaffin	6/18/2007
6*/
7
8/* { dg-do run { xfail mips*-*-* arm*-*-* strongarm*-*-* xscale*-*-* } } */
9/* { dg-options -mlong-double-128 { target powerpc64*-*-* } } */
10
11#include <stdint.h>
12
13#include "ffitest.h"
14
15typedef	struct BigStruct{
16	uint8_t		a;
17	int8_t		b;
18	uint16_t	c;
19	int16_t		d;
20	uint32_t	e;
21	int32_t		f;
22	uint64_t	g;
23	int64_t		h;
24	float		i;
25	double		j;
26	long double	k;
27	char*		l;
28	uint8_t		m;
29	int8_t		n;
30	uint16_t	o;
31	int16_t		p;
32	uint32_t	q;
33	int32_t		r;
34	uint64_t	s;
35	int64_t		t;
36	float		u;
37	double		v;
38	long double	w;
39	char*		x;
40	uint8_t		y;
41	int8_t		z;
42	uint16_t	aa;
43	int16_t		bb;
44	uint32_t	cc;
45	int32_t		dd;
46	uint64_t	ee;
47	int64_t		ff;
48	float		gg;
49	double		hh;
50	long double	ii;
51	char*		jj;
52	uint8_t		kk;
53	int8_t		ll;
54	uint16_t	mm;
55	int16_t		nn;
56	uint32_t	oo;
57	int32_t		pp;
58	uint64_t	qq;
59	int64_t		rr;
60	float		ss;
61	double		tt;
62	long double	uu;
63	char*		vv;
64	uint8_t		ww;
65	int8_t		xx;
66} BigStruct;
67
68BigStruct
69test_large_fn(
70	uint8_t		ui8_1,
71	int8_t		si8_1,
72	uint16_t	ui16_1,
73	int16_t		si16_1,
74	uint32_t	ui32_1,
75	int32_t		si32_1,
76	uint64_t	ui64_1,
77	int64_t		si64_1,
78	float		f_1,
79	double		d_1,
80	long double	ld_1,
81	char*		p_1,
82	uint8_t		ui8_2,
83	int8_t		si8_2,
84	uint16_t	ui16_2,
85	int16_t		si16_2,
86	uint32_t	ui32_2,
87	int32_t		si32_2,
88	uint64_t	ui64_2,
89	int64_t		si64_2,
90	float		f_2,
91	double		d_2,
92	long double	ld_2,
93	char*		p_2,
94	uint8_t		ui8_3,
95	int8_t		si8_3,
96	uint16_t	ui16_3,
97	int16_t		si16_3,
98	uint32_t	ui32_3,
99	int32_t		si32_3,
100	uint64_t	ui64_3,
101	int64_t		si64_3,
102	float		f_3,
103	double		d_3,
104	long double	ld_3,
105	char*		p_3,
106	uint8_t		ui8_4,
107	int8_t		si8_4,
108	uint16_t	ui16_4,
109	int16_t		si16_4,
110	uint32_t	ui32_4,
111	int32_t		si32_4,
112	uint64_t	ui64_4,
113	int64_t		si64_4,
114	float		f_4,
115	double		d_4,
116	long double	ld_4,
117	char*		p_4,
118	uint8_t		ui8_5,
119	int8_t		si8_5)
120{
121	BigStruct	retVal	= {
122		ui8_1 + 1, si8_1 + 1, ui16_1 + 1, si16_1 + 1, ui32_1 + 1, si32_1 + 1,
123			ui64_1 + 1, si64_1 + 1, f_1 + 1, d_1 + 1, ld_1 + 1, (char*)((long)p_1 + 1),
124		ui8_2 + 2, si8_2 + 2, ui16_2 + 2, si16_2 + 2, ui32_2 + 2, si32_2 + 2,
125			ui64_2 + 2, si64_2 + 2, f_2 + 2, d_2 + 2, ld_2 + 2, (char*)((long)p_2 + 2),
126		ui8_3 + 3, si8_3 + 3, ui16_3 + 3, si16_3 + 3, ui32_3 + 3, si32_3 + 3,
127			ui64_3 + 3, si64_3 + 3, f_3 + 3, d_3 + 3, ld_3 + 3, (char*)((long)p_3 + 3),
128		ui8_4 + 4, si8_4 + 4, ui16_4 + 4, si16_4 + 4, ui32_4 + 4, si32_4 + 4,
129			ui64_4 + 4, si64_4 + 4, f_4 + 4, d_4 + 4, ld_4 + 4, (char*)((long)p_4 + 4),
130		ui8_5 + 5, si8_5 + 5};
131
132	printf("%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
133		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
134		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
135		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd: "
136		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
137		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
138		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
139		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd\n",
140		ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
141		ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
142		ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
143		ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4, ui8_5, si8_5,
144		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
145		retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, retVal.l,
146		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
147		retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, retVal.x,
148		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
149		retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, retVal.jj,
150		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
151		retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, retVal.vv, retVal.ww, retVal.xx);
152
153	return	retVal;
154}
155
156static void
157cls_large_fn(ffi_cif* cif, void* resp, void** args, void* userdata)
158{
159	uint8_t		ui8_1	= *(uint8_t*)args[0];
160	int8_t		si8_1	= *(int8_t*)args[1];
161	uint16_t	ui16_1	= *(uint16_t*)args[2];
162	int16_t		si16_1	= *(int16_t*)args[3];
163	uint32_t	ui32_1	= *(uint32_t*)args[4];
164	int32_t		si32_1	= *(int32_t*)args[5];
165	uint64_t	ui64_1	= *(uint64_t*)args[6];
166	int64_t		si64_1	= *(int64_t*)args[7];
167	float		f_1		= *(float*)args[8];
168	double		d_1		= *(double*)args[9];
169	long double	ld_1	= *(long double*)args[10];
170	char*		p_1		= *(char**)args[11];
171	uint8_t		ui8_2	= *(uint8_t*)args[12];
172	int8_t		si8_2	= *(int8_t*)args[13];
173	uint16_t	ui16_2	= *(uint16_t*)args[14];
174	int16_t		si16_2	= *(int16_t*)args[15];
175	uint32_t	ui32_2	= *(uint32_t*)args[16];
176	int32_t		si32_2	= *(int32_t*)args[17];
177	uint64_t	ui64_2	= *(uint64_t*)args[18];
178	int64_t		si64_2	= *(int64_t*)args[19];
179	float		f_2		= *(float*)args[20];
180	double		d_2		= *(double*)args[21];
181	long double	ld_2	= *(long double*)args[22];
182	char*		p_2		= *(char**)args[23];
183	uint8_t		ui8_3	= *(uint8_t*)args[24];
184	int8_t		si8_3	= *(int8_t*)args[25];
185	uint16_t	ui16_3	= *(uint16_t*)args[26];
186	int16_t		si16_3	= *(int16_t*)args[27];
187	uint32_t	ui32_3	= *(uint32_t*)args[28];
188	int32_t		si32_3	= *(int32_t*)args[29];
189	uint64_t	ui64_3	= *(uint64_t*)args[30];
190	int64_t		si64_3	= *(int64_t*)args[31];
191	float		f_3		= *(float*)args[32];
192	double		d_3		= *(double*)args[33];
193	long double	ld_3	= *(long double*)args[34];
194	char*		p_3		= *(char**)args[35];
195	uint8_t		ui8_4	= *(uint8_t*)args[36];
196	int8_t		si8_4	= *(int8_t*)args[37];
197	uint16_t	ui16_4	= *(uint16_t*)args[38];
198	int16_t		si16_4	= *(int16_t*)args[39];
199	uint32_t	ui32_4	= *(uint32_t*)args[40];
200	int32_t		si32_4	= *(int32_t*)args[41];
201	uint64_t	ui64_4	= *(uint64_t*)args[42];
202	int64_t		si64_4	= *(int64_t*)args[43];
203	float		f_4		= *(float*)args[44];
204	double		d_4		= *(double*)args[45];
205	long double	ld_4	= *(long double*)args[46];
206	char*		p_4		= *(char**)args[47];
207	uint8_t		ui8_5	= *(uint8_t*)args[48];
208	int8_t		si8_5	= *(int8_t*)args[49];
209
210	*(BigStruct*)resp = test_large_fn(
211		ui8_1, si8_1, ui16_1, si16_1, ui32_1, si32_1, ui64_1, si64_1, f_1, d_1, ld_1, p_1,
212		ui8_2, si8_2, ui16_2, si16_2, ui32_2, si32_2, ui64_2, si64_2, f_2, d_2, ld_2, p_2,
213		ui8_3, si8_3, ui16_3, si16_3, ui32_3, si32_3, ui64_3, si64_3, f_3, d_3, ld_3, p_3,
214		ui8_4, si8_4, ui16_4, si16_4, ui32_4, si32_4, ui64_4, si64_4, f_4, d_4, ld_4, p_4,
215		ui8_5, si8_5);
216}
217
218int
219main(int argc, const char** argv)
220{
221#ifndef USING_MMAP
222	static ffi_closure cl;
223#endif
224	ffi_closure *pcl;
225
226#ifdef USING_MMAP
227	pcl = allocate_mmap(sizeof(ffi_closure));
228#else
229	pcl = &cl;
230#endif
231
232	ffi_cif		cif;
233	ffi_type*	argTypes[51];
234	void*		argValues[51];
235
236	ffi_type	ret_struct_type;
237	ffi_type*	st_fields[51];
238	BigStruct	retVal	= {0};
239
240	ret_struct_type.size = 0;
241	ret_struct_type.alignment = 0;
242	ret_struct_type.type = FFI_TYPE_STRUCT;
243	ret_struct_type.elements = st_fields;
244
245	st_fields[0]	= st_fields[12]	= st_fields[24]	= st_fields[36]	= st_fields[48]	= &ffi_type_uint8;
246	st_fields[1]	= st_fields[13]	= st_fields[25]	= st_fields[37]	= st_fields[49]	= &ffi_type_sint8;
247	st_fields[2]	= st_fields[14]	= st_fields[26]	= st_fields[38]	= &ffi_type_uint16;
248	st_fields[3]	= st_fields[15]	= st_fields[27]	= st_fields[39]	= &ffi_type_sint16;
249	st_fields[4]	= st_fields[16]	= st_fields[28]	= st_fields[40]	= &ffi_type_uint32;
250	st_fields[5]	= st_fields[17]	= st_fields[29]	= st_fields[41]	= &ffi_type_sint32;
251	st_fields[6]	= st_fields[18]	= st_fields[30]	= st_fields[42]	= &ffi_type_uint64;
252	st_fields[7]	= st_fields[19]	= st_fields[31]	= st_fields[43]	= &ffi_type_sint64;
253	st_fields[8]	= st_fields[20]	= st_fields[32]	= st_fields[44]	= &ffi_type_float;
254	st_fields[9]	= st_fields[21]	= st_fields[33]	= st_fields[45]	= &ffi_type_double;
255	st_fields[10]	= st_fields[22]	= st_fields[34]	= st_fields[46]	= &ffi_type_longdouble;
256	st_fields[11]	= st_fields[23]	= st_fields[35]	= st_fields[47]	= &ffi_type_pointer;
257
258	st_fields[50] = NULL;
259
260	uint8_t		ui8		= 1;
261	int8_t		si8		= 2;
262	uint16_t	ui16	= 3;
263	int16_t		si16	= 4;
264	uint32_t	ui32	= 5;
265	int32_t		si32	= 6;
266	uint64_t	ui64	= 7;
267	int64_t		si64	= 8;
268	float		f		= 9;
269	double		d		= 10;
270	long double	ld		= 11;
271	char*		p		= (char*)0x12345678;
272
273	argTypes[0]		= argTypes[12]	= argTypes[24]	= argTypes[36]	= argTypes[48]	= &ffi_type_uint8;
274	argValues[0]	= argValues[12]	= argValues[24]	= argValues[36]	= argValues[48]	= &ui8;
275	argTypes[1]		= argTypes[13]	= argTypes[25]	= argTypes[37]	= argTypes[49]	= &ffi_type_sint8;
276	argValues[1]	= argValues[13]	= argValues[25]	= argValues[37]	= argValues[49]	= &si8;
277	argTypes[2]		= argTypes[14]	= argTypes[26]	= argTypes[38]	= &ffi_type_uint16;
278	argValues[2]	= argValues[14]	= argValues[26]	= argValues[38]	= &ui16;
279	argTypes[3]		= argTypes[15]	= argTypes[27]	= argTypes[39]	= &ffi_type_sint16;
280	argValues[3]	= argValues[15]	= argValues[27]	= argValues[39]	= &si16;
281	argTypes[4]		= argTypes[16]	= argTypes[28]	= argTypes[40]	= &ffi_type_uint32;
282	argValues[4]	= argValues[16]	= argValues[28]	= argValues[40]	= &ui32;
283	argTypes[5]		= argTypes[17]	= argTypes[29]	= argTypes[41]	= &ffi_type_sint32;
284	argValues[5]	= argValues[17]	= argValues[29]	= argValues[41]	= &si32;
285	argTypes[6]		= argTypes[18]	= argTypes[30]	= argTypes[42]	= &ffi_type_uint64;
286	argValues[6]	= argValues[18]	= argValues[30]	= argValues[42]	= &ui64;
287	argTypes[7]		= argTypes[19]	= argTypes[31]	= argTypes[43]	= &ffi_type_sint64;
288	argValues[7]	= argValues[19]	= argValues[31]	= argValues[43]	= &si64;
289	argTypes[8]		= argTypes[20]	= argTypes[32]	= argTypes[44]	= &ffi_type_float;
290	argValues[8]	= argValues[20]	= argValues[32]	= argValues[44]	= &f;
291	argTypes[9]		= argTypes[21]	= argTypes[33]	= argTypes[45]	= &ffi_type_double;
292	argValues[9]	= argValues[21]	= argValues[33]	= argValues[45]	= &d;
293	argTypes[10]	= argTypes[22]	= argTypes[34]	= argTypes[46]	= &ffi_type_longdouble;
294	argValues[10]	= argValues[22]	= argValues[34]	= argValues[46]	= &ld;
295	argTypes[11]	= argTypes[23]	= argTypes[35]	= argTypes[47]	= &ffi_type_pointer;
296	argValues[11]	= argValues[23]	= argValues[35]	= argValues[47]	= &p;
297
298	argTypes[50]	= NULL;
299	argValues[50]	= NULL;
300
301	CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 50, &ret_struct_type, argTypes) == FFI_OK);
302
303	ffi_call(&cif, FFI_FN(test_large_fn), &retVal, argValues);
304	// { dg-output "1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
305	printf("res: %hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
306		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
307		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
308		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd\n",
309		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
310		retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, retVal.l,
311		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
312		retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, retVal.x,
313		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
314		retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, retVal.jj,
315		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
316		retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, retVal.vv, retVal.ww, retVal.xx);
317	// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
318
319	CHECK(ffi_prep_closure(pcl, &cif, cls_large_fn, NULL) == FFI_OK);
320
321	retVal	= ((BigStruct(*)(
322		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
323		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
324		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
325		uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t, float, double, long double, char*,
326		uint8_t, int8_t))(pcl))(
327		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
328		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
329		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
330		ui8, si8, ui16, si16, ui32, si32, ui64, si64, f, d, ld, p,
331		ui8, si8);
332	// { dg-output "\n1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2 3 4 5 6 7 8 9 10 11 0x12345678 1 2: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
333	printf("res: %hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
334		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
335		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p "
336		"%hhu %hhd %hu %hd %u %d %llu %lld %.0f %.0f %L.0f %p %hhu %hhd\n",
337		retVal.a, retVal.b, retVal.c, retVal.d, retVal.e, retVal.f,
338		retVal.g, retVal.h, retVal.i, retVal.j, retVal.k, retVal.l,
339		retVal.m, retVal.n, retVal.o, retVal.p, retVal.q, retVal.r,
340		retVal.s, retVal.t, retVal.u, retVal.v, retVal.w, retVal.x,
341		retVal.y, retVal.z, retVal.aa, retVal.bb, retVal.cc, retVal.dd,
342		retVal.ee, retVal.ff, retVal.gg, retVal.hh, retVal.ii, retVal.jj,
343		retVal.kk, retVal.ll, retVal.mm, retVal.nn, retVal.oo, retVal.pp,
344		retVal.qq, retVal.rr, retVal.ss, retVal.tt, retVal.uu, retVal.vv, retVal.ww, retVal.xx);
345	// { dg-output "\nres: 2 3 4 5 6 7 8 9 10 11 12 0x12345679 3 4 5 6 7 8 9 10 11 12 13 0x1234567a 4 5 6 7 8 9 10 11 12 13 14 0x1234567b 5 6 7 8 9 10 11 12 13 14 15 0x1234567c 6 7" }
346
347    return 0;
348}
349