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 ----------------------------------------------------------------------- */
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
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
);
47 static size_t my_strlen(char *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
;
60 static signed char return_sc(signed char sc
)
65 static unsigned char return_uc(unsigned char uc
)
70 static long long return_ll(long long ll
)
75 static int floating(int a
, float b
, double c
, long double d
, int e
)
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
);
86 i
= (int) ((float)a
/b
+ ((float)c
/(float)d
));
91 static float many(float f1
,
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
);
112 return ((f1
/f2
+f3
/f4
+f5
/f6
+f7
/f8
+f9
/f10
+f11
/f12
) * f13
);
115 static double dblit(float f
)
120 static long double ldblit(float f
)
122 return (long double) (((long double) f
)/ (long double) 3.0);
183 static test_structure_1
struct1(test_structure_1 ts
)
194 static test_structure_2
struct2(test_structure_2 ts
)
202 static test_structure_3
struct3(test_structure_3 ts
)
209 static test_structure_4
struct4(test_structure_4 ts
)
211 ts
.ui3
= ts
.ui1
* ts
.ui2
* ts
.ui3
;
216 static test_structure_5
struct5(test_structure_5 ts1
, test_structure_5 ts2
)
224 static test_structure_6
struct6 (test_structure_6 ts
)
232 static test_structure_7
struct7 (test_structure_7 ts
)
241 static test_structure_8
struct8 (test_structure_8 ts
)
251 static test_structure_9
struct9 (test_structure_9 ts
)
259 /* Take an int and a float argument, together with int userdata, and */
260 /* return the sum. */
263 closure_test_fn(ffi_cif
* cif
,void* resp
,void** args
, void* userdata
)
265 *(int*)resp
= *(int*)args
[0] + (int)(*(float*)args
[1]) + (int)(long)userdata
;
268 typedef int (*closure_test_type
)(int, float);
271 int main(/*@unused@*/ int argc
, /*@unused@*/ char *argv
[])
274 ffi_type
*args
[MAX_ARGS
];
275 void *values
[MAX_ARGS
];
301 ffi_type
*ts1_type_elements
[4];
302 ffi_type
*ts2_type_elements
[3];
303 ffi_type
*ts3_type_elements
[2];
304 ffi_type
*ts4_type_elements
[4];
305 ffi_type
*ts5_type_elements
[3];
306 ffi_type
*ts6_type_elements
[3];
307 ffi_type
*ts7_type_elements
[4];
308 ffi_type
*ts8_type_elements
[5];
309 ffi_type
*ts9_type_elements
[3];
312 ts1_type
.alignment
= 0;
313 ts1_type
.type
= FFI_TYPE_STRUCT
;
316 ts2_type
.alignment
= 0;
317 ts2_type
.type
= FFI_TYPE_STRUCT
;
320 ts3_type
.alignment
= 0;
321 ts3_type
.type
= FFI_TYPE_STRUCT
;
324 ts4_type
.alignment
= 0;
325 ts4_type
.type
= FFI_TYPE_STRUCT
;
328 ts5_type
.alignment
= 0;
329 ts5_type
.type
= FFI_TYPE_STRUCT
;
332 ts6_type
.alignment
= 0;
333 ts6_type
.type
= FFI_TYPE_STRUCT
;
336 ts7_type
.alignment
= 0;
337 ts7_type
.type
= FFI_TYPE_STRUCT
;
340 ts8_type
.alignment
= 0;
341 ts8_type
.type
= FFI_TYPE_STRUCT
;
344 ts9_type
.alignment
= 0;
345 ts9_type
.type
= FFI_TYPE_STRUCT
;
347 /*@-immediatetrans@*/
348 ts1_type
.elements
= ts1_type_elements
;
349 ts2_type
.elements
= ts2_type_elements
;
350 ts3_type
.elements
= ts3_type_elements
;
351 ts4_type
.elements
= ts4_type_elements
;
352 ts5_type
.elements
= ts5_type_elements
;
353 ts6_type
.elements
= ts6_type_elements
;
354 ts7_type
.elements
= ts7_type_elements
;
355 ts8_type
.elements
= ts8_type_elements
;
356 ts9_type
.elements
= ts9_type_elements
;
357 /*@=immediatetrans@*/
359 ts1_type_elements
[0] = &ffi_type_uchar
;
360 ts1_type_elements
[1] = &ffi_type_double
;
361 ts1_type_elements
[2] = &ffi_type_uint
;
362 ts1_type_elements
[3] = NULL
;
364 ts2_type_elements
[0] = &ffi_type_double
;
365 ts2_type_elements
[1] = &ffi_type_double
;
366 ts2_type_elements
[2] = NULL
;
368 ts3_type_elements
[0] = &ffi_type_sint
;
369 ts3_type_elements
[1] = NULL
;
371 ts4_type_elements
[0] = &ffi_type_uint
;
372 ts4_type_elements
[1] = &ffi_type_uint
;
373 ts4_type_elements
[2] = &ffi_type_uint
;
374 ts4_type_elements
[3] = NULL
;
376 ts5_type_elements
[0] = &ffi_type_schar
;
377 ts5_type_elements
[1] = &ffi_type_schar
;
378 ts5_type_elements
[2] = NULL
;
380 ts6_type_elements
[0] = &ffi_type_float
;
381 ts6_type_elements
[1] = &ffi_type_double
;
382 ts6_type_elements
[2] = NULL
;
384 ts7_type_elements
[0] = &ffi_type_float
;
385 ts7_type_elements
[1] = &ffi_type_float
;
386 ts7_type_elements
[2] = &ffi_type_double
;
387 ts7_type_elements
[3] = NULL
;
389 ts8_type_elements
[0] = &ffi_type_float
;
390 ts8_type_elements
[1] = &ffi_type_float
;
391 ts8_type_elements
[2] = &ffi_type_float
;
392 ts8_type_elements
[3] = &ffi_type_float
;
393 ts8_type_elements
[4] = NULL
;
395 ts9_type_elements
[0] = &ffi_type_float
;
396 ts9_type_elements
[1] = &ffi_type_sint
;
397 ts9_type_elements
[2] = NULL
;
401 /* return value tests */
403 #if defined(MIPS) /* || defined(ARM) */
404 puts ("long long tests not run. This is a known bug on this architecture.");
406 args
[0] = &ffi_type_sint64
;
409 /* Initialize the cif */
410 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
411 &ffi_type_sint64
, args
) == FFI_OK
);
413 for (ll
= 0LL; ll
< 100LL; ll
++)
416 ffi_call(&cif
, FFI_FN(return_ll
), &rlonglong
, values
);
417 CHECK(rlonglong
== ll
);
420 for (ll
= 55555555555000LL; ll
< 55555555555100LL; ll
++)
423 ffi_call(&cif
, FFI_FN(return_ll
), &rlonglong
, values
);
424 CHECK(rlonglong
== ll
);
428 args
[0] = &ffi_type_schar
;
431 /* Initialize the cif */
432 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
433 &ffi_type_schar
, args
) == FFI_OK
);
435 for (sc
= (signed char) -127;
436 sc
< (signed char) 127; /*@-type@*/ sc
++ /*@=type@*/)
439 ffi_call(&cif
, FFI_FN(return_sc
), &rint
, values
);
440 CHECK(rint
== (ffi_arg
) sc
);
443 args
[0] = &ffi_type_uchar
;
446 /* Initialize the cif */
447 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
448 &ffi_type_uchar
, args
) == FFI_OK
);
450 for (uc
= (unsigned char) '\x00';
451 uc
< (unsigned char) '\xff'; /*@-type@*/ uc
++ /*@=type@*/)
454 ffi_call(&cif
, FFI_FN(return_uc
), &rint
, values
);
455 CHECK(rint
== (signed int) uc
);
458 printf("%lu return value tests run\n", ul
);
461 #ifdef BROKEN_LONG_DOUBLE
462 printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
464 /* float arg tests */
466 args
[0] = &ffi_type_float
;
469 /* Initialize the cif */
470 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
471 &ffi_type_longdouble
, args
) == FFI_OK
);
476 /* This is ifdef'd out for now. long double support under SunOS/gcc
477 is pretty much non-existent. You'll get the odd bus error in library
478 routines like printf(). */
479 printf ("%Lf\n", ldblit(f
));
482 ffi_call(&cif
, FFI_FN(ldblit
), &ld
, values
);
485 /* This is ifdef'd out for now. long double support under SunOS/gcc
486 is pretty much non-existent. You'll get the odd bus error in library
487 routines like printf(). */
488 printf ("%Lf, %Lf, %Lf, %Lf\n", ld
, ldblit(f
), ld
- ldblit(f
), LDBL_EPSILON
);
491 /* These are not always the same!! Check for a reasonable delta */
493 if (ld
- ldblit(f
) < LDBL_EPSILON
)
495 puts("long double return value tests ok!");
500 /* float arg tests */
502 args
[0] = &ffi_type_sint
;
504 args
[1] = &ffi_type_float
;
506 args
[2] = &ffi_type_double
;
508 args
[3] = &ffi_type_longdouble
;
510 args
[4] = &ffi_type_sint
;
513 /* Initialize the cif */
514 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 5,
515 &ffi_type_sint
, args
) == FFI_OK
);
519 d
= (double)1.0/(double)3.0;
523 floating (si1
, f
, d
, ld
, si2
);
525 ffi_call(&cif
, FFI_FN(floating
), &rint
, values
);
527 printf ("%d vs %d\n", (int)rint
, floating (si1
, f
, d
, ld
, si2
));
529 CHECK(rint
== floating(si1
, f
, d
, ld
, si2
));
531 printf("float arg tests ok!\n");
537 args
[0] = &ffi_type_pointer
;
538 values
[0] = (void*) &s
;
540 /* Initialize the cif */
541 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
542 &ffi_type_sint
, args
) == FFI_OK
);
545 ffi_call(&cif
, FFI_FN(my_strlen
), &rint
, values
);
549 ffi_call(&cif
, FFI_FN(my_strlen
), &rint
, values
);
552 s
= "1234567890123456789012345";
553 ffi_call(&cif
, FFI_FN(my_strlen
), &rint
, values
);
556 printf("strlen tests passed\n");
559 /* float arg tests */
561 args
[0] = &ffi_type_float
;
564 /* Initialize the cif */
565 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
566 &ffi_type_double
, args
) == FFI_OK
);
570 ffi_call(&cif
, FFI_FN(dblit
), &d
, values
);
572 /* These are not always the same!! Check for a reasonable delta */
574 CHECK(d
- dblit(f
) < DBL_EPSILON
);
577 printf("double return value tests ok!\n");
585 for (ul
= 0; ul
< 13; ul
++)
587 args
[ul
] = &ffi_type_float
;
588 values
[ul
] = &fa
[ul
];
592 /* Initialize the cif */
593 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 13,
594 &ffi_type_float
, args
) == FFI_OK
);
597 ff
= many (fa
[0], fa
[1],
602 fa
[10],fa
[11],fa
[12]);
605 ffi_call(&cif
, FFI_FN(many
), &f
, values
);
608 if (f
- ff
< FLT_EPSILON
)
610 printf("many arg tests ok!\n");
613 printf("many arg tests failed! This is a gcc bug.\n");
619 /* promotion tests */
621 args
[0] = &ffi_type_schar
;
622 args
[1] = &ffi_type_sshort
;
623 args
[2] = &ffi_type_uchar
;
624 args
[3] = &ffi_type_ushort
;
630 /* Initialize the cif */
631 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 4,
632 &ffi_type_sint
, args
) == FFI_OK
);
637 for (sc
= (signed char) -127;
638 sc
<= (signed char) 120; /*@-type@*/ sc
+= 1 /*@=type@*/)
639 for (ss
= -30000; ss
<= 30000; ss
+= 10000)
640 for (uc
= (unsigned char) 0;
641 uc
<= (unsigned char) 200; /*@-type@*/ uc
+= 20 /*@=type@*/)
642 for (us
= 0; us
<= 60000; us
+= 10000)
645 ffi_call(&cif
, FFI_FN(promotion
), &rint
, values
);
646 CHECK((int)rint
== (signed char) sc
+ (signed short) ss
+
647 (unsigned char) uc
+ (unsigned short) us
);
649 printf("%lu promotion tests run\n", ul
);
652 #ifndef X86_WIN32 /* Structures dont work on Win32 */
656 test_structure_1 ts1_arg
;
657 /* This is a hack to get a properly aligned result buffer */
658 test_structure_1
*ts1_result
=
659 (test_structure_1
*) malloc (sizeof(test_structure_1
));
662 values
[0] = &ts1_arg
;
664 /* Initialize the cif */
665 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
666 &ts1_type
, args
) == FFI_OK
);
672 ffi_call(&cif
, FFI_FN(struct1
), ts1_result
, values
);
674 CHECK(ts1_result
->ui
== 556);
675 CHECK(ts1_result
->d
== 3.14159 - 1);
677 puts ("structure test 1 ok!\n");
684 test_structure_2 ts2_arg
;
686 /* This is a hack to get a properly aligned result buffer */
687 test_structure_2
*ts2_result
=
688 (test_structure_2
*) malloc (sizeof(test_structure_2
));
691 values
[0] = &ts2_arg
;
693 /* Initialize the cif */
694 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1, &ts2_type
, args
) == FFI_OK
);
699 printf ("%g\n", ts2_result
->d1
);
700 printf ("%g\n", ts2_result
->d2
);
702 ffi_call(&cif
, FFI_FN(struct2
), ts2_result
, values
);
704 printf ("%g\n", ts2_result
->d1
);
705 printf ("%g\n", ts2_result
->d2
);
707 CHECK(ts2_result
->d1
== 5.55 - 1);
708 CHECK(ts2_result
->d2
== 6.66 - 1);
710 printf("structure test 2 ok!\n");
718 test_structure_3 ts3_arg
;
719 test_structure_3
*ts3_result
=
720 (test_structure_3
*) malloc (sizeof(test_structure_3
));
723 values
[0] = &ts3_arg
;
725 /* Initialize the cif */
726 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1,
727 &ts3_type
, args
) == FFI_OK
);
730 compare_value
= ts3_arg
.si
;
732 ffi_call(&cif
, FFI_FN(struct3
), ts3_result
, values
);
734 printf ("%d %d\n", ts3_result
->si
, -(compare_value
*2));
736 if (ts3_result
->si
== -(ts3_arg
.si
*2))
737 puts ("structure test 3 ok!");
740 puts ("Structure test 3 found structure passing bug.");
741 puts (" Current versions of GCC are not 100% compliant with the");
742 puts (" n32 ABI. There is a known problem related to passing");
743 puts (" small structures. Send a bug report to the gcc maintainers.");
751 test_structure_4 ts4_arg
;
753 /* This is a hack to get a properly aligned result buffer */
754 test_structure_4
*ts4_result
=
755 (test_structure_4
*) malloc (sizeof(test_structure_4
));
758 values
[0] = &ts4_arg
;
760 /* Initialize the cif */
761 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1, &ts4_type
, args
) == FFI_OK
);
767 ffi_call (&cif
, FFI_FN(struct4
), ts4_result
, values
);
769 if (ts4_result
->ui3
== 2U * 3U * 4U)
770 puts ("structure test 4 ok!");
772 puts ("Structure test 4 found GCC's structure passing bug.");
779 test_structure_5 ts5_arg1
, ts5_arg2
;
781 /* This is a hack to get a properly aligned result buffer */
782 test_structure_5
*ts5_result
=
783 (test_structure_5
*) malloc (sizeof(test_structure_5
));
787 values
[0] = &ts5_arg1
;
788 values
[1] = &ts5_arg2
;
790 /* Initialize the cif */
791 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 2, &ts5_type
, args
) == FFI_OK
);
798 ffi_call (&cif
, FFI_FN(struct5
), ts5_result
, values
);
800 if (ts5_result
->c1
== 7
801 && ts5_result
->c2
== 3)
802 puts ("structure test 5 ok!");
804 puts ("Structure test 5 found GCC's structure passing bug.");
811 test_structure_6 ts6_arg
;
813 /* This is a hack to get a properly aligned result buffer */
814 test_structure_6
*ts6_result
=
815 (test_structure_6
*) malloc (sizeof(test_structure_6
));
818 values
[0] = &ts6_arg
;
820 /* Initialize the cif */
821 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1, &ts6_type
, args
) == FFI_OK
);
826 printf ("%g\n", ts6_arg
.f
);
827 printf ("%g\n", ts6_arg
.d
);
829 ffi_call(&cif
, FFI_FN(struct6
), ts6_result
, values
);
831 printf ("%g\n", ts6_result
->f
);
832 printf ("%g\n", ts6_result
->d
);
834 CHECK(ts6_result
->f
== 5.55f
+ 1);
835 CHECK(ts6_result
->d
== 6.66 + 1);
837 printf("structure test 6 ok!\n");
844 test_structure_7 ts7_arg
;
846 /* This is a hack to get a properly aligned result buffer */
847 test_structure_7
*ts7_result
=
848 (test_structure_7
*) malloc (sizeof(test_structure_7
));
851 values
[0] = &ts7_arg
;
853 /* Initialize the cif */
854 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1, &ts7_type
, args
) == FFI_OK
);
860 printf ("%g\n", ts7_arg
.f1
);
861 printf ("%g\n", ts7_arg
.f2
);
862 printf ("%g\n", ts7_arg
.d
);
864 ffi_call(&cif
, FFI_FN(struct7
), ts7_result
, values
);
866 printf ("%g\n", ts7_result
->f1
);
867 printf ("%g\n", ts7_result
->f2
);
868 printf ("%g\n", ts7_result
->d
);
870 CHECK(ts7_result
->f1
== 5.55f
+ 1);
871 CHECK(ts7_result
->f2
== 55.5f
+ 1);
872 CHECK(ts7_result
->d
== 6.66 + 1);
874 printf("structure test 7 ok!\n");
881 test_structure_8 ts8_arg
;
883 /* This is a hack to get a properly aligned result buffer */
884 test_structure_8
*ts8_result
=
885 (test_structure_8
*) malloc (sizeof(test_structure_8
));
888 values
[0] = &ts8_arg
;
890 /* Initialize the cif */
891 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1, &ts8_type
, args
) == FFI_OK
);
898 printf ("%g\n", ts8_arg
.f1
);
899 printf ("%g\n", ts8_arg
.f2
);
900 printf ("%g\n", ts8_arg
.f3
);
901 printf ("%g\n", ts8_arg
.f4
);
903 ffi_call(&cif
, FFI_FN(struct8
), ts8_result
, values
);
905 printf ("%g\n", ts8_result
->f1
);
906 printf ("%g\n", ts8_result
->f2
);
907 printf ("%g\n", ts8_result
->f3
);
908 printf ("%g\n", ts8_result
->f4
);
910 CHECK(ts8_result
->f1
== 5.55f
+ 1);
911 CHECK(ts8_result
->f2
== 55.5f
+ 1);
912 CHECK(ts8_result
->f3
== -5.55f
+ 1);
913 CHECK(ts8_result
->f4
== -55.5f
+ 1);
915 printf("structure test 8 ok!\n");
922 test_structure_9 ts9_arg
;
924 /* This is a hack to get a properly aligned result buffer */
925 test_structure_9
*ts9_result
=
926 (test_structure_9
*) malloc (sizeof(test_structure_9
));
929 values
[0] = &ts9_arg
;
931 /* Initialize the cif */
932 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 1, &ts9_type
, args
) == FFI_OK
);
937 printf ("%g\n", ts9_arg
.f
);
938 printf ("%d\n", ts9_arg
.i
);
940 ffi_call(&cif
, FFI_FN(struct9
), ts9_result
, values
);
942 printf ("%g\n", ts9_result
->f
);
943 printf ("%d\n", ts9_result
->i
);
945 CHECK(ts9_result
->f
== 5.55f
+ 1);
946 CHECK(ts9_result
->i
== 5 + 1);
948 printf("structure test 9 ok!\n");
954 printf("Structure passing doesn't work on Win32.\n");
955 #endif /* X86_WIN32 */
958 /* A simple closure test */
961 ffi_type
* cl_arg_types
[3];
963 cl_arg_types
[0] = &ffi_type_sint
;
964 cl_arg_types
[1] = &ffi_type_float
;
965 cl_arg_types
[2] = NULL
;
967 /* Initialize the cif */
968 CHECK(ffi_prep_cif(&cif
, FFI_DEFAULT_ABI
, 2,
969 &ffi_type_sint
, cl_arg_types
) == FFI_OK
);
971 CHECK(ffi_prep_closure(&cl
, &cif
, closure_test_fn
,
972 (void *) 3 /* userdata */)
974 CHECK((*((closure_test_type
)(&cl
)))(1, 2.0) == 6);
978 /* If we arrived here, all is good */
979 (void) puts("\nLooks good. No surprises.\n");