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);
156 static test_structure_1 struct1(test_structure_1 ts)
167 static test_structure_2 struct2(test_structure_2 ts)
175 static test_structure_3 struct3(test_structure_3 ts)
182 static test_structure_4 struct4(test_structure_4 ts)
184 ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
189 static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
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)
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[])
210 ffi_type *args[MAX_ARGS];
211 void *values[MAX_ARGS];
225 #if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
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];
244 ts1_type.alignment = 0;
245 ts1_type.type = FFI_TYPE_STRUCT;
248 ts2_type.alignment = 0;
249 ts2_type.type = FFI_TYPE_STRUCT;
252 ts3_type.alignment = 0;
253 ts3_type.type = FFI_TYPE_STRUCT;
256 ts4_type.alignment = 0;
257 ts4_type.type = FFI_TYPE_STRUCT;
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;
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.");
299 args[0] = &ffi_type_sint64;
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++)
309 ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
310 CHECK(rlonglong == ll);
313 for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
316 ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
317 CHECK(rlonglong == ll);
321 args[0] = &ffi_type_schar;
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@*/)
332 ffi_call(&cif, FFI_FN(return_sc), &rint, values);
333 CHECK(rint == (int) sc);
336 args[0] = &ffi_type_uchar;
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@*/)
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");
357 /* float arg tests */
359 args[0] = &ffi_type_float;
362 /* Initialize the cif */
363 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
364 &ffi_type_longdouble, args) == FFI_OK);
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));
375 ffi_call(&cif, FFI_FN(ldblit), &ld, values);
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);
384 /* These are not always the same!! Check for a reasonable delta */
386 if (ld - ldblit(f) < LDBL_EPSILON)
388 puts("long double return value tests ok!");
393 /* float arg tests */
395 args[0] = &ffi_type_sint;
397 args[1] = &ffi_type_float;
399 args[2] = &ffi_type_double;
401 args[3] = &ffi_type_longdouble;
403 args[4] = &ffi_type_sint;
406 /* Initialize the cif */
407 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
408 &ffi_type_sint, args) == FFI_OK);
412 d = (double)1.0/(double)3.0;
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");
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);
438 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
442 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
445 s = "1234567890123456789012345";
446 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
449 printf("strlen tests passed\n");
452 /* float arg tests */
454 args[0] = &ffi_type_float;
457 /* Initialize the cif */
458 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
459 &ffi_type_double, args) == FFI_OK);
463 ffi_call(&cif, FFI_FN(dblit), &d, values);
465 /* These are not always the same!! Check for a reasonable delta */
467 CHECK(d - dblit(f) < DBL_EPSILON);
470 printf("double return value tests ok!\n");
478 for (ul = 0; ul < 13; ul++)
480 args[ul] = &ffi_type_float;
481 values[ul] = &fa[ul];
485 /* Initialize the cif */
486 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
487 &ffi_type_float, args) == FFI_OK);
490 ff = many(fa[0], fa[1],
495 fa[10],fa[11],fa[12]);
498 ffi_call(&cif, FFI_FN(many), &f, values);
501 if (f - ff < FLT_EPSILON)
503 printf("many arg tests ok!\n");
506 printf("many arg tests failed! This is a gcc bug.\n");
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;
523 /* Initialize the cif */
524 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
525 &ffi_type_sint, args) == FFI_OK);
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)
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 */
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));
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);
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");
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));
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);
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");
611 test_structure_3 ts3_arg;
612 test_structure_3 *ts3_result =
613 (test_structure_3 *) malloc (sizeof(test_structure_3));
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);
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!");
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.");
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));
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);
661 ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
663 if (ts4_result->ui3 == 2U * 3U * 4U)
664 puts ("structure test 4 ok!");
666 puts ("Structure test 4 found GCC's structure passing bug.");
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));
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);
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!");
699 puts ("Structure test 5 found GCC's structure passing bug.");
705 printf("Structure passing doesn't work on Win32.\n");
706 #endif /* X86_WIN32 */
709 /* A simple closure test */
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 */)
725 CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
729 /* If we arrived here, all is good */
730 (void) puts("\nLooks good. No surprises.\n");