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