* cfgloop.c (flow_loop_entry_edges_find): Fix typo.
[official-gcc.git] / libffi / src / ffitest.c
bloba03f045b2fb27cb135dbdb4b3de930be1e2549b3
1 /* -----------------------------------------------------------------------
2 ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
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:
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
24 #include <ffi.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <float.h>
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
35 #define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
37 static int fail(char *file, int line)
39 fprintf(stderr, "Test failure: %s line %d\n", file, line);
40 exit(EXIT_FAILURE);
41 /*@notreached@*/
42 return 0;
45 #define MAX_ARGS 256
47 static size_t my_strlen(char *s)
49 return (strlen(s));
52 static int promotion(signed char sc, signed short ss,
53 unsigned char uc, unsigned short us)
55 int r = (int) sc + (int) ss + (int) uc + (int) us;
57 return r;
60 static signed char return_sc(signed char sc)
62 return sc;
65 static unsigned char return_uc(unsigned char uc)
67 return uc;
70 static long long return_ll(long long ll)
72 return ll;
75 static int floating(int a, float b, double c, long double d, int e)
77 int i;
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
86 i = (int) ((float)a/b + ((float)c/(float)d));
88 return i;
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)
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
112 return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
115 static double dblit(float f)
117 return f/3.0;
120 static long double ldblit(float f)
122 return (long double) (((long double) f)/ (long double) 3.0);
125 typedef struct
127 unsigned char uc;
128 double d;
129 unsigned int ui;
130 } test_structure_1;
132 typedef struct
134 double d1;
135 double d2;
136 } test_structure_2;
138 typedef struct
140 int si;
141 } test_structure_3;
143 typedef struct
145 unsigned ui1;
146 unsigned ui2;
147 unsigned ui3;
148 } test_structure_4;
150 typedef struct
152 char c1;
153 char c2;
154 } test_structure_5;
156 static test_structure_1 struct1(test_structure_1 ts)
158 /*@-type@*/
159 ts.uc++;
160 /*@=type@*/
161 ts.d--;
162 ts.ui++;
164 return ts;
167 static test_structure_2 struct2(test_structure_2 ts)
169 ts.d1--;
170 ts.d2--;
172 return ts;
175 static test_structure_3 struct3(test_structure_3 ts)
177 ts.si = -(ts.si*2);
179 return ts;
182 static test_structure_4 struct4(test_structure_4 ts)
184 ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
186 return ts;
189 static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
191 ts1.c1 += ts2.c1;
192 ts1.c2 -= ts2.c2;
194 return ts1;
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)
201 *(int*)resp =
202 *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
205 typedef int (*closure_test_type)(int, float);
207 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
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;
225 #if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
226 long long rint;
227 #else
228 int rint;
229 #endif
230 long long rlonglong;
232 ffi_type ts1_type;
233 ffi_type ts2_type;
234 ffi_type ts3_type;
235 ffi_type ts4_type;
236 ffi_type ts5_type;
237 ffi_type *ts1_type_elements[4];
238 ffi_type *ts2_type_elements[3];
239 ffi_type *ts3_type_elements[2];
240 ffi_type *ts4_type_elements[4];
241 ffi_type *ts5_type_elements[3];
243 ts1_type.size = 0;
244 ts1_type.alignment = 0;
245 ts1_type.type = FFI_TYPE_STRUCT;
247 ts2_type.size = 0;
248 ts2_type.alignment = 0;
249 ts2_type.type = FFI_TYPE_STRUCT;
251 ts3_type.size = 0;
252 ts3_type.alignment = 0;
253 ts3_type.type = FFI_TYPE_STRUCT;
255 ts4_type.size = 0;
256 ts4_type.alignment = 0;
257 ts4_type.type = FFI_TYPE_STRUCT;
259 ts5_type.size = 0;
260 ts5_type.alignment = 0;
261 ts5_type.type = FFI_TYPE_STRUCT;
263 /*@-immediatetrans@*/
264 ts1_type.elements = ts1_type_elements;
265 ts2_type.elements = ts2_type_elements;
266 ts3_type.elements = ts3_type_elements;
267 ts4_type.elements = ts4_type_elements;
268 ts5_type.elements = ts5_type_elements;
269 /*@=immediatetrans@*/
271 ts1_type_elements[0] = &ffi_type_uchar;
272 ts1_type_elements[1] = &ffi_type_double;
273 ts1_type_elements[2] = &ffi_type_uint;
274 ts1_type_elements[3] = NULL;
276 ts2_type_elements[0] = &ffi_type_double;
277 ts2_type_elements[1] = &ffi_type_double;
278 ts2_type_elements[2] = NULL;
280 ts3_type_elements[0] = &ffi_type_sint;
281 ts3_type_elements[1] = NULL;
283 ts4_type_elements[0] = &ffi_type_uint;
284 ts4_type_elements[1] = &ffi_type_uint;
285 ts4_type_elements[2] = &ffi_type_uint;
286 ts4_type_elements[3] = NULL;
288 ts5_type_elements[0] = &ffi_type_schar;
289 ts5_type_elements[1] = &ffi_type_schar;
290 ts5_type_elements[2] = NULL;
292 ul = 0;
294 /* return value tests */
296 #if defined(MIPS) /* || defined(ARM) */
297 puts ("long long tests not run. This is a known bug on this architecture.");
298 #else
299 args[0] = &ffi_type_sint64;
300 values[0] = &ll;
302 /* Initialize the cif */
303 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
304 &ffi_type_sint64, args) == FFI_OK);
306 for (ll = 0LL; ll < 100LL; ll++)
308 ul++;
309 ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
310 CHECK(rlonglong == ll);
313 for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
315 ul++;
316 ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
317 CHECK(rlonglong == ll);
319 #endif
321 args[0] = &ffi_type_schar;
322 values[0] = &sc;
324 /* Initialize the cif */
325 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
326 &ffi_type_schar, args) == FFI_OK);
328 for (sc = (signed char) -127;
329 sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
331 ul++;
332 ffi_call(&cif, FFI_FN(return_sc), &rint, values);
333 CHECK(rint == (int) sc);
336 args[0] = &ffi_type_uchar;
337 values[0] = &uc;
339 /* Initialize the cif */
340 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
341 &ffi_type_uchar, args) == FFI_OK);
343 for (uc = (unsigned char) '\x00';
344 uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
346 ul++;
347 ffi_call(&cif, FFI_FN(return_uc), &rint, values);
348 CHECK(rint == (signed int) uc);
351 printf("%lu return value tests run\n", ul);
354 #ifdef BROKEN_LONG_DOUBLE
355 printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
356 #else
357 /* float arg tests */
359 args[0] = &ffi_type_float;
360 values[0] = &f;
362 /* Initialize the cif */
363 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
364 &ffi_type_longdouble, args) == FFI_OK);
366 f = 3.14159;
368 #if 0
369 /* This is ifdef'd out for now. long double support under SunOS/gcc
370 is pretty much non-existent. You'll get the odd bus error in library
371 routines like printf(). */
372 printf ("%Lf\n", ldblit(f));
373 #endif
374 ld = 666;
375 ffi_call(&cif, FFI_FN(ldblit), &ld, values);
377 #if 0
378 /* This is ifdef'd out for now. long double support under SunOS/gcc
379 is pretty much non-existent. You'll get the odd bus error in library
380 routines like printf(). */
381 printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
382 #endif
384 /* These are not always the same!! Check for a reasonable delta */
385 /*@-realcompare@*/
386 if (ld - ldblit(f) < LDBL_EPSILON)
387 /*@=realcompare@*/
388 puts("long double return value tests ok!");
389 else
390 CHECK(0);
393 /* float arg tests */
395 args[0] = &ffi_type_sint;
396 values[0] = &si1;
397 args[1] = &ffi_type_float;
398 values[1] = &f;
399 args[2] = &ffi_type_double;
400 values[2] = &d;
401 args[3] = &ffi_type_longdouble;
402 values[3] = &ld;
403 args[4] = &ffi_type_sint;
404 values[4] = &si2;
406 /* Initialize the cif */
407 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
408 &ffi_type_sint, args) == FFI_OK);
410 si1 = 6;
411 f = 3.14159;
412 d = (double)1.0/(double)3.0;
413 ld = 2.71828182846L;
414 si2 = 10;
416 floating (si1, f, d, ld, si2);
418 ffi_call(&cif, FFI_FN(floating), &rint, values);
420 printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
422 CHECK(rint == floating(si1, f, d, ld, si2));
424 printf("float arg tests ok!\n");
426 #endif
428 /* strlen tests */
430 args[0] = &ffi_type_pointer;
431 values[0] = (void*) &s;
433 /* Initialize the cif */
434 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
435 &ffi_type_sint, args) == FFI_OK);
437 s = "a";
438 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
439 CHECK(rint == 1);
441 s = "1234567";
442 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
443 CHECK(rint == 7);
445 s = "1234567890123456789012345";
446 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
447 CHECK(rint == 25);
449 printf("strlen tests passed\n");
452 /* float arg tests */
454 args[0] = &ffi_type_float;
455 values[0] = &f;
457 /* Initialize the cif */
458 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
459 &ffi_type_double, args) == FFI_OK);
461 f = 3.14159;
463 ffi_call(&cif, FFI_FN(dblit), &d, values);
465 /* These are not always the same!! Check for a reasonable delta */
466 /*@-realcompare@*/
467 CHECK(d - dblit(f) < DBL_EPSILON);
468 /*@=realcompare@*/
470 printf("double return value tests ok!\n");
473 /* many arg tests */
475 float ff;
476 float fa[13];
478 for (ul = 0; ul < 13; ul++)
480 args[ul] = &ffi_type_float;
481 values[ul] = &fa[ul];
482 fa[ul] = (float) ul;
485 /* Initialize the cif */
486 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
487 &ffi_type_float, args) == FFI_OK);
489 /*@-usedef@*/
490 ff = many(fa[0], fa[1],
491 fa[2], fa[3],
492 fa[4], fa[5],
493 fa[6], fa[7],
494 fa[8], fa[9],
495 fa[10],fa[11],fa[12]);
496 /*@=usedef@*/
498 ffi_call(&cif, FFI_FN(many), &f, values);
500 /*@-realcompare@*/
501 if (f - ff < FLT_EPSILON)
502 /*@=realcompare@*/
503 printf("many arg tests ok!\n");
504 else
505 #ifdef POWERPC
506 printf("many arg tests failed! This is a gcc bug.\n");
507 #else
508 CHECK(0);
509 #endif
512 /* promotion tests */
514 args[0] = &ffi_type_schar;
515 args[1] = &ffi_type_sshort;
516 args[2] = &ffi_type_uchar;
517 args[3] = &ffi_type_ushort;
518 values[0] = &sc;
519 values[1] = &ss;
520 values[2] = &uc;
521 values[3] = &us;
523 /* Initialize the cif */
524 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
525 &ffi_type_sint, args) == FFI_OK);
527 us = 0;
528 ul = 0;
530 for (sc = (signed char) -127;
531 sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
532 for (ss = -30000; ss <= 30000; ss += 10000)
533 for (uc = (unsigned char) 0;
534 uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
535 for (us = 0; us <= 60000; us += 10000)
537 ul++;
538 ffi_call(&cif, FFI_FN(promotion), &rint, values);
539 CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
541 printf("%lu promotion tests run\n", ul);
544 #ifndef X86_WIN32 /* Structures dont work on Win32 */
546 /* struct tests */
548 test_structure_1 ts1_arg;
549 /* This is a hack to get a properly aligned result buffer */
550 test_structure_1 *ts1_result =
551 (test_structure_1 *) malloc (sizeof(test_structure_1));
553 args[0] = &ts1_type;
554 values[0] = &ts1_arg;
556 /* Initialize the cif */
557 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
558 &ts1_type, args) == FFI_OK);
560 ts1_arg.uc = '\x01';
561 ts1_arg.d = 3.14159;
562 ts1_arg.ui = 555;
564 ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
566 CHECK(ts1_result->ui == 556);
567 CHECK(ts1_result->d == 3.14159 - 1);
569 puts ("structure test 1 ok!\n");
571 free (ts1_result);
574 /* struct tests */
576 test_structure_2 ts2_arg;
578 /* This is a hack to get a properly aligned result buffer */
579 test_structure_2 *ts2_result =
580 (test_structure_2 *) malloc (sizeof(test_structure_2));
582 args[0] = &ts2_type;
583 values[0] = &ts2_arg;
585 /* Initialize the cif */
586 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
587 &ts2_type, args) == FFI_OK);
589 ts2_arg.d1 = 5.55;
590 ts2_arg.d2 = 6.66;
592 printf ("%g\n", ts2_result->d1);
593 printf ("%g\n", ts2_result->d2);
595 ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
597 printf ("%g\n", ts2_result->d1);
598 printf ("%g\n", ts2_result->d2);
600 CHECK(ts2_result->d1 == 5.55 - 1);
601 CHECK(ts2_result->d2 == 6.66 - 1);
603 printf("structure test 2 ok!\n");
605 free (ts2_result);
608 /* struct tests */
610 int compare_value;
611 test_structure_3 ts3_arg;
612 test_structure_3 *ts3_result =
613 (test_structure_3 *) malloc (sizeof(test_structure_3));
615 args[0] = &ts3_type;
616 values[0] = &ts3_arg;
618 /* Initialize the cif */
619 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
620 &ts3_type, args) == FFI_OK);
622 ts3_arg.si = -123;
623 compare_value = ts3_arg.si;
625 ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
627 printf ("%d %d\n", ts3_result->si, -(compare_value*2));
629 if (ts3_result->si == -(ts3_arg.si*2))
630 puts ("structure test 3 ok!");
631 else
633 puts ("Structure test 3 found structure passing bug.");
634 puts (" Current versions of GCC are not 100% compliant with the");
635 puts (" n32 ABI. There is a known problem related to passing");
636 puts (" small structures. Send a bug report to the gcc maintainers.");
639 free (ts3_result);
642 /* struct tests */
644 test_structure_4 ts4_arg;
646 /* This is a hack to get a properly aligned result buffer */
647 test_structure_4 *ts4_result =
648 (test_structure_4 *) malloc (sizeof(test_structure_4));
650 args[0] = &ts4_type;
651 values[0] = &ts4_arg;
653 /* Initialize the cif */
654 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
655 &ts4_type, args) == FFI_OK);
657 ts4_arg.ui1 = 2;
658 ts4_arg.ui2 = 3;
659 ts4_arg.ui3 = 4;
661 ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
663 if (ts4_result->ui3 == 2U * 3U * 4U)
664 puts ("structure test 4 ok!");
665 else
666 puts ("Structure test 4 found GCC's structure passing bug.");
668 free (ts4_result);
671 /* struct tests */
673 test_structure_5 ts5_arg1, ts5_arg2;
675 /* This is a hack to get a properly aligned result buffer */
676 test_structure_5 *ts5_result =
677 (test_structure_5 *) malloc (sizeof(test_structure_5));
679 args[0] = &ts5_type;
680 args[1] = &ts5_type;
681 values[0] = &ts5_arg1;
682 values[1] = &ts5_arg2;
684 /* Initialize the cif */
685 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
686 &ts5_type, args) == FFI_OK);
688 ts5_arg1.c1 = 2;
689 ts5_arg1.c2 = 6;
690 ts5_arg2.c1 = 5;
691 ts5_arg2.c2 = 3;
693 ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
695 if (ts5_result->c1 == 7
696 && ts5_result->c2 == 3)
697 puts ("structure test 5 ok!");
698 else
699 puts ("Structure test 5 found GCC's structure passing bug.");
701 free (ts5_result);
704 #else
705 printf("Structure passing doesn't work on Win32.\n");
706 #endif /* X86_WIN32 */
708 # if FFI_CLOSURES
709 /* A simple closure test */
711 ffi_closure cl;
712 ffi_type * cl_arg_types[3];
714 cl_arg_types[0] = &ffi_type_sint;
715 cl_arg_types[1] = &ffi_type_float;
716 cl_arg_types[2] = NULL;
718 /* Initialize the cif */
719 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
720 &ffi_type_sint, cl_arg_types) == FFI_OK);
722 CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
723 (void *) 3 /* userdata */)
724 == FFI_OK);
725 CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
727 # endif
729 /* If we arrived here, all is good */
730 (void) puts("\nLooks good. No surprises.\n");
732 /*@-compdestroy@*/
734 return 0;