1 | /* -----------------------------------------------------------------------
|
---|
2 | ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
|
---|
3 |
|
---|
4 | Permission is hereby granted, free of charge, to any person obtaining
|
---|
5 | a copy of this software and associated documentation files (the
|
---|
6 | ``Software''), to deal in the Software without restriction, including
|
---|
7 | without limitation the rights to use, copy, modify, merge, publish,
|
---|
8 | distribute, sublicense, and/or sell copies of the Software, and to
|
---|
9 | permit persons to whom the Software is furnished to do so, subject to
|
---|
10 | the following conditions:
|
---|
11 |
|
---|
12 | The above copyright notice and this permission notice shall be included
|
---|
13 | in all copies or substantial portions of the Software.
|
---|
14 |
|
---|
15 | THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
---|
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
---|
18 | IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
---|
19 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
---|
20 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
21 | OTHER DEALINGS IN THE SOFTWARE.
|
---|
22 | ----------------------------------------------------------------------- */
|
---|
23 |
|
---|
24 | #include <ffi.h>
|
---|
25 | #include <stdio.h>
|
---|
26 | #include <stdlib.h>
|
---|
27 | #include <string.h>
|
---|
28 | #include <float.h>
|
---|
29 |
|
---|
30 | /* This is lame. Long double support is barely there under SunOS 4.x */
|
---|
31 | #if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
|
---|
32 | #define BROKEN_LONG_DOUBLE
|
---|
33 | #endif
|
---|
34 |
|
---|
35 | #define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
|
---|
36 |
|
---|
37 | static int fail(char *file, int line)
|
---|
38 | {
|
---|
39 | fprintf(stderr, "Test failure: %s line %d\n", file, line);
|
---|
40 | exit(EXIT_FAILURE);
|
---|
41 | /*@notreached@*/
|
---|
42 | return 0;
|
---|
43 | }
|
---|
44 |
|
---|
45 | #define MAX_ARGS 256
|
---|
46 |
|
---|
47 | static size_t my_strlen(char *s)
|
---|
48 | {
|
---|
49 | return (strlen(s));
|
---|
50 | }
|
---|
51 |
|
---|
52 | static int promotion(signed char sc, signed short ss,
|
---|
53 | unsigned char uc, unsigned short us)
|
---|
54 | {
|
---|
55 | int r = (int) sc + (int) ss + (int) uc + (int) us;
|
---|
56 |
|
---|
57 | return r;
|
---|
58 | }
|
---|
59 |
|
---|
60 | static signed char return_sc(signed char sc)
|
---|
61 | {
|
---|
62 | return sc;
|
---|
63 | }
|
---|
64 |
|
---|
65 | static unsigned char return_uc(unsigned char uc)
|
---|
66 | {
|
---|
67 | return uc;
|
---|
68 | }
|
---|
69 |
|
---|
70 | static long long return_ll(long long ll)
|
---|
71 | {
|
---|
72 | return ll;
|
---|
73 | }
|
---|
74 |
|
---|
75 | static int floating(int a, float b, double c, long double d, int e)
|
---|
76 | {
|
---|
77 | int i;
|
---|
78 |
|
---|
79 | #if 0
|
---|
80 | /* This is ifdef'd out for now. long double support under SunOS/gcc
|
---|
81 | is pretty much non-existent. You'll get the odd bus error in library
|
---|
82 | routines like printf(). */
|
---|
83 | printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
|
---|
84 | #endif
|
---|
85 |
|
---|
86 | i = (int) ((float)a/b + ((float)c/(float)d));
|
---|
87 |
|
---|
88 | return i;
|
---|
89 | }
|
---|
90 |
|
---|
91 | static float many(float f1,
|
---|
92 | float f2,
|
---|
93 | float f3,
|
---|
94 | float f4,
|
---|
95 | float f5,
|
---|
96 | float f6,
|
---|
97 | float f7,
|
---|
98 | float f8,
|
---|
99 | float f9,
|
---|
100 | float f10,
|
---|
101 | float f11,
|
---|
102 | float f12,
|
---|
103 | float f13)
|
---|
104 | {
|
---|
105 | #if 0
|
---|
106 | printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
|
---|
107 | (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
|
---|
108 | (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
|
---|
109 | (double) f11, (double) f12, (double) f13);
|
---|
110 | #endif
|
---|
111 |
|
---|
112 | return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
|
---|
113 | }
|
---|
114 |
|
---|
115 | static double dblit(float f)
|
---|
116 | {
|
---|
117 | return f/3.0;
|
---|
118 | }
|
---|
119 |
|
---|
120 | static long double ldblit(float f)
|
---|
121 | {
|
---|
122 | return (long double) (((long double) f)/ (long double) 3.0);
|
---|
123 | }
|
---|
124 |
|
---|
125 | typedef struct
|
---|
126 | {
|
---|
127 | unsigned char uc;
|
---|
128 | double d;
|
---|
129 | unsigned int ui;
|
---|
130 | } test_structure_1;
|
---|
131 |
|
---|
132 | typedef struct
|
---|
133 | {
|
---|
134 | double d1;
|
---|
135 | double d2;
|
---|
136 | } test_structure_2;
|
---|
137 |
|
---|
138 | typedef struct
|
---|
139 | {
|
---|
140 | int si;
|
---|
141 | } test_structure_3;
|
---|
142 |
|
---|
143 | typedef struct
|
---|
144 | {
|
---|
145 | unsigned ui1;
|
---|
146 | unsigned ui2;
|
---|
147 | unsigned ui3;
|
---|
148 | } test_structure_4;
|
---|
149 |
|
---|
150 | typedef struct
|
---|
151 | {
|
---|
152 | char c1;
|
---|
153 | char c2;
|
---|
154 | } test_structure_5;
|
---|
155 |
|
---|
156 | static test_structure_1 struct1(test_structure_1 ts)
|
---|
157 | {
|
---|
158 | /*@-type@*/
|
---|
159 | ts.uc++;
|
---|
160 | /*@=type@*/
|
---|
161 | ts.d--;
|
---|
162 | ts.ui++;
|
---|
163 |
|
---|
164 | return ts;
|
---|
165 | }
|
---|
166 |
|
---|
167 | static test_structure_2 struct2(test_structure_2 ts)
|
---|
168 | {
|
---|
169 | ts.d1--;
|
---|
170 | ts.d2--;
|
---|
171 |
|
---|
172 | return ts;
|
---|
173 | }
|
---|
174 |
|
---|
175 | static test_structure_3 struct3(test_structure_3 ts)
|
---|
176 | {
|
---|
177 | ts.si = -(ts.si*2);
|
---|
178 |
|
---|
179 | return ts;
|
---|
180 | }
|
---|
181 |
|
---|
182 | static test_structure_4 struct4(test_structure_4 ts)
|
---|
183 | {
|
---|
184 | ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
|
---|
185 |
|
---|
186 | return ts;
|
---|
187 | }
|
---|
188 |
|
---|
189 | static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
|
---|
190 | {
|
---|
191 | ts1.c1 += ts2.c1;
|
---|
192 | ts1.c2 -= ts2.c2;
|
---|
193 |
|
---|
194 | return ts1;
|
---|
195 | }
|
---|
196 |
|
---|
197 | /* Take an int and a float argument, together with int userdata, and */
|
---|
198 | /* return the sum. */
|
---|
199 | static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
|
---|
200 | {
|
---|
201 | *(int*)resp =
|
---|
202 | *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
|
---|
203 | }
|
---|
204 |
|
---|
205 | typedef int (*closure_test_type)(int, float);
|
---|
206 |
|
---|
207 | int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
|
---|
208 | {
|
---|
209 | ffi_cif cif;
|
---|
210 | ffi_type *args[MAX_ARGS];
|
---|
211 | void *values[MAX_ARGS];
|
---|
212 | char *s;
|
---|
213 | signed char sc;
|
---|
214 | unsigned char uc;
|
---|
215 | signed short ss;
|
---|
216 | unsigned short us;
|
---|
217 | unsigned long ul;
|
---|
218 | long long ll;
|
---|
219 | float f;
|
---|
220 | double d;
|
---|
221 | long double ld;
|
---|
222 | signed int si1;
|
---|
223 | signed int si2;
|
---|
224 |
|
---|
225 | ffi_arg rint;
|
---|
226 | long long rlonglong;
|
---|
227 |
|
---|
228 | ffi_type ts1_type;
|
---|
229 | ffi_type ts2_type;
|
---|
230 | ffi_type ts3_type;
|
---|
231 | ffi_type ts4_type;
|
---|
232 | ffi_type ts5_type;
|
---|
233 | ffi_type *ts1_type_elements[4];
|
---|
234 | ffi_type *ts2_type_elements[3];
|
---|
235 | ffi_type *ts3_type_elements[2];
|
---|
236 | ffi_type *ts4_type_elements[4];
|
---|
237 | ffi_type *ts5_type_elements[3];
|
---|
238 |
|
---|
239 | ts1_type.size = 0;
|
---|
240 | ts1_type.alignment = 0;
|
---|
241 | ts1_type.type = FFI_TYPE_STRUCT;
|
---|
242 |
|
---|
243 | ts2_type.size = 0;
|
---|
244 | ts2_type.alignment = 0;
|
---|
245 | ts2_type.type = FFI_TYPE_STRUCT;
|
---|
246 |
|
---|
247 | ts3_type.size = 0;
|
---|
248 | ts3_type.alignment = 0;
|
---|
249 | ts3_type.type = FFI_TYPE_STRUCT;
|
---|
250 |
|
---|
251 | ts4_type.size = 0;
|
---|
252 | ts4_type.alignment = 0;
|
---|
253 | ts4_type.type = FFI_TYPE_STRUCT;
|
---|
254 |
|
---|
255 | ts5_type.size = 0;
|
---|
256 | ts5_type.alignment = 0;
|
---|
257 | ts5_type.type = FFI_TYPE_STRUCT;
|
---|
258 |
|
---|
259 | /*@-immediatetrans@*/
|
---|
260 | ts1_type.elements = ts1_type_elements;
|
---|
261 | ts2_type.elements = ts2_type_elements;
|
---|
262 | ts3_type.elements = ts3_type_elements;
|
---|
263 | ts4_type.elements = ts4_type_elements;
|
---|
264 | ts5_type.elements = ts5_type_elements;
|
---|
265 | /*@=immediatetrans@*/
|
---|
266 |
|
---|
267 | ts1_type_elements[0] = &ffi_type_uchar;
|
---|
268 | ts1_type_elements[1] = &ffi_type_double;
|
---|
269 | ts1_type_elements[2] = &ffi_type_uint;
|
---|
270 | ts1_type_elements[3] = NULL;
|
---|
271 |
|
---|
272 | ts2_type_elements[0] = &ffi_type_double;
|
---|
273 | ts2_type_elements[1] = &ffi_type_double;
|
---|
274 | ts2_type_elements[2] = NULL;
|
---|
275 |
|
---|
276 | ts3_type_elements[0] = &ffi_type_sint;
|
---|
277 | ts3_type_elements[1] = NULL;
|
---|
278 |
|
---|
279 | ts4_type_elements[0] = &ffi_type_uint;
|
---|
280 | ts4_type_elements[1] = &ffi_type_uint;
|
---|
281 | ts4_type_elements[2] = &ffi_type_uint;
|
---|
282 | ts4_type_elements[3] = NULL;
|
---|
283 |
|
---|
284 | ts5_type_elements[0] = &ffi_type_schar;
|
---|
285 | ts5_type_elements[1] = &ffi_type_schar;
|
---|
286 | ts5_type_elements[2] = NULL;
|
---|
287 |
|
---|
288 | ul = 0;
|
---|
289 |
|
---|
290 | /* return value tests */
|
---|
291 | {
|
---|
292 | #if defined(MIPS) /* || defined(ARM) */
|
---|
293 | puts ("long long tests not run. This is a known bug on this architecture.");
|
---|
294 | #else
|
---|
295 | args[0] = &ffi_type_sint64;
|
---|
296 | values[0] = ≪
|
---|
297 |
|
---|
298 | /* Initialize the cif */
|
---|
299 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
300 | &ffi_type_sint64, args) == FFI_OK);
|
---|
301 |
|
---|
302 | for (ll = 0LL; ll < 100LL; ll++)
|
---|
303 | {
|
---|
304 | ul++;
|
---|
305 | ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
|
---|
306 | CHECK(rlonglong == ll);
|
---|
307 | }
|
---|
308 |
|
---|
309 | for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
|
---|
310 | {
|
---|
311 | ul++;
|
---|
312 | ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
|
---|
313 | CHECK(rlonglong == ll);
|
---|
314 | }
|
---|
315 | #endif
|
---|
316 |
|
---|
317 | args[0] = &ffi_type_schar;
|
---|
318 | values[0] = ≻
|
---|
319 |
|
---|
320 | /* Initialize the cif */
|
---|
321 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
322 | &ffi_type_schar, args) == FFI_OK);
|
---|
323 |
|
---|
324 | for (sc = (signed char) -127;
|
---|
325 | sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
|
---|
326 | {
|
---|
327 | ul++;
|
---|
328 | ffi_call(&cif, FFI_FN(return_sc), &rint, values);
|
---|
329 | CHECK(rint == (int) sc);
|
---|
330 | }
|
---|
331 |
|
---|
332 | args[0] = &ffi_type_uchar;
|
---|
333 | values[0] = &uc;
|
---|
334 |
|
---|
335 | /* Initialize the cif */
|
---|
336 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
337 | &ffi_type_uchar, args) == FFI_OK);
|
---|
338 |
|
---|
339 | for (uc = (unsigned char) '\x00';
|
---|
340 | uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
|
---|
341 | {
|
---|
342 | ul++;
|
---|
343 | ffi_call(&cif, FFI_FN(return_uc), &rint, values);
|
---|
344 | CHECK(rint == (signed int) uc);
|
---|
345 | }
|
---|
346 |
|
---|
347 | printf("%lu return value tests run\n", ul);
|
---|
348 | }
|
---|
349 |
|
---|
350 | #ifdef BROKEN_LONG_DOUBLE
|
---|
351 | printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
|
---|
352 | #else
|
---|
353 | /* float arg tests */
|
---|
354 | {
|
---|
355 | args[0] = &ffi_type_float;
|
---|
356 | values[0] = &f;
|
---|
357 |
|
---|
358 | /* Initialize the cif */
|
---|
359 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
360 | &ffi_type_longdouble, args) == FFI_OK);
|
---|
361 |
|
---|
362 | f = 3.14159;
|
---|
363 |
|
---|
364 | #if 0
|
---|
365 | /* This is ifdef'd out for now. long double support under SunOS/gcc
|
---|
366 | is pretty much non-existent. You'll get the odd bus error in library
|
---|
367 | routines like printf(). */
|
---|
368 | printf ("%Lf\n", ldblit(f));
|
---|
369 | #endif
|
---|
370 | ld = 666;
|
---|
371 | ffi_call(&cif, FFI_FN(ldblit), &ld, values);
|
---|
372 |
|
---|
373 | #if 0
|
---|
374 | /* This is ifdef'd out for now. long double support under SunOS/gcc
|
---|
375 | is pretty much non-existent. You'll get the odd bus error in library
|
---|
376 | routines like printf(). */
|
---|
377 | printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
|
---|
378 | #endif
|
---|
379 |
|
---|
380 | /* These are not always the same!! Check for a reasonable delta */
|
---|
381 | /*@-realcompare@*/
|
---|
382 | if (ld - ldblit(f) < LDBL_EPSILON)
|
---|
383 | /*@=realcompare@*/
|
---|
384 | puts("long double return value tests ok!");
|
---|
385 | else
|
---|
386 | CHECK(0);
|
---|
387 | }
|
---|
388 |
|
---|
389 | /* float arg tests */
|
---|
390 | {
|
---|
391 | args[0] = &ffi_type_sint;
|
---|
392 | values[0] = &si1;
|
---|
393 | args[1] = &ffi_type_float;
|
---|
394 | values[1] = &f;
|
---|
395 | args[2] = &ffi_type_double;
|
---|
396 | values[2] = &d;
|
---|
397 | args[3] = &ffi_type_longdouble;
|
---|
398 | values[3] = &ld;
|
---|
399 | args[4] = &ffi_type_sint;
|
---|
400 | values[4] = &si2;
|
---|
401 |
|
---|
402 | /* Initialize the cif */
|
---|
403 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
|
---|
404 | &ffi_type_sint, args) == FFI_OK);
|
---|
405 |
|
---|
406 | si1 = 6;
|
---|
407 | f = 3.14159;
|
---|
408 | d = (double)1.0/(double)3.0;
|
---|
409 | ld = 2.71828182846L;
|
---|
410 | si2 = 10;
|
---|
411 |
|
---|
412 | floating (si1, f, d, ld, si2);
|
---|
413 |
|
---|
414 | ffi_call(&cif, FFI_FN(floating), &rint, values);
|
---|
415 |
|
---|
416 | printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
|
---|
417 |
|
---|
418 | CHECK(rint == floating(si1, f, d, ld, si2));
|
---|
419 |
|
---|
420 | printf("float arg tests ok!\n");
|
---|
421 | }
|
---|
422 | #endif
|
---|
423 |
|
---|
424 | /* strlen tests */
|
---|
425 | {
|
---|
426 | args[0] = &ffi_type_pointer;
|
---|
427 | values[0] = (void*) &s;
|
---|
428 |
|
---|
429 | /* Initialize the cif */
|
---|
430 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
431 | &ffi_type_sint, args) == FFI_OK);
|
---|
432 |
|
---|
433 | s = "a";
|
---|
434 | ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
---|
435 | CHECK(rint == 1);
|
---|
436 |
|
---|
437 | s = "1234567";
|
---|
438 | ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
---|
439 | CHECK(rint == 7);
|
---|
440 |
|
---|
441 | s = "1234567890123456789012345";
|
---|
442 | ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
|
---|
443 | CHECK(rint == 25);
|
---|
444 |
|
---|
445 | printf("strlen tests passed\n");
|
---|
446 | }
|
---|
447 |
|
---|
448 | /* float arg tests */
|
---|
449 | {
|
---|
450 | args[0] = &ffi_type_float;
|
---|
451 | values[0] = &f;
|
---|
452 |
|
---|
453 | /* Initialize the cif */
|
---|
454 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
455 | &ffi_type_double, args) == FFI_OK);
|
---|
456 |
|
---|
457 | f = 3.14159;
|
---|
458 |
|
---|
459 | ffi_call(&cif, FFI_FN(dblit), &d, values);
|
---|
460 |
|
---|
461 | /* These are not always the same!! Check for a reasonable delta */
|
---|
462 | /*@-realcompare@*/
|
---|
463 | CHECK(d - dblit(f) < DBL_EPSILON);
|
---|
464 | /*@=realcompare@*/
|
---|
465 |
|
---|
466 | printf("double return value tests ok!\n");
|
---|
467 | }
|
---|
468 |
|
---|
469 | /* many arg tests */
|
---|
470 | {
|
---|
471 | float ff;
|
---|
472 | float fa[13];
|
---|
473 |
|
---|
474 | for (ul = 0; ul < 13; ul++)
|
---|
475 | {
|
---|
476 | args[ul] = &ffi_type_float;
|
---|
477 | values[ul] = &fa[ul];
|
---|
478 | fa[ul] = (float) ul;
|
---|
479 | }
|
---|
480 |
|
---|
481 | /* Initialize the cif */
|
---|
482 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
|
---|
483 | &ffi_type_float, args) == FFI_OK);
|
---|
484 |
|
---|
485 | /*@-usedef@*/
|
---|
486 | ff = many(fa[0], fa[1],
|
---|
487 | fa[2], fa[3],
|
---|
488 | fa[4], fa[5],
|
---|
489 | fa[6], fa[7],
|
---|
490 | fa[8], fa[9],
|
---|
491 | fa[10],fa[11],fa[12]);
|
---|
492 | /*@=usedef@*/
|
---|
493 |
|
---|
494 | ffi_call(&cif, FFI_FN(many), &f, values);
|
---|
495 |
|
---|
496 | /*@-realcompare@*/
|
---|
497 | if (f - ff < FLT_EPSILON)
|
---|
498 | /*@=realcompare@*/
|
---|
499 | printf("many arg tests ok!\n");
|
---|
500 | else
|
---|
501 | #ifdef POWERPC
|
---|
502 | printf("many arg tests failed! This is a gcc bug.\n");
|
---|
503 | #else
|
---|
504 | CHECK(0);
|
---|
505 | #endif
|
---|
506 | }
|
---|
507 |
|
---|
508 | /* promotion tests */
|
---|
509 | {
|
---|
510 | args[0] = &ffi_type_schar;
|
---|
511 | args[1] = &ffi_type_sshort;
|
---|
512 | args[2] = &ffi_type_uchar;
|
---|
513 | args[3] = &ffi_type_ushort;
|
---|
514 | values[0] = ≻
|
---|
515 | values[1] = &ss;
|
---|
516 | values[2] = &uc;
|
---|
517 | values[3] = &us;
|
---|
518 |
|
---|
519 | /* Initialize the cif */
|
---|
520 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
|
---|
521 | &ffi_type_sint, args) == FFI_OK);
|
---|
522 |
|
---|
523 | us = 0;
|
---|
524 | ul = 0;
|
---|
525 |
|
---|
526 | for (sc = (signed char) -127;
|
---|
527 | sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
|
---|
528 | for (ss = -30000; ss <= 30000; ss += 10000)
|
---|
529 | for (uc = (unsigned char) 0;
|
---|
530 | uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
|
---|
531 | for (us = 0; us <= 60000; us += 10000)
|
---|
532 | {
|
---|
533 | ul++;
|
---|
534 | ffi_call(&cif, FFI_FN(promotion), &rint, values);
|
---|
535 | CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
|
---|
536 | }
|
---|
537 | printf("%lu promotion tests run\n", ul);
|
---|
538 | }
|
---|
539 |
|
---|
540 | #ifndef X86_WIN32 /* Structures dont work on Win32 */
|
---|
541 |
|
---|
542 | /* struct tests */
|
---|
543 | {
|
---|
544 | test_structure_1 ts1_arg;
|
---|
545 | /* This is a hack to get a properly aligned result buffer */
|
---|
546 | test_structure_1 *ts1_result =
|
---|
547 | (test_structure_1 *) malloc (sizeof(test_structure_1));
|
---|
548 |
|
---|
549 | args[0] = &ts1_type;
|
---|
550 | values[0] = &ts1_arg;
|
---|
551 |
|
---|
552 | /* Initialize the cif */
|
---|
553 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
554 | &ts1_type, args) == FFI_OK);
|
---|
555 |
|
---|
556 | ts1_arg.uc = '\x01';
|
---|
557 | ts1_arg.d = 3.14159;
|
---|
558 | ts1_arg.ui = 555;
|
---|
559 |
|
---|
560 | ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
|
---|
561 |
|
---|
562 | CHECK(ts1_result->ui == 556);
|
---|
563 | CHECK(ts1_result->d == 3.14159 - 1);
|
---|
564 |
|
---|
565 | puts ("structure test 1 ok!\n");
|
---|
566 |
|
---|
567 | free (ts1_result);
|
---|
568 | }
|
---|
569 |
|
---|
570 | /* struct tests */
|
---|
571 | {
|
---|
572 | test_structure_2 ts2_arg;
|
---|
573 |
|
---|
574 | /* This is a hack to get a properly aligned result buffer */
|
---|
575 | test_structure_2 *ts2_result =
|
---|
576 | (test_structure_2 *) malloc (sizeof(test_structure_2));
|
---|
577 |
|
---|
578 | args[0] = &ts2_type;
|
---|
579 | values[0] = &ts2_arg;
|
---|
580 |
|
---|
581 | /* Initialize the cif */
|
---|
582 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
583 | &ts2_type, args) == FFI_OK);
|
---|
584 |
|
---|
585 | ts2_arg.d1 = 5.55;
|
---|
586 | ts2_arg.d2 = 6.66;
|
---|
587 |
|
---|
588 | printf ("%g\n", ts2_result->d1);
|
---|
589 | printf ("%g\n", ts2_result->d2);
|
---|
590 |
|
---|
591 | ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
|
---|
592 |
|
---|
593 | printf ("%g\n", ts2_result->d1);
|
---|
594 | printf ("%g\n", ts2_result->d2);
|
---|
595 |
|
---|
596 | CHECK(ts2_result->d1 == 5.55 - 1);
|
---|
597 | CHECK(ts2_result->d2 == 6.66 - 1);
|
---|
598 |
|
---|
599 | printf("structure test 2 ok!\n");
|
---|
600 |
|
---|
601 | free (ts2_result);
|
---|
602 | }
|
---|
603 |
|
---|
604 | /* struct tests */
|
---|
605 | {
|
---|
606 | int compare_value;
|
---|
607 | test_structure_3 ts3_arg;
|
---|
608 | test_structure_3 *ts3_result =
|
---|
609 | (test_structure_3 *) malloc (sizeof(test_structure_3));
|
---|
610 |
|
---|
611 | args[0] = &ts3_type;
|
---|
612 | values[0] = &ts3_arg;
|
---|
613 |
|
---|
614 | /* Initialize the cif */
|
---|
615 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
616 | &ts3_type, args) == FFI_OK);
|
---|
617 |
|
---|
618 | ts3_arg.si = -123;
|
---|
619 | compare_value = ts3_arg.si;
|
---|
620 |
|
---|
621 | ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
|
---|
622 |
|
---|
623 | printf ("%d %d\n", ts3_result->si, -(compare_value*2));
|
---|
624 |
|
---|
625 | if (ts3_result->si == -(ts3_arg.si*2))
|
---|
626 | puts ("structure test 3 ok!");
|
---|
627 | else
|
---|
628 | {
|
---|
629 | puts ("Structure test 3 found structure passing bug.");
|
---|
630 | puts (" Current versions of GCC are not 100% compliant with the");
|
---|
631 | puts (" n32 ABI. There is a known problem related to passing");
|
---|
632 | puts (" small structures. Send a bug report to the gcc maintainers.");
|
---|
633 | }
|
---|
634 |
|
---|
635 | free (ts3_result);
|
---|
636 | }
|
---|
637 |
|
---|
638 | /* struct tests */
|
---|
639 | {
|
---|
640 | test_structure_4 ts4_arg;
|
---|
641 |
|
---|
642 | /* This is a hack to get a properly aligned result buffer */
|
---|
643 | test_structure_4 *ts4_result =
|
---|
644 | (test_structure_4 *) malloc (sizeof(test_structure_4));
|
---|
645 |
|
---|
646 | args[0] = &ts4_type;
|
---|
647 | values[0] = &ts4_arg;
|
---|
648 |
|
---|
649 | /* Initialize the cif */
|
---|
650 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
|
---|
651 | &ts4_type, args) == FFI_OK);
|
---|
652 |
|
---|
653 | ts4_arg.ui1 = 2;
|
---|
654 | ts4_arg.ui2 = 3;
|
---|
655 | ts4_arg.ui3 = 4;
|
---|
656 |
|
---|
657 | ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
|
---|
658 |
|
---|
659 | if (ts4_result->ui3 == 2U * 3U * 4U)
|
---|
660 | puts ("structure test 4 ok!");
|
---|
661 | else
|
---|
662 | puts ("Structure test 4 found GCC's structure passing bug.");
|
---|
663 |
|
---|
664 | free (ts4_result);
|
---|
665 | }
|
---|
666 |
|
---|
667 | /* struct tests */
|
---|
668 | {
|
---|
669 | test_structure_5 ts5_arg1, ts5_arg2;
|
---|
670 |
|
---|
671 | /* This is a hack to get a properly aligned result buffer */
|
---|
672 | test_structure_5 *ts5_result =
|
---|
673 | (test_structure_5 *) malloc (sizeof(test_structure_5));
|
---|
674 |
|
---|
675 | args[0] = &ts5_type;
|
---|
676 | args[1] = &ts5_type;
|
---|
677 | values[0] = &ts5_arg1;
|
---|
678 | values[1] = &ts5_arg2;
|
---|
679 |
|
---|
680 | /* Initialize the cif */
|
---|
681 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
---|
682 | &ts5_type, args) == FFI_OK);
|
---|
683 |
|
---|
684 | ts5_arg1.c1 = 2;
|
---|
685 | ts5_arg1.c2 = 6;
|
---|
686 | ts5_arg2.c1 = 5;
|
---|
687 | ts5_arg2.c2 = 3;
|
---|
688 |
|
---|
689 | ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
|
---|
690 |
|
---|
691 | if (ts5_result->c1 == 7
|
---|
692 | && ts5_result->c2 == 3)
|
---|
693 | puts ("structure test 5 ok!");
|
---|
694 | else
|
---|
695 | puts ("Structure test 5 found GCC's structure passing bug.");
|
---|
696 |
|
---|
697 | free (ts5_result);
|
---|
698 | }
|
---|
699 |
|
---|
700 | #else
|
---|
701 | printf("Structure passing doesn't work on Win32.\n");
|
---|
702 | #endif /* X86_WIN32 */
|
---|
703 |
|
---|
704 | # if FFI_CLOSURES
|
---|
705 | /* A simple closure test */
|
---|
706 | {
|
---|
707 | ffi_closure cl;
|
---|
708 | ffi_type * cl_arg_types[3];
|
---|
709 |
|
---|
710 | cl_arg_types[0] = &ffi_type_sint;
|
---|
711 | cl_arg_types[1] = &ffi_type_float;
|
---|
712 | cl_arg_types[2] = NULL;
|
---|
713 |
|
---|
714 | /* Initialize the cif */
|
---|
715 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
|
---|
716 | &ffi_type_sint, cl_arg_types) == FFI_OK);
|
---|
717 |
|
---|
718 | CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
|
---|
719 | (void *) 3 /* userdata */)
|
---|
720 | == FFI_OK);
|
---|
721 | CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
|
---|
722 | }
|
---|
723 | # endif
|
---|
724 |
|
---|
725 | /* If we arrived here, all is good */
|
---|
726 | (void) puts("\nLooks good. No surprises.\n");
|
---|
727 |
|
---|
728 | /*@-compdestroy@*/
|
---|
729 |
|
---|
730 | return 0;
|
---|
731 | }
|
---|
732 |
|
---|