1 /* -----------------------------------------------------------------------
2 ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions
4 $Id: ffitest.c,v 1.1.1.1 1998/11/29 16:48:16 green Exp $
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 ``Software''), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 ----------------------------------------------------------------------- */
32 /* This is lame. Long double support is barely there under SunOS 4.x */
33 #if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16)
34 #define BROKEN_LONG_DOUBLE
37 #define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0
39 static int fail(char *file, int line)
41 fprintf(stderr, "Test failure: %s line %d\n", file, line);
49 static size_t my_strlen(char *s)
54 static int promotion(signed char sc, signed short ss,
55 unsigned char uc, unsigned short us)
57 int r = (int) sc + (int) ss + (int) uc + (int) us;
62 static signed char return_sc(signed char sc)
67 static unsigned char return_uc(unsigned char uc)
72 static long long return_ll(long long ll)
77 static int floating(int a, float b, double c, long double d, int e)
82 /* This is ifdef'd out for now. long double support under SunOS/gcc
83 is pretty much non-existent. You'll get the odd bus error in library
84 routines like printf(). */
85 printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
88 i = (int) ((float)a/b + ((float)c/(float)d));
93 static float many(float f1,
108 printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
109 (double) f1, (double) f2, (double) f3, (double) f4, (double) f5,
110 (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
111 (double) f11, (double) f12, (double) f13);
114 return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
117 static double dblit(float f)
122 static long double ldblit(float f)
124 return (long double) (((long double) f)/ (long double) 3.0);
158 static test_structure_1 struct1(test_structure_1 ts)
169 static test_structure_2 struct2(test_structure_2 ts)
177 static test_structure_3 struct3(test_structure_3 ts)
184 static test_structure_4 struct4(test_structure_4 ts)
186 ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
191 static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
199 /* Take an int and a float argument, together with int userdata, and */
200 /* return the sum. */
201 static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
204 *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
207 typedef int (*closure_test_type)(int, float);
209 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
212 ffi_type *args[MAX_ARGS];
213 void *values[MAX_ARGS];
227 #if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
239 ffi_type *ts1_type_elements[4];
240 ffi_type *ts2_type_elements[3];
241 ffi_type *ts3_type_elements[2];
242 ffi_type *ts4_type_elements[4];
243 ffi_type *ts5_type_elements[3];
246 ts1_type.alignment = 0;
247 ts1_type.type = FFI_TYPE_STRUCT;
250 ts2_type.alignment = 0;
251 ts2_type.type = FFI_TYPE_STRUCT;
254 ts3_type.alignment = 0;
255 ts3_type.type = FFI_TYPE_STRUCT;
258 ts4_type.alignment = 0;
259 ts4_type.type = FFI_TYPE_STRUCT;
262 ts5_type.alignment = 0;
263 ts5_type.type = FFI_TYPE_STRUCT;
265 /*@-immediatetrans@*/
266 ts1_type.elements = ts1_type_elements;
267 ts2_type.elements = ts2_type_elements;
268 ts3_type.elements = ts3_type_elements;
269 ts4_type.elements = ts4_type_elements;
270 ts5_type.elements = ts5_type_elements;
271 /*@=immediatetrans@*/
273 ts1_type_elements[0] = &ffi_type_uchar;
274 ts1_type_elements[1] = &ffi_type_double;
275 ts1_type_elements[2] = &ffi_type_uint;
276 ts1_type_elements[3] = NULL;
278 ts2_type_elements[0] = &ffi_type_double;
279 ts2_type_elements[1] = &ffi_type_double;
280 ts2_type_elements[2] = NULL;
282 ts3_type_elements[0] = &ffi_type_sint;
283 ts3_type_elements[1] = NULL;
285 ts4_type_elements[0] = &ffi_type_uint;
286 ts4_type_elements[1] = &ffi_type_uint;
287 ts4_type_elements[2] = &ffi_type_uint;
288 ts4_type_elements[3] = NULL;
290 ts5_type_elements[0] = &ffi_type_schar;
291 ts5_type_elements[1] = &ffi_type_schar;
292 ts5_type_elements[2] = NULL;
296 /* return value tests */
298 #if defined(MIPS) /* || defined(ARM) */
299 puts ("long long tests not run. This is a known bug on this architecture.");
301 args[0] = &ffi_type_sint64;
304 /* Initialize the cif */
305 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
306 &ffi_type_sint64, args) == FFI_OK);
308 for (ll = 0LL; ll < 100LL; ll++)
311 ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
312 CHECK(rlonglong == ll);
315 for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
318 ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
319 CHECK(rlonglong == ll);
323 args[0] = &ffi_type_schar;
326 /* Initialize the cif */
327 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
328 &ffi_type_schar, args) == FFI_OK);
330 for (sc = (signed char) -127;
331 sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
334 ffi_call(&cif, FFI_FN(return_sc), &rint, values);
335 CHECK(rint == (int) sc);
338 args[0] = &ffi_type_uchar;
341 /* Initialize the cif */
342 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
343 &ffi_type_uchar, args) == FFI_OK);
345 for (uc = (unsigned char) '\x00';
346 uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
349 ffi_call(&cif, FFI_FN(return_uc), &rint, values);
350 CHECK(rint == (signed int) uc);
353 printf("%lu return value tests run\n", ul);
356 #ifdef BROKEN_LONG_DOUBLE
357 printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
359 /* float arg tests */
361 args[0] = &ffi_type_float;
364 /* Initialize the cif */
365 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
366 &ffi_type_longdouble, args) == FFI_OK);
371 /* This is ifdef'd out for now. long double support under SunOS/gcc
372 is pretty much non-existent. You'll get the odd bus error in library
373 routines like printf(). */
374 printf ("%Lf\n", ldblit(f));
377 ffi_call(&cif, FFI_FN(ldblit), &ld, values);
380 /* This is ifdef'd out for now. long double support under SunOS/gcc
381 is pretty much non-existent. You'll get the odd bus error in library
382 routines like printf(). */
383 printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
386 /* These are not always the same!! Check for a reasonable delta */
388 if (ld - ldblit(f) < LDBL_EPSILON)
390 puts("long double return value tests ok!");
395 /* float arg tests */
397 args[0] = &ffi_type_sint;
399 args[1] = &ffi_type_float;
401 args[2] = &ffi_type_double;
403 args[3] = &ffi_type_longdouble;
405 args[4] = &ffi_type_sint;
408 /* Initialize the cif */
409 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
410 &ffi_type_sint, args) == FFI_OK);
414 d = (double)1.0/(double)3.0;
418 floating (si1, f, d, ld, si2);
420 ffi_call(&cif, FFI_FN(floating), &rint, values);
422 printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
424 CHECK(rint == floating(si1, f, d, ld, si2));
426 printf("float arg tests ok!\n");
432 args[0] = &ffi_type_pointer;
433 values[0] = (void*) &s;
435 /* Initialize the cif */
436 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
437 &ffi_type_sint, args) == FFI_OK);
440 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
444 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
447 s = "1234567890123456789012345";
448 ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
451 printf("strlen tests passed\n");
454 /* float arg tests */
456 args[0] = &ffi_type_float;
459 /* Initialize the cif */
460 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
461 &ffi_type_double, args) == FFI_OK);
465 ffi_call(&cif, FFI_FN(dblit), &d, values);
467 /* These are not always the same!! Check for a reasonable delta */
469 CHECK(d - dblit(f) < DBL_EPSILON);
472 printf("double return value tests ok!\n");
480 for (ul = 0; ul < 13; ul++)
482 args[ul] = &ffi_type_float;
483 values[ul] = &fa[ul];
487 /* Initialize the cif */
488 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13,
489 &ffi_type_float, args) == FFI_OK);
492 ff = many(fa[0], fa[1],
497 fa[10],fa[11],fa[12]);
500 ffi_call(&cif, FFI_FN(many), &f, values);
503 if (f - ff < FLT_EPSILON)
505 printf("many arg tests ok!\n");
508 printf("many arg tests failed! This is a gcc bug.\n");
514 /* promotion tests */
516 args[0] = &ffi_type_schar;
517 args[1] = &ffi_type_sshort;
518 args[2] = &ffi_type_uchar;
519 args[3] = &ffi_type_ushort;
525 /* Initialize the cif */
526 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4,
527 &ffi_type_sint, args) == FFI_OK);
532 for (sc = (signed char) -127;
533 sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
534 for (ss = -30000; ss <= 30000; ss += 10000)
535 for (uc = (unsigned char) 0;
536 uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
537 for (us = 0; us <= 60000; us += 10000)
540 ffi_call(&cif, FFI_FN(promotion), &rint, values);
541 CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
543 printf("%lu promotion tests run\n", ul);
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 /* A simple closure test */
708 ffi_type * cl_arg_types[3];
710 cl_arg_types[0] = &ffi_type_sint;
711 cl_arg_types[1] = &ffi_type_float;
712 cl_arg_types[2] = NULL;
714 /* Initialize the cif */
715 CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2,
716 &ffi_type_sint, cl_arg_types) == FFI_OK);
718 CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
719 (void *) 3 /* userdata */)
721 CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
725 /* If we arrived here, all is good */
726 (void) puts("\nLooks good. No surprises.\n");