OSDN Git Service

Merge basic-improvements-branch to trunk
[pf3gnuchains/gcc-fork.git] / libffi / src / ffitest.c
1 /* -----------------------------------------------------------------------
2    ffitest.c - Copyright (c) 1996, 1997, 1998, 2002  Red Hat, Inc.
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
37 static 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
47 static size_t my_strlen(char *s)
48 {
49   return (strlen(s));
50 }
51
52 #ifdef X86_WIN32
53 static size_t __attribute__((stdcall)) my_stdcall_strlen(char *s)
54 {
55   return (strlen(s));
56 }
57 #endif /* X86_WIN32 */
58
59 static int promotion(signed char sc, signed short ss, 
60                      unsigned char uc, unsigned short us)
61 {
62   int r = (int) sc + (int) ss + (int) uc + (int) us;
63
64   return r;
65 }
66
67 static signed char return_sc(signed char sc)
68 {
69   return sc;
70 }
71
72 static unsigned char return_uc(unsigned char uc)
73 {
74   return uc;
75 }
76
77 static long long return_ll(long long ll)
78 {
79   return ll;
80 }
81
82 static int floating(int a, float b, double c, long double d, int e)
83 {
84   int i;
85
86 #if 0
87   /* This is ifdef'd out for now. long double support under SunOS/gcc
88      is pretty much non-existent.  You'll get the odd bus error in library
89      routines like printf().  */
90   printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e);
91 #endif
92
93   i = (int) ((float)a/b + ((float)c/(float)d));
94
95   return i;
96 }
97
98 static float many(float f1,
99                   float f2,
100                   float f3,
101                   float f4,
102                   float f5,
103                   float f6,
104                   float f7,
105                   float f8,
106                   float f9,
107                   float f10,
108                   float f11,
109                   float f12,
110                   float f13)
111 {
112 #if 0
113   printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n",
114          (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, 
115          (double) f6, (double) f7, (double) f8, (double) f9, (double) f10,
116          (double) f11, (double) f12, (double) f13);
117 #endif
118
119   return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
120 }
121
122 #ifdef X86_WIN32
123 static float __attribute__((stdcall)) stdcall_many(float f1,
124                                                    float f2,
125                                                    float f3,
126                                                    float f4,
127                                                    float f5,
128                                                    float f6,
129                                                    float f7,
130                                                    float f8,
131                                                    float f9,
132                                                    float f10,
133                                                    float f11,
134                                                    float f12,
135                                                    float f13)
136 {
137   return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13);
138 }
139 #endif /* X86_WIN32 */
140
141 static double dblit(float f)
142 {
143   return f/3.0;
144 }
145
146 static long double ldblit(float f)
147 {
148   return (long double) (((long double) f)/ (long double) 3.0);
149 }
150
151 typedef struct
152 {
153   unsigned char uc;
154   double d;
155   unsigned int ui;
156 } test_structure_1;
157
158 typedef struct
159 {
160   double d1;
161   double d2;
162 } test_structure_2;
163
164 typedef struct
165 {
166   int si;
167 } test_structure_3;
168
169 typedef struct
170 {
171   unsigned ui1;
172   unsigned ui2;
173   unsigned ui3;
174 } test_structure_4;
175
176 typedef struct
177 {
178   char c1;
179   char c2;
180 } test_structure_5;
181
182 typedef struct
183 {
184   float f;
185   double d;
186 } test_structure_6;
187
188 typedef struct
189 {
190   float f1;
191   float f2;
192   double d;
193 } test_structure_7;
194
195 typedef struct
196 {
197   float f1;
198   float f2;
199   float f3;
200   float f4;
201 } test_structure_8;
202
203 typedef struct
204 {
205   float f;
206   int i;
207 } test_structure_9;
208
209 static test_structure_1 struct1(test_structure_1 ts)
210 {
211   /*@-type@*/
212   ts.uc++;
213   /*@=type@*/
214   ts.d--;
215   ts.ui++;
216
217   return ts;
218 }
219
220 static test_structure_2 struct2(test_structure_2 ts)
221 {
222   ts.d1--;
223   ts.d2--;
224
225   return ts;
226 }
227
228 static test_structure_3 struct3(test_structure_3 ts)
229 {
230   ts.si = -(ts.si*2);
231
232   return ts;
233 }
234
235 static test_structure_4 struct4(test_structure_4 ts)
236 {
237   ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3;
238
239   return ts;
240 }
241
242 static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2)
243 {
244   ts1.c1 += ts2.c1;
245   ts1.c2 -= ts2.c2;
246
247   return ts1;
248 }
249
250 static test_structure_6 struct6 (test_structure_6 ts)
251 {
252   ts.f += 1;
253   ts.d += 1;
254
255   return ts;
256 }
257
258 static test_structure_7 struct7 (test_structure_7 ts)
259 {
260   ts.f1 += 1;
261   ts.f2 += 1;
262   ts.d += 1;
263
264   return ts;
265 }
266
267 static test_structure_8 struct8 (test_structure_8 ts)
268 {
269   ts.f1 += 1;
270   ts.f2 += 1;
271   ts.f3 += 1;
272   ts.f4 += 1;
273
274   return ts;
275 }
276
277 static test_structure_9 struct9 (test_structure_9 ts)
278 {
279   ts.f += 1;
280   ts.i += 1;
281
282   return ts;
283 }
284
285 /* Take an int and a float argument, together with int userdata, and    */
286 /* return the sum.                                                      */
287 #if FFI_CLOSURES
288 static void
289 closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata)
290 {
291   *(ffi_arg*)resp = *(int*)args[0] + (int)(*(float*)args[1]) + (int)(long)userdata;
292 }
293
294 typedef int (*closure_test_type)(int, float);
295 #endif
296
297 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
298 {
299   ffi_cif cif;
300   ffi_type *args[MAX_ARGS];
301   void *values[MAX_ARGS];
302   char *s;
303   signed char sc;
304   unsigned char uc;
305   signed short ss;
306   unsigned short us;
307   unsigned long ul;
308   long long ll;
309   float f;
310   double d;
311   long double ld;
312   signed int si1;
313   signed int si2;
314
315   ffi_arg rint;
316   long long rlonglong;
317
318   ffi_type ts1_type;
319   ffi_type ts2_type;
320   ffi_type ts3_type;
321   ffi_type ts4_type;  
322   ffi_type ts5_type;
323   ffi_type ts6_type;
324   ffi_type ts7_type;
325   ffi_type ts8_type;
326   ffi_type ts9_type;
327   ffi_type *ts1_type_elements[4];
328   ffi_type *ts2_type_elements[3];
329   ffi_type *ts3_type_elements[2];
330   ffi_type *ts4_type_elements[4];
331   ffi_type *ts5_type_elements[3];
332   ffi_type *ts6_type_elements[3];
333   ffi_type *ts7_type_elements[4];
334   ffi_type *ts8_type_elements[5];
335   ffi_type *ts9_type_elements[3];
336
337   ts1_type.size = 0;
338   ts1_type.alignment = 0;
339   ts1_type.type = FFI_TYPE_STRUCT;
340
341   ts2_type.size = 0;
342   ts2_type.alignment = 0;
343   ts2_type.type = FFI_TYPE_STRUCT;
344
345   ts3_type.size = 0;
346   ts3_type.alignment = 0;
347   ts3_type.type = FFI_TYPE_STRUCT;
348
349   ts4_type.size = 0;
350   ts4_type.alignment = 0;
351   ts4_type.type = FFI_TYPE_STRUCT;
352
353   ts5_type.size = 0;
354   ts5_type.alignment = 0;
355   ts5_type.type = FFI_TYPE_STRUCT;
356
357   ts6_type.size = 0;
358   ts6_type.alignment = 0;
359   ts6_type.type = FFI_TYPE_STRUCT;
360
361   ts7_type.size = 0;
362   ts7_type.alignment = 0;
363   ts7_type.type = FFI_TYPE_STRUCT;
364
365   ts8_type.size = 0;
366   ts8_type.alignment = 0;
367   ts8_type.type = FFI_TYPE_STRUCT;
368
369   ts9_type.size = 0;
370   ts9_type.alignment = 0;
371   ts9_type.type = FFI_TYPE_STRUCT;
372
373   /*@-immediatetrans@*/
374   ts1_type.elements = ts1_type_elements;
375   ts2_type.elements = ts2_type_elements;
376   ts3_type.elements = ts3_type_elements;
377   ts4_type.elements = ts4_type_elements;
378   ts5_type.elements = ts5_type_elements;
379   ts6_type.elements = ts6_type_elements;
380   ts7_type.elements = ts7_type_elements;
381   ts8_type.elements = ts8_type_elements;
382   ts9_type.elements = ts9_type_elements;
383   /*@=immediatetrans@*/
384   
385   ts1_type_elements[0] = &ffi_type_uchar;
386   ts1_type_elements[1] = &ffi_type_double;
387   ts1_type_elements[2] = &ffi_type_uint;
388   ts1_type_elements[3] = NULL;
389   
390   ts2_type_elements[0] = &ffi_type_double;
391   ts2_type_elements[1] = &ffi_type_double;
392   ts2_type_elements[2] = NULL;
393
394   ts3_type_elements[0] = &ffi_type_sint;
395   ts3_type_elements[1] = NULL;
396
397   ts4_type_elements[0] = &ffi_type_uint;
398   ts4_type_elements[1] = &ffi_type_uint;
399   ts4_type_elements[2] = &ffi_type_uint;
400   ts4_type_elements[3] = NULL;
401
402   ts5_type_elements[0] = &ffi_type_schar;
403   ts5_type_elements[1] = &ffi_type_schar;
404   ts5_type_elements[2] = NULL;
405
406   ts6_type_elements[0] = &ffi_type_float;
407   ts6_type_elements[1] = &ffi_type_double;
408   ts6_type_elements[2] = NULL;
409
410   ts7_type_elements[0] = &ffi_type_float;
411   ts7_type_elements[1] = &ffi_type_float;
412   ts7_type_elements[2] = &ffi_type_double;
413   ts7_type_elements[3] = NULL;
414
415   ts8_type_elements[0] = &ffi_type_float;
416   ts8_type_elements[1] = &ffi_type_float;
417   ts8_type_elements[2] = &ffi_type_float;
418   ts8_type_elements[3] = &ffi_type_float;
419   ts8_type_elements[4] = NULL;
420
421   ts9_type_elements[0] = &ffi_type_float;
422   ts9_type_elements[1] = &ffi_type_sint;
423   ts9_type_elements[2] = NULL;
424
425   ul = 0;
426
427   /* return value tests */
428   {
429 #if defined(MIPS) /* || defined(ARM) */
430     puts ("long long tests not run. This is a known bug on this architecture.");
431 #else
432     args[0] = &ffi_type_sint64;
433     values[0] = &ll;
434     
435     /* Initialize the cif */
436     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
437                        &ffi_type_sint64, args) == FFI_OK);
438
439     for (ll = 0LL; ll < 100LL; ll++)
440       {
441         ul++;
442         ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
443         CHECK(rlonglong == ll);
444       }
445
446     for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
447       {
448         ul++;
449         ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
450         CHECK(rlonglong == ll);
451       }
452 #endif
453
454     args[0] = &ffi_type_schar;
455     values[0] = &sc;
456     
457     /* Initialize the cif */
458     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
459                        &ffi_type_schar, args) == FFI_OK);
460
461     for (sc = (signed char) -127; 
462          sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
463       {
464         ul++;
465         ffi_call(&cif, FFI_FN(return_sc), &rint, values);
466         CHECK(rint == (ffi_arg) sc);
467       }
468
469     args[0] = &ffi_type_uchar;
470     values[0] = &uc;
471     
472     /* Initialize the cif */
473     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
474                        &ffi_type_uchar, args) == FFI_OK);
475
476     for (uc = (unsigned char) '\x00'; 
477          uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
478       {
479         ul++;
480         ffi_call(&cif, FFI_FN(return_uc), &rint, values);
481         CHECK(rint == (signed int) uc);
482       }
483
484     printf("%lu return value tests run\n", ul);
485   }
486
487 #ifdef BROKEN_LONG_DOUBLE
488   printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
489 #else
490   /* float arg tests */
491   {
492     args[0] = &ffi_type_float;
493     values[0] = &f;
494
495     /* Initialize the cif */
496     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
497                        &ffi_type_longdouble, args) == FFI_OK);
498
499     f = 3.14159;
500
501 #if 0
502   /* This is ifdef'd out for now. long double support under SunOS/gcc
503      is pretty much non-existent.  You'll get the odd bus error in library
504      routines like printf().  */
505     printf ("%Lf\n", ldblit(f));
506 #endif
507     ld = 666;
508     ffi_call(&cif, FFI_FN(ldblit), &ld, values);
509
510 #if 0
511   /* This is ifdef'd out for now. long double support under SunOS/gcc
512      is pretty much non-existent.  You'll get the odd bus error in library
513      routines like printf().  */
514     printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
515 #endif
516
517     /* These are not always the same!! Check for a reasonable delta */
518     /*@-realcompare@*/
519     if (ld - ldblit(f) < LDBL_EPSILON)
520     /*@=realcompare@*/
521         puts("long double return value tests ok!");
522     else
523         CHECK(0);
524   }
525
526   /* float arg tests */
527   {
528     args[0] = &ffi_type_sint;
529     values[0] = &si1;
530     args[1] = &ffi_type_float;
531     values[1] = &f;
532     args[2] = &ffi_type_double;
533     values[2] = &d;
534     args[3] = &ffi_type_longdouble;
535     values[3] = &ld;
536     args[4] = &ffi_type_sint;
537     values[4] = &si2;
538     
539     /* Initialize the cif */
540     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
541                        &ffi_type_sint, args) == FFI_OK);
542
543     si1 = 6;
544     f = 3.14159;
545     d = (double)1.0/(double)3.0;
546     ld = 2.71828182846L;
547     si2 = 10;
548
549     floating (si1, f, d, ld, si2);
550
551     ffi_call(&cif, FFI_FN(floating), &rint, values);
552
553     printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld, si2));
554
555     CHECK(rint == floating(si1, f, d, ld, si2));
556
557     printf("float arg tests ok!\n");
558   }
559 #endif
560
561   /* strlen tests */
562   {
563     args[0] = &ffi_type_pointer;
564     values[0] = (void*) &s;
565     
566     /* Initialize the cif */
567     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
568                        &ffi_type_sint, args) == FFI_OK);
569
570     s = "a";
571     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
572     CHECK(rint == 1);
573
574     s = "1234567";
575     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
576     CHECK(rint == 7);
577
578     s = "1234567890123456789012345";
579     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
580     CHECK(rint == 25);
581
582     printf("strlen tests passed\n");
583   }
584
585   /* float arg tests */
586   {
587     args[0] = &ffi_type_float;
588     values[0] = &f;
589     
590     /* Initialize the cif */
591     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
592                        &ffi_type_double, args) == FFI_OK);
593
594     f = 3.14159;
595
596     ffi_call(&cif, FFI_FN(dblit), &d, values);
597
598     /* These are not always the same!! Check for a reasonable delta */
599     /*@-realcompare@*/
600     CHECK(d - dblit(f) < DBL_EPSILON);
601     /*@=realcompare@*/
602
603     printf("double return value tests ok!\n");
604   }
605
606   /* many arg tests */
607   {
608     float ff;
609     float fa[13];
610     
611     for (ul = 0; ul < 13; ul++)
612       {
613         args[ul] = &ffi_type_float;
614         values[ul] = &fa[ul];
615         fa[ul] = (float) ul;
616       }
617
618     /* Initialize the cif */
619     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
620                        &ffi_type_float, args) == FFI_OK);
621
622     /*@-usedef@*/
623     ff = many (fa[0], fa[1],
624                fa[2], fa[3],
625                fa[4], fa[5],
626                fa[6], fa[7],
627                fa[8], fa[9],
628                fa[10],fa[11],fa[12]);
629     /*@=usedef@*/
630
631     ffi_call(&cif, FFI_FN(many), &f, values);
632
633     /*@-realcompare@*/
634     if (f - ff < FLT_EPSILON)
635     /*@=realcompare@*/
636         printf("many arg tests ok!\n");
637     else
638 #ifdef POWERPC
639         printf("many arg tests failed!  This is a gcc bug.\n");
640 #else
641         CHECK(0);
642 #endif
643   }
644
645   /* promotion tests */
646   {
647     args[0] = &ffi_type_schar;
648     args[1] = &ffi_type_sshort;
649     args[2] = &ffi_type_uchar;
650     args[3] = &ffi_type_ushort;
651     values[0] = &sc;
652     values[1] = &ss;
653     values[2] = &uc;
654     values[3] = &us;
655     
656     /* Initialize the cif */
657     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
658                        &ffi_type_sint, args) == FFI_OK);
659
660     us = 0;
661     ul = 0;
662
663     for (sc = (signed char) -127; 
664          sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
665       for (ss = -30000; ss <= 30000; ss += 10000)
666         for (uc = (unsigned char) 0; 
667              uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
668           for (us = 0; us <= 60000; us += 10000)
669             {
670               ul++;
671               ffi_call(&cif, FFI_FN(promotion), &rint, values);
672               CHECK((int)rint == (signed char) sc + (signed short) ss +
673                     (unsigned char) uc + (unsigned short) us);
674             }
675     printf("%lu promotion tests run\n", ul);
676   }
677
678 #ifndef X86_WIN32 /* Structures dont work on Win32 */
679
680   /* struct tests */
681   {
682     test_structure_1 ts1_arg;
683     /* This is a hack to get a properly aligned result buffer */
684     test_structure_1 *ts1_result = 
685       (test_structure_1 *) malloc (sizeof(test_structure_1));
686
687     args[0] = &ts1_type;
688     values[0] = &ts1_arg;
689     
690     /* Initialize the cif */
691     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
692                        &ts1_type, args) == FFI_OK);
693
694     ts1_arg.uc = '\x01';
695     ts1_arg.d = 3.14159;
696     ts1_arg.ui = 555;
697
698     ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
699
700     CHECK(ts1_result->ui == 556);
701     CHECK(ts1_result->d == 3.14159 - 1);
702
703     puts ("structure test 1 ok!\n");
704
705     free (ts1_result);
706   }
707
708   /* struct tests */
709   {
710     test_structure_2 ts2_arg;
711
712     /* This is a hack to get a properly aligned result buffer */
713     test_structure_2 *ts2_result = 
714       (test_structure_2 *) malloc (sizeof(test_structure_2));
715
716     args[0] = &ts2_type;
717     values[0] = &ts2_arg;
718     
719     /* Initialize the cif */
720     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
721
722     ts2_arg.d1 = 5.55;
723     ts2_arg.d2 = 6.66;
724
725     printf ("%g\n", ts2_result->d1);
726     printf ("%g\n", ts2_result->d2);
727
728     ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
729
730     printf ("%g\n", ts2_result->d1);
731     printf ("%g\n", ts2_result->d2);
732     
733     CHECK(ts2_result->d1 == 5.55 - 1);
734     CHECK(ts2_result->d2 == 6.66 - 1);
735
736     printf("structure test 2 ok!\n");
737
738     free (ts2_result);
739   }
740
741   /* struct tests */
742   {
743     int compare_value;
744     test_structure_3 ts3_arg;
745     test_structure_3 *ts3_result = 
746       (test_structure_3 *) malloc (sizeof(test_structure_3));
747
748     args[0] = &ts3_type;
749     values[0] = &ts3_arg;
750     
751     /* Initialize the cif */
752     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
753                        &ts3_type, args) == FFI_OK);
754
755     ts3_arg.si = -123;
756     compare_value = ts3_arg.si;
757
758     ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
759
760     printf ("%d %d\n", ts3_result->si, -(compare_value*2));
761
762     if (ts3_result->si == -(ts3_arg.si*2))
763         puts ("structure test 3 ok!");
764     else
765       {
766         puts ("Structure test 3 found structure passing bug.");
767         puts ("  Current versions of GCC are not 100% compliant with the");
768         puts ("  n32 ABI.  There is a known problem related to passing");
769         puts ("  small structures.  Send a bug report to the gcc maintainers.");
770       }
771
772     free (ts3_result);
773   }
774
775   /* struct tests */
776   {
777     test_structure_4 ts4_arg;
778
779     /* This is a hack to get a properly aligned result buffer */
780     test_structure_4 *ts4_result = 
781       (test_structure_4 *) malloc (sizeof(test_structure_4));
782
783     args[0] = &ts4_type;
784     values[0] = &ts4_arg;
785     
786     /* Initialize the cif */
787     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
788
789     ts4_arg.ui1 = 2;
790     ts4_arg.ui2 = 3;
791     ts4_arg.ui3 = 4;
792
793     ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
794     
795     if (ts4_result->ui3 == 2U * 3U * 4U)
796       puts ("structure test 4 ok!");
797     else
798       puts ("Structure test 4 found GCC's structure passing bug.");
799
800     free (ts4_result);
801   }
802
803   /* struct tests */
804   {
805     test_structure_5 ts5_arg1, ts5_arg2;
806
807     /* This is a hack to get a properly aligned result buffer */
808     test_structure_5 *ts5_result = 
809       (test_structure_5 *) malloc (sizeof(test_structure_5));
810
811     args[0] = &ts5_type;
812     args[1] = &ts5_type;
813     values[0] = &ts5_arg1;
814     values[1] = &ts5_arg2;
815     
816     /* Initialize the cif */
817     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
818
819     ts5_arg1.c1 = 2;
820     ts5_arg1.c2 = 6;
821     ts5_arg2.c1 = 5;
822     ts5_arg2.c2 = 3;
823
824     ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
825     
826     if (ts5_result->c1 == 7 
827         && ts5_result->c2 == 3)
828       puts ("structure test 5 ok!");
829     else
830       puts ("Structure test 5 found GCC's structure passing bug.");
831
832     free (ts5_result);
833   }
834
835   /* struct tests */
836   {
837     test_structure_6 ts6_arg;
838
839     /* This is a hack to get a properly aligned result buffer */
840     test_structure_6 *ts6_result = 
841       (test_structure_6 *) malloc (sizeof(test_structure_6));
842
843     args[0] = &ts6_type;
844     values[0] = &ts6_arg;
845
846     /* Initialize the cif */
847     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
848
849     ts6_arg.f = 5.55f;
850     ts6_arg.d = 6.66;
851
852     printf ("%g\n", ts6_arg.f);
853     printf ("%g\n", ts6_arg.d);
854
855     ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
856
857     printf ("%g\n", ts6_result->f);
858     printf ("%g\n", ts6_result->d);
859
860     CHECK(ts6_result->f == 5.55f + 1);
861     CHECK(ts6_result->d == 6.66 + 1);
862
863     printf("structure test 6 ok!\n");
864
865     free (ts6_result);
866   }
867
868   /* struct tests */
869   {
870     test_structure_7 ts7_arg;
871
872     /* This is a hack to get a properly aligned result buffer */
873     test_structure_7 *ts7_result = 
874       (test_structure_7 *) malloc (sizeof(test_structure_7));
875
876     args[0] = &ts7_type;
877     values[0] = &ts7_arg;
878
879     /* Initialize the cif */
880     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
881
882     ts7_arg.f1 = 5.55f;
883     ts7_arg.f2 = 55.5f;
884     ts7_arg.d = 6.66;
885
886     printf ("%g\n", ts7_arg.f1);
887     printf ("%g\n", ts7_arg.f2);
888     printf ("%g\n", ts7_arg.d);
889
890     ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
891
892     printf ("%g\n", ts7_result->f1);
893     printf ("%g\n", ts7_result->f2);
894     printf ("%g\n", ts7_result->d);
895
896     CHECK(ts7_result->f1 == 5.55f + 1);
897     CHECK(ts7_result->f2 == 55.5f + 1);
898     CHECK(ts7_result->d == 6.66 + 1);
899
900     printf("structure test 7 ok!\n");
901
902     free (ts7_result);
903   }
904
905   /* struct tests */
906   {
907     test_structure_8 ts8_arg;
908
909     /* This is a hack to get a properly aligned result buffer */
910     test_structure_8 *ts8_result = 
911       (test_structure_8 *) malloc (sizeof(test_structure_8));
912
913     args[0] = &ts8_type;
914     values[0] = &ts8_arg;
915
916     /* Initialize the cif */
917     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
918
919     ts8_arg.f1 = 5.55f;
920     ts8_arg.f2 = 55.5f;
921     ts8_arg.f3 = -5.55f;
922     ts8_arg.f4 = -55.5f;
923
924     printf ("%g\n", ts8_arg.f1);
925     printf ("%g\n", ts8_arg.f2);
926     printf ("%g\n", ts8_arg.f3);
927     printf ("%g\n", ts8_arg.f4);
928
929     ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
930
931     printf ("%g\n", ts8_result->f1);
932     printf ("%g\n", ts8_result->f2);
933     printf ("%g\n", ts8_result->f3);
934     printf ("%g\n", ts8_result->f4);
935
936     CHECK(ts8_result->f1 == 5.55f + 1);
937     CHECK(ts8_result->f2 == 55.5f + 1);
938     CHECK(ts8_result->f3 == -5.55f + 1);
939     CHECK(ts8_result->f4 == -55.5f + 1);
940
941     printf("structure test 8 ok!\n");
942
943     free (ts8_result);
944   }
945
946   /* struct tests */
947   {
948     test_structure_9 ts9_arg;
949
950     /* This is a hack to get a properly aligned result buffer */
951     test_structure_9 *ts9_result = 
952       (test_structure_9 *) malloc (sizeof(test_structure_9));
953
954     args[0] = &ts9_type;
955     values[0] = &ts9_arg;
956
957     /* Initialize the cif */
958     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
959
960     ts9_arg.f = 5.55f;
961     ts9_arg.i = 5;
962
963     printf ("%g\n", ts9_arg.f);
964     printf ("%d\n", ts9_arg.i);
965
966     ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
967
968     printf ("%g\n", ts9_result->f);
969     printf ("%d\n", ts9_result->i);
970
971     CHECK(ts9_result->f == 5.55f + 1);
972     CHECK(ts9_result->i == 5 + 1);
973
974     printf("structure test 9 ok!\n");
975
976     free (ts9_result);
977   }
978
979 #else
980   printf("Structure passing doesn't work on Win32.\n");
981 #endif /* X86_WIN32 */
982
983 #ifdef X86_WIN32
984   /* stdcall strlen tests */
985   {
986     args[0] = &ffi_type_pointer;
987     values[0] = (void*) &s;
988
989     /* Initialize the cif */
990     CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
991                        &ffi_type_sint, args) == FFI_OK);
992
993     s = "a";
994     ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
995     CHECK(rint == 1);
996
997     s = "1234567";
998     ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
999     CHECK(rint == 7);
1000
1001     s = "1234567890123456789012345";
1002     ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
1003     CHECK(rint == 25);
1004
1005     printf("stdcall strlen tests passed\n");
1006   }
1007
1008   /* stdcall many arg tests */
1009   {
1010     float ff;
1011     float fa[13];
1012
1013     for (ul = 0; ul < 13; ul++)
1014       {
1015         args[ul] = &ffi_type_float;
1016         values[ul] = &fa[ul];
1017         fa[ul] = (float) ul;
1018       }
1019
1020     /* Initialize the cif */
1021     CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
1022                        &ffi_type_float, args) == FFI_OK);
1023
1024     /*@-usedef@*/
1025     ff =  stdcall_many(fa[0], fa[1],
1026                fa[2], fa[3],
1027                fa[4], fa[5],
1028                fa[6], fa[7],
1029                fa[8], fa[9],
1030                fa[10],fa[11],fa[12]);
1031     /*@=usedef@*/
1032
1033     ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
1034
1035     /*@-realcompare@*/
1036     if (f - ff < FLT_EPSILON)
1037     /*@=realcompare@*/
1038         printf("stdcall many arg tests ok!\n");
1039     else
1040         CHECK(0);
1041   }
1042 #endif /* X86_WIN32 */
1043
1044 # if FFI_CLOSURES
1045   /* A simple closure test */
1046     {
1047       ffi_closure cl;
1048       ffi_type * cl_arg_types[3];
1049
1050       cl_arg_types[0] = &ffi_type_sint;
1051       cl_arg_types[1] = &ffi_type_float;
1052       cl_arg_types[2] = NULL;
1053       
1054       /* Initialize the cif */
1055       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, 
1056                          &ffi_type_sint, cl_arg_types) == FFI_OK);
1057
1058       CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn,
1059                              (void *) 3 /* userdata */)
1060             == FFI_OK);
1061       CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6);
1062     }
1063 # endif
1064
1065   /* If we arrived here, all is good */
1066   (void) puts("\nLooks good. No surprises.\n");
1067
1068   /*@-compdestroy@*/
1069
1070   return 0;
1071 }
1072