source: vendor/gcc/3.2.2/libffi/src/ffitest.c

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 16.8 KB
Line 
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
37static 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
47static size_t my_strlen(char *s)
48{
49 return (strlen(s));
50}
51
52static 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
60static signed char return_sc(signed char sc)
61{
62 return sc;
63}
64
65static unsigned char return_uc(unsigned char uc)
66{
67 return uc;
68}
69
70static long long return_ll(long long ll)
71{
72 return ll;
73}
74
75static 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
91static 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
115static double dblit(float f)
116{
117 return f/3.0;
118}
119
120static long double ldblit(float f)
121{
122 return (long double) (((long double) f)/ (long double) 3.0);
123}
124
125typedef struct
126{
127 unsigned char uc;
128 double d;
129 unsigned int ui;
130} test_structure_1;
131
132typedef struct
133{
134 double d1;
135 double d2;
136} test_structure_2;
137
138typedef struct
139{
140 int si;
141} test_structure_3;
142
143typedef struct
144{
145 unsigned ui1;
146 unsigned ui2;
147 unsigned ui3;
148} test_structure_4;
149
150typedef struct
151{
152 char c1;
153 char c2;
154} test_structure_5;
155
156static 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
167static test_structure_2 struct2(test_structure_2 ts)
168{
169 ts.d1--;
170 ts.d2--;
171
172 return ts;
173}
174
175static test_structure_3 struct3(test_structure_3 ts)
176{
177 ts.si = -(ts.si*2);
178
179 return ts;
180}
181
182static test_structure_4 struct4(test_structure_4 ts)
183{
184 ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
185
186 return ts;
187}
188
189static 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. */
199static 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
205typedef int (*closure_test_type)(int, float);
206
207int 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] = &ll;
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] = &sc;
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] = &sc;
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
Note: See TracBrowser for help on using the repository browser.