OSDN Git Service

Port to sparc 32 and 64 Linux.
[pf3gnuchains/gcc-fork.git] / libffi / src / ffitest.c
1 /* -----------------------------------------------------------------------
2    ffitest.c - Copyright (c) 1996, 1997, 1998  Cygnus Solutions
3
4    $Id: ffitest.c,v 1.1.1.1 1998/11/29 16:48:16 green Exp $
5
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:
13
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
16
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    ----------------------------------------------------------------------- */
25
26 #include <ffi.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <float.h>
31
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
35 #endif
36
37 #define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0 
38
39 static int fail(char *file, int line)
40 {
41   fprintf(stderr, "Test failure: %s line %d\n", file, line);
42   exit(EXIT_FAILURE);
43   /*@notreached@*/
44   return 0;
45 }
46
47 #define MAX_ARGS 256
48
49 static size_t my_strlen(char *s)
50 {
51   return (strlen(s));
52 }
53
54 static int promotion(signed char sc, signed short ss, 
55                      unsigned char uc, unsigned short us)
56 {
57   int r = (int) sc + (int) ss + (int) uc + (int) us;
58
59   return r;
60 }
61
62 static signed char return_sc(signed char sc)
63 {
64   return sc;
65 }
66
67 static unsigned char return_uc(unsigned char uc)
68 {
69   return uc;
70 }
71
72 static long long return_ll(long long ll)
73 {
74   return ll;
75 }
76
77 static int floating(int a, float b, double c, long double d, int e)
78 {
79   int i;
80
81 #if 0
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);
86 #endif
87
88   i = (int) ((float)a/b + ((float)c/(float)d));
89
90   return i;
91 }
92
93 static float many(float f1,
94                   float f2,
95                   float f3,
96                   float f4,
97                   float f5,
98                   float f6,
99                   float f7,
100                   float f8,
101                   float f9,
102                   float f10,
103                   float f11,
104                   float f12,
105                   float f13)
106 {
107 #if 0
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);
112 #endif
113
114   return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
115 }
116
117 static double dblit(float f)
118 {
119   return f/3.0;
120 }
121
122 static long double ldblit(float f)
123 {
124   return (long double) (((long double) f)/ (long double) 3.0);
125 }
126
127 typedef struct
128 {
129   unsigned char uc;
130   double d;
131   unsigned int ui;
132 } test_structure_1;
133
134 typedef struct
135 {
136   double d1;
137   double d2;
138 } test_structure_2;
139
140 typedef struct
141 {
142   int si;
143 } test_structure_3;
144
145 typedef struct
146 {
147   unsigned ui1;
148   unsigned ui2;
149   unsigned ui3;
150 } test_structure_4;
151
152 typedef struct
153 {
154   char c1;
155   char c2;
156 } test_structure_5;
157
158 static test_structure_1 struct1(test_structure_1 ts)
159 {
160   /*@-type@*/
161   ts.uc++;
162   /*@=type@*/
163   ts.d--;
164   ts.ui++;
165
166   return ts;
167 }
168
169 static test_structure_2 struct2(test_structure_2 ts)
170 {
171   ts.d1--;
172   ts.d2--;
173
174   return ts;
175 }
176
177 static test_structure_3 struct3(test_structure_3 ts)
178 {
179   ts.si = -(ts.si*2);
180
181   return ts;
182 }
183
184 static test_structure_4 struct4(test_structure_4 ts)
185 {
186   ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
187
188   return ts;
189 }
190
191 static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
192 {
193   ts1.c1 += ts2.c1;
194   ts1.c2 -= ts2.c2;
195
196   return ts1;
197 }
198
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)
202 {
203     *(int*)resp =
204          *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata;
205 }
206
207 typedef int (*closure_test_type)(int, float);
208
209 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
210 {
211   ffi_cif cif;
212   ffi_type *args[MAX_ARGS];
213   void *values[MAX_ARGS];
214   char *s;
215   signed char sc;
216   unsigned char uc;
217   signed short ss;
218   unsigned short us;
219   unsigned long ul;
220   long long ll;
221   float f;
222   double d;
223   long double ld;
224   signed int si1;
225   signed int si2;
226
227 #if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32))
228   long long rint;
229 #else
230   int rint;
231 #endif
232   long long rlonglong;
233
234   ffi_type ts1_type;
235   ffi_type ts2_type;
236   ffi_type ts3_type;
237   ffi_type ts4_type;  
238   ffi_type ts5_type;
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];
244
245   ts1_type.size = 0;
246   ts1_type.alignment = 0;
247   ts1_type.type = FFI_TYPE_STRUCT;
248
249   ts2_type.size = 0;
250   ts2_type.alignment = 0;
251   ts2_type.type = FFI_TYPE_STRUCT;
252
253   ts3_type.size = 0;
254   ts3_type.alignment = 0;
255   ts3_type.type = FFI_TYPE_STRUCT;
256
257   ts4_type.size = 0;
258   ts4_type.alignment = 0;
259   ts4_type.type = FFI_TYPE_STRUCT;
260
261   ts5_type.size = 0;
262   ts5_type.alignment = 0;
263   ts5_type.type = FFI_TYPE_STRUCT;
264
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@*/
272   
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;
277   
278   ts2_type_elements[0] = &ffi_type_double;
279   ts2_type_elements[1] = &ffi_type_double;
280   ts2_type_elements[2] = NULL;
281
282   ts3_type_elements[0] = &ffi_type_sint;
283   ts3_type_elements[1] = NULL;
284
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;
289
290   ts5_type_elements[0] = &ffi_type_schar;
291   ts5_type_elements[1] = &ffi_type_schar;
292   ts5_type_elements[2] = NULL;
293
294   ul = 0;
295
296   /* return value tests */
297   {
298 #if defined(MIPS) /* || defined(ARM) */
299     puts ("long long tests not run. This is a known bug on this architecture.");
300 #else
301     args[0] = &ffi_type_sint64;
302     values[0] = &ll;
303     
304     /* Initialize the cif */
305     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
306                        &ffi_type_sint64, args) == FFI_OK);
307
308     for (ll = 0LL; ll < 100LL; ll++)
309       {
310         ul++;
311         ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
312         CHECK(rlonglong == ll);
313       }
314
315     for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
316       {
317         ul++;
318         ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
319         CHECK(rlonglong == ll);
320       }
321 #endif
322
323     args[0] = &ffi_type_schar;
324     values[0] = &sc;
325     
326     /* Initialize the cif */
327     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
328                        &ffi_type_schar, args) == FFI_OK);
329
330     for (sc = (signed char) -127; 
331          sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
332       {
333         ul++;
334         ffi_call(&cif, FFI_FN(return_sc), &rint, values);
335         CHECK(rint == (int) sc);
336       }
337
338     args[0] = &ffi_type_uchar;
339     values[0] = &uc;
340     
341     /* Initialize the cif */
342     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
343                        &ffi_type_uchar, args) == FFI_OK);
344
345     for (uc = (unsigned char) '\x00'; 
346          uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
347       {
348         ul++;
349         ffi_call(&cif, FFI_FN(return_uc), &rint, values);
350         CHECK(rint == (signed int) uc);
351       }
352
353     printf("%lu return value tests run\n", ul);
354   }
355
356 #ifdef BROKEN_LONG_DOUBLE
357   printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
358 #else
359   /* float arg tests */
360   {
361     args[0] = &ffi_type_float;
362     values[0] = &f;
363
364     /* Initialize the cif */
365     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
366                        &ffi_type_longdouble, args) == FFI_OK);
367
368     f = 3.14159;
369
370 #if 0
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));
375 #endif
376     ld = 666;
377     ffi_call(&cif, FFI_FN(ldblit), &ld, values);
378
379 #if 0
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);
384 #endif
385
386     /* These are not always the same!! Check for a reasonable delta */
387     /*@-realcompare@*/
388     if (ld - ldblit(f) < LDBL_EPSILON)
389     /*@=realcompare@*/
390         puts("long double return value tests ok!");
391     else
392         CHECK(0);
393   }
394
395   /* float arg tests */
396   {
397     args[0] = &ffi_type_sint;
398     values[0] = &si1;
399     args[1] = &ffi_type_float;
400     values[1] = &f;
401     args[2] = &ffi_type_double;
402     values[2] = &d;
403     args[3] = &ffi_type_longdouble;
404     values[3] = &ld;
405     args[4] = &ffi_type_sint;
406     values[4] = &si2;
407     
408     /* Initialize the cif */
409     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
410                        &ffi_type_sint, args) == FFI_OK);
411
412     si1 = 6;
413     f = 3.14159;
414     d = (double)1.0/(double)3.0;
415     ld = 2.71828182846L;
416     si2 = 10;
417
418     floating (si1, f, d, ld, si2);
419
420     ffi_call(&cif, FFI_FN(floating), &rint, values);
421
422     printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2));
423
424     CHECK(rint == floating(si1, f, d, ld, si2));
425
426     printf("float arg tests ok!\n");
427   }
428 #endif
429
430   /* strlen tests */
431   {
432     args[0] = &ffi_type_pointer;
433     values[0] = (void*) &s;
434     
435     /* Initialize the cif */
436     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
437                        &ffi_type_sint, args) == FFI_OK);
438
439     s = "a";
440     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
441     CHECK(rint == 1);
442
443     s = "1234567";
444     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
445     CHECK(rint == 7);
446
447     s = "1234567890123456789012345";
448     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
449     CHECK(rint == 25);
450
451     printf("strlen tests passed\n");
452   }
453
454   /* float arg tests */
455   {
456     args[0] = &ffi_type_float;
457     values[0] = &f;
458     
459     /* Initialize the cif */
460     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
461                        &ffi_type_double, args) == FFI_OK);
462
463     f = 3.14159;
464
465     ffi_call(&cif, FFI_FN(dblit), &d, values);
466
467     /* These are not always the same!! Check for a reasonable delta */
468     /*@-realcompare@*/
469     CHECK(d - dblit(f) < DBL_EPSILON);
470     /*@=realcompare@*/
471
472     printf("double return value tests ok!\n");
473   }
474
475   /* many arg tests */
476   {
477     float ff;
478     float fa[13];
479     
480     for (ul = 0; ul < 13; ul++)
481       {
482         args[ul] = &ffi_type_float;
483         values[ul] = &fa[ul];
484         fa[ul] = (float) ul;
485       }
486
487     /* Initialize the cif */
488     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
489                        &ffi_type_float, args) == FFI_OK);
490
491     /*@-usedef@*/
492     ff =  many(fa[0], fa[1],
493                fa[2], fa[3],
494                fa[4], fa[5],
495                fa[6], fa[7],
496                fa[8], fa[9],
497                fa[10],fa[11],fa[12]);
498     /*@=usedef@*/
499
500     ffi_call(&cif, FFI_FN(many), &f, values);
501
502     /*@-realcompare@*/
503     if (f - ff < FLT_EPSILON)
504     /*@=realcompare@*/
505         printf("many arg tests ok!\n");
506     else
507 #ifdef POWERPC
508         printf("many arg tests failed!  This is a gcc bug.\n");
509 #else
510         CHECK(0);
511 #endif
512   }
513
514   /* promotion tests */
515   {
516     args[0] = &ffi_type_schar;
517     args[1] = &ffi_type_sshort;
518     args[2] = &ffi_type_uchar;
519     args[3] = &ffi_type_ushort;
520     values[0] = &sc;
521     values[1] = &ss;
522     values[2] = &uc;
523     values[3] = &us;
524     
525     /* Initialize the cif */
526     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
527                        &ffi_type_sint, args) == FFI_OK);
528
529     us = 0;
530     ul = 0;
531
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)
538             {
539               ul++;
540               ffi_call(&cif, FFI_FN(promotion), &rint, values);
541               CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us);
542             }
543     printf("%lu promotion tests run\n", ul);
544   }
545
546   /* struct tests */
547   {
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));
552
553     args[0] = &ts1_type;
554     values[0] = &ts1_arg;
555     
556     /* Initialize the cif */
557     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
558                        &ts1_type, args) == FFI_OK);
559
560     ts1_arg.uc = '\x01';
561     ts1_arg.d = 3.14159;
562     ts1_arg.ui = 555;
563
564     ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
565
566     CHECK(ts1_result->ui == 556);
567     CHECK(ts1_result->d == 3.14159 - 1);
568
569     puts ("structure test 1 ok!\n");
570
571     free (ts1_result);
572   }
573
574   /* struct tests */
575   {
576     test_structure_2 ts2_arg;
577
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));
581
582     args[0] = &ts2_type;
583     values[0] = &ts2_arg;
584     
585     /* Initialize the cif */
586     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
587                        &ts2_type, args) == FFI_OK);
588
589     ts2_arg.d1 = 5.55;
590     ts2_arg.d2 = 6.66;
591
592     printf ("%g\n", ts2_result->d1);
593     printf ("%g\n", ts2_result->d2);
594
595     ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
596
597     printf ("%g\n", ts2_result->d1);
598     printf ("%g\n", ts2_result->d2);
599     
600     CHECK(ts2_result->d1 == 5.55 - 1);
601     CHECK(ts2_result->d2 == 6.66 - 1);
602
603     printf("structure test 2 ok!\n");
604
605     free (ts2_result);
606   }
607
608   /* struct tests */
609   {
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));
614
615     args[0] = &ts3_type;
616     values[0] = &ts3_arg;
617     
618     /* Initialize the cif */
619     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
620                        &ts3_type, args) == FFI_OK);
621
622     ts3_arg.si = -123;
623     compare_value = ts3_arg.si;
624
625     ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
626
627     printf ("%d %d\n", ts3_result->si, -(compare_value*2));
628
629     if (ts3_result->si == -(ts3_arg.si*2))
630         puts ("structure test 3 ok!");
631     else
632       {
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.");
637       }
638
639     free (ts3_result);
640   }
641
642   /* struct tests */
643   {
644     test_structure_4 ts4_arg;
645
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));
649
650     args[0] = &ts4_type;
651     values[0] = &ts4_arg;
652     
653     /* Initialize the cif */
654     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
655                        &ts4_type, args) == FFI_OK);
656
657     ts4_arg.ui1 = 2;
658     ts4_arg.ui2 = 3;
659     ts4_arg.ui3 = 4;
660
661     ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
662     
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.");
667
668     free (ts4_result);
669   }
670
671   /* struct tests */
672   {
673     test_structure_5 ts5_arg1, ts5_arg2;
674
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));
678
679     args[0] = &ts5_type;
680     args[1] = &ts5_type;
681     values[0] = &ts5_arg1;
682     values[1] = &ts5_arg2;
683     
684     /* Initialize the cif */
685     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
686                        &ts5_type, args) == FFI_OK);
687
688     ts5_arg1.c1 = 2;
689     ts5_arg1.c2 = 6;
690     ts5_arg2.c1 = 5;
691     ts5_arg2.c2 = 3;
692
693     ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
694     
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.");
700
701     free (ts5_result);
702   }
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