OSDN Git Service

223b49c6dd81b25d1d782648fe4c4e2b9b1aac8b
[pf3gnuchains/gcc-fork.git] / libffi / src / ffitest.c
1 /* -----------------------------------------------------------------------
2    ffitest.c - Copyright (c) 1996, 1997, 1998, 2002, 2003  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 =
292     (int)*(unsigned long long *)args[0] + (int)(*(int *)args[1]) +
293     (int)(*(unsigned long long *)args[2]) + (int)*(int *)args[3] +
294     (int)(*(signed short *)args[4]) +
295     (int)(*(unsigned long long *)args[5]) +
296     (int)*(int *)args[6] + (int)(*(int *)args[7]) +
297     (int)(*(double *)args[8]) + (int)*(int *)args[9] +
298     (int)(*(int *)args[10]) + (int)(*(float *)args[11]) +
299     (int)*(int *)args[12] + (int)(*(int *)args[13]) +
300     (int)(*(int *)args[14]) +  *(int *)args[15] + (int)(long)userdata;
301
302         printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
303                (int)*(unsigned long long *)args[0], (int)(*(int *)args[1]), 
304                (int)(*(unsigned long long *)args[2]),
305                (int)*(int *)args[3], (int)(*(signed short *)args[4]), 
306                (int)(*(unsigned long long *)args[5]),
307                (int)*(int *)args[6], (int)(*(int *)args[7]), 
308                (int)(*(double *)args[8]), (int)*(int *)args[9],
309                (int)(*(int *)args[10]), (int)(*(float *)args[11]),
310                (int)*(int *)args[12], (int)(*(int *)args[13]), 
311                (int)(*(int *)args[14]),*(int *)args[15],
312                (int)(long)userdata, (int)*(ffi_arg *)resp);
313 }
314
315 typedef int (*closure_test_type)(unsigned long long, int, unsigned long long, 
316                                  int, signed short, unsigned long long, int, 
317                                  int, double, int, int, float, int, int, 
318                                  int, int);
319
320 static void closure_test_fn1(ffi_cif* cif,void* resp,void** args, 
321                              void* userdata)
322  {
323     *(ffi_arg*)resp =
324       (int)*(float *)args[0] +(int)(*(float *)args[1]) + 
325       (int)(*(float *)args[2]) + (int)*(float *)args[3] +
326       (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) +
327       (int)*(float *)args[6] + (int)(*(int *)args[7]) + 
328       (int)(*(double*)args[8]) + (int)*(int *)args[9] + 
329       (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + 
330       (int)*(int *)args[12] + (int)(*(int *)args[13]) + 
331       (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
332
333     printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
334            (int)*(float *)args[0], (int)(*(float *)args[1]), 
335            (int)(*(float *)args[2]), (int)*(float *)args[3], 
336            (int)(*(signed short *)args[4]), (int)(*(float *)args[5]),
337            (int)*(float *)args[6], (int)(*(int *)args[7]),
338            (int)(*(double *)args[8]), (int)*(int *)args[9],
339            (int)(*(int *)args[10]), (int)(*(float *)args[11]),
340            (int)*(int *)args[12], (int)(*(int *)args[13]),
341            (int)(*(int *)args[14]), *(int *)args[15],
342            (int)(long)userdata, (int)*(ffi_arg *)resp);
343 }
344
345 typedef int (*closure_test_type1)(float, float, float, float, signed short, 
346                                   float, float, int, double, int, int, float,
347                                   int, int, int, int);
348
349 static void closure_test_fn2(ffi_cif* cif,void* resp,void** args, 
350                              void* userdata)
351  {
352     *(ffi_arg*)resp =
353       (int)*(double *)args[0] +(int)(*(double *)args[1]) + 
354       (int)(*(double *)args[2]) + (int)*(double *)args[3] +
355       (int)(*(signed short *)args[4]) + (int)(*(double *)args[5]) +
356       (int)*(double *)args[6] + (int)(*(int *)args[7]) + 
357       (int)(*(double *)args[8]) + (int)*(int *)args[9] +
358       (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + 
359       (int)*(int *)args[12] + (int)(*(float *)args[13]) +
360       (int)(*(int *)args[14]) + *(int *)args[15] + (int)(long)userdata;
361
362     printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
363            (int)*(double *)args[0], (int)(*(double *)args[1]), 
364            (int)(*(double *)args[2]), (int)*(double *)args[3], 
365            (int)(*(signed short *)args[4]), (int)(*(double *)args[5]),
366            (int)*(double *)args[6], (int)(*(int *)args[7]), 
367            (int)(*(double*)args[8]), (int)*(int *)args[9], 
368            (int)(*(int *)args[10]), (int)(*(float *)args[11]),
369            (int)*(int *)args[12], (int)(*(float *)args[13]), 
370            (int)(*(int *)args[14]), *(int *)args[15], (int)(long)userdata, 
371            (int)*(ffi_arg *)resp);
372  }
373
374 typedef int (*closure_test_type2)(double, double, double, double, signed short,
375                                   double, double, int, double, int, int, float,
376                                   int, float, int, int);
377
378 static void closure_test_fn3(ffi_cif* cif,void* resp,void** args,
379                              void* userdata)
380  {
381     *(ffi_arg*)resp =
382       (int)*(float *)args[0] +(int)(*(float *)args[1]) + 
383       (int)(*(float *)args[2]) + (int)*(float *)args[3] +
384       (int)(*(float *)args[4]) + (int)(*(float *)args[5]) +
385       (int)*(float *)args[6] + (int)(*(float *)args[7]) + 
386       (int)(*(double *)args[8]) + (int)*(int *)args[9] +
387       (int)(*(float *)args[10]) + (int)(*(float *)args[11]) + 
388       (int)*(int *)args[12] + (int)(*(float *)args[13]) +
389       (int)(*(float *)args[14]) +  *(int *)args[15] + (int)(long)userdata;
390
391     printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n",
392            (int)*(float *)args[0], (int)(*(float *)args[1]), 
393            (int)(*(float *)args[2]), (int)*(float *)args[3], 
394            (int)(*(float *)args[4]), (int)(*(float *)args[5]),
395            (int)*(float *)args[6], (int)(*(float *)args[7]), 
396            (int)(*(double *)args[8]), (int)*(int *)args[9], 
397            (int)(*(float *)args[10]), (int)(*(float *)args[11]),
398            (int)*(int *)args[12], (int)(*(float *)args[13]), 
399            (int)(*(float *)args[14]), *(int *)args[15], (int)(long)userdata,
400            (int)*(ffi_arg *)resp);
401  }
402
403 typedef int (*closure_test_type3)(float, float, float, float, float, float,
404                                   float, float, double, int, float, float, int,
405                                   float, float, int);
406 #endif
407
408 int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[])
409 {
410   ffi_cif cif;
411   ffi_type *args[MAX_ARGS];
412   void *values[MAX_ARGS];
413   char *s;
414   signed char sc;
415   unsigned char uc;
416   signed short ss;
417   unsigned short us;
418   unsigned long ul;
419   long long ll;
420   float f;
421   double d;
422   long double ld;
423   signed int si1;
424   signed int si2;
425
426   ffi_arg rint;
427   long long rlonglong;
428
429 # if FFI_CLOSURES
430   /* The closure must not be an automatic variable on
431      platforms (Solaris) that forbid stack execution by default. */
432   static ffi_closure cl;
433   ffi_closure *pcl = &cl;
434 #endif
435
436   ffi_type * cl_arg_types[17];
437
438   ffi_type ts1_type;
439   ffi_type ts2_type;
440   ffi_type ts3_type;
441   ffi_type ts4_type;  
442   ffi_type ts5_type;
443   ffi_type ts6_type;
444   ffi_type ts7_type;
445   ffi_type ts8_type;
446   ffi_type ts9_type;
447   ffi_type *ts1_type_elements[4];
448   ffi_type *ts2_type_elements[3];
449   ffi_type *ts3_type_elements[2];
450   ffi_type *ts4_type_elements[4];
451   ffi_type *ts5_type_elements[3];
452   ffi_type *ts6_type_elements[3];
453   ffi_type *ts7_type_elements[4];
454   ffi_type *ts8_type_elements[5];
455   ffi_type *ts9_type_elements[3];
456
457   ts1_type.size = 0;
458   ts1_type.alignment = 0;
459   ts1_type.type = FFI_TYPE_STRUCT;
460
461   ts2_type.size = 0;
462   ts2_type.alignment = 0;
463   ts2_type.type = FFI_TYPE_STRUCT;
464
465   ts3_type.size = 0;
466   ts3_type.alignment = 0;
467   ts3_type.type = FFI_TYPE_STRUCT;
468
469   ts4_type.size = 0;
470   ts4_type.alignment = 0;
471   ts4_type.type = FFI_TYPE_STRUCT;
472
473   ts5_type.size = 0;
474   ts5_type.alignment = 0;
475   ts5_type.type = FFI_TYPE_STRUCT;
476
477   ts6_type.size = 0;
478   ts6_type.alignment = 0;
479   ts6_type.type = FFI_TYPE_STRUCT;
480
481   ts7_type.size = 0;
482   ts7_type.alignment = 0;
483   ts7_type.type = FFI_TYPE_STRUCT;
484
485   ts8_type.size = 0;
486   ts8_type.alignment = 0;
487   ts8_type.type = FFI_TYPE_STRUCT;
488
489   ts9_type.size = 0;
490   ts9_type.alignment = 0;
491   ts9_type.type = FFI_TYPE_STRUCT;
492
493   /*@-immediatetrans@*/
494   ts1_type.elements = ts1_type_elements;
495   ts2_type.elements = ts2_type_elements;
496   ts3_type.elements = ts3_type_elements;
497   ts4_type.elements = ts4_type_elements;
498   ts5_type.elements = ts5_type_elements;
499   ts6_type.elements = ts6_type_elements;
500   ts7_type.elements = ts7_type_elements;
501   ts8_type.elements = ts8_type_elements;
502   ts9_type.elements = ts9_type_elements;
503   /*@=immediatetrans@*/
504   
505   ts1_type_elements[0] = &ffi_type_uchar;
506   ts1_type_elements[1] = &ffi_type_double;
507   ts1_type_elements[2] = &ffi_type_uint;
508   ts1_type_elements[3] = NULL;
509   
510   ts2_type_elements[0] = &ffi_type_double;
511   ts2_type_elements[1] = &ffi_type_double;
512   ts2_type_elements[2] = NULL;
513
514   ts3_type_elements[0] = &ffi_type_sint;
515   ts3_type_elements[1] = NULL;
516
517   ts4_type_elements[0] = &ffi_type_uint;
518   ts4_type_elements[1] = &ffi_type_uint;
519   ts4_type_elements[2] = &ffi_type_uint;
520   ts4_type_elements[3] = NULL;
521
522   ts5_type_elements[0] = &ffi_type_schar;
523   ts5_type_elements[1] = &ffi_type_schar;
524   ts5_type_elements[2] = NULL;
525
526   ts6_type_elements[0] = &ffi_type_float;
527   ts6_type_elements[1] = &ffi_type_double;
528   ts6_type_elements[2] = NULL;
529
530   ts7_type_elements[0] = &ffi_type_float;
531   ts7_type_elements[1] = &ffi_type_float;
532   ts7_type_elements[2] = &ffi_type_double;
533   ts7_type_elements[3] = NULL;
534
535   ts8_type_elements[0] = &ffi_type_float;
536   ts8_type_elements[1] = &ffi_type_float;
537   ts8_type_elements[2] = &ffi_type_float;
538   ts8_type_elements[3] = &ffi_type_float;
539   ts8_type_elements[4] = NULL;
540
541   ts9_type_elements[0] = &ffi_type_float;
542   ts9_type_elements[1] = &ffi_type_sint;
543   ts9_type_elements[2] = NULL;
544
545   ul = 0;
546
547   /* return value tests */
548   {
549 #if defined(MIPS) /* || defined(ARM) */
550     puts ("long long tests not run. This is a known bug on this architecture.");
551 #else
552     args[0] = &ffi_type_sint64;
553     values[0] = &ll;
554     
555     /* Initialize the cif */
556     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
557                        &ffi_type_sint64, args) == FFI_OK);
558
559     for (ll = 0LL; ll < 100LL; ll++)
560       {
561         ul++;
562         ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
563         CHECK(rlonglong == ll);
564       }
565
566     for (ll = 55555555555000LL; ll < 55555555555100LL; ll++)
567       {
568         ul++;
569         ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values);
570         CHECK(rlonglong == ll);
571       }
572 #endif
573
574     args[0] = &ffi_type_schar;
575     values[0] = &sc;
576     
577     /* Initialize the cif */
578     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
579                        &ffi_type_schar, args) == FFI_OK);
580
581     for (sc = (signed char) -127; 
582          sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/)
583       {
584         ul++;
585         ffi_call(&cif, FFI_FN(return_sc), &rint, values);
586         CHECK(rint == (ffi_arg) sc);
587       }
588
589     args[0] = &ffi_type_uchar;
590     values[0] = &uc;
591     
592     /* Initialize the cif */
593     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
594                        &ffi_type_uchar, args) == FFI_OK);
595
596     for (uc = (unsigned char) '\x00'; 
597          uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/)
598       {
599         ul++;
600         ffi_call(&cif, FFI_FN(return_uc), &rint, values);
601         CHECK(rint == (signed int) uc);
602       }
603
604     printf("%lu return value tests run\n", ul);
605   }
606
607 #ifdef BROKEN_LONG_DOUBLE
608   printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n");
609 #else
610   /* float arg tests */
611   {
612     args[0] = &ffi_type_float;
613     values[0] = &f;
614
615     /* Initialize the cif */
616     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
617                        &ffi_type_longdouble, args) == FFI_OK);
618
619     f = 3.14159;
620
621 #if 0
622   /* This is ifdef'd out for now. long double support under SunOS/gcc
623      is pretty much non-existent.  You'll get the odd bus error in library
624      routines like printf().  */
625     printf ("%Lf\n", ldblit(f));
626 #endif
627     ld = 666;
628     ffi_call(&cif, FFI_FN(ldblit), &ld, values);
629
630 #if 0
631   /* This is ifdef'd out for now. long double support under SunOS/gcc
632      is pretty much non-existent.  You'll get the odd bus error in library
633      routines like printf().  */
634     printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON);
635 #endif
636
637     /* These are not always the same!! Check for a reasonable delta */
638     /*@-realcompare@*/
639     if (ld - ldblit(f) < LDBL_EPSILON)
640     /*@=realcompare@*/
641         puts("long double return value tests ok!");
642     else
643         CHECK(0);
644   }
645
646   /* float arg tests */
647   {
648     args[0] = &ffi_type_sint;
649     values[0] = &si1;
650     args[1] = &ffi_type_float;
651     values[1] = &f;
652     args[2] = &ffi_type_double;
653     values[2] = &d;
654     args[3] = &ffi_type_longdouble;
655     values[3] = &ld;
656     args[4] = &ffi_type_sint;
657     values[4] = &si2;
658     
659     /* Initialize the cif */
660     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5,
661                        &ffi_type_sint, args) == FFI_OK);
662
663     si1 = 6;
664     f = 3.14159;
665     d = (double)1.0/(double)3.0;
666     ld = 2.71828182846L;
667     si2 = 10;
668
669     floating (si1, f, d, ld, si2);
670
671     ffi_call(&cif, FFI_FN(floating), &rint, values);
672
673     printf ("%d vs %d\n", (int)rint, floating (si1, f, d, ld, si2));
674
675     CHECK(rint == floating(si1, f, d, ld, si2));
676
677     printf("float arg tests ok!\n");
678   }
679 #endif
680
681   /* strlen tests */
682   {
683     args[0] = &ffi_type_pointer;
684     values[0] = (void*) &s;
685     
686     /* Initialize the cif */
687     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
688                        &ffi_type_sint, args) == FFI_OK);
689
690     s = "a";
691     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
692     CHECK(rint == 1);
693
694     s = "1234567";
695     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
696     CHECK(rint == 7);
697
698     s = "1234567890123456789012345";
699     ffi_call(&cif, FFI_FN(my_strlen), &rint, values);
700     CHECK(rint == 25);
701
702     printf("strlen tests passed\n");
703   }
704
705   /* float arg tests */
706   {
707     args[0] = &ffi_type_float;
708     values[0] = &f;
709     
710     /* Initialize the cif */
711     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
712                        &ffi_type_double, args) == FFI_OK);
713
714     f = 3.14159;
715
716     ffi_call(&cif, FFI_FN(dblit), &d, values);
717
718     /* These are not always the same!! Check for a reasonable delta */
719     /*@-realcompare@*/
720     CHECK(d - dblit(f) < DBL_EPSILON);
721     /*@=realcompare@*/
722
723     printf("double return value tests ok!\n");
724   }
725
726   /* many arg tests */
727   {
728     float ff;
729     float fa[13];
730     
731     for (ul = 0; ul < 13; ul++)
732       {
733         args[ul] = &ffi_type_float;
734         values[ul] = &fa[ul];
735         fa[ul] = (float) ul;
736       }
737
738     /* Initialize the cif */
739     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, 
740                        &ffi_type_float, args) == FFI_OK);
741
742     /*@-usedef@*/
743     ff = many (fa[0], fa[1],
744                fa[2], fa[3],
745                fa[4], fa[5],
746                fa[6], fa[7],
747                fa[8], fa[9],
748                fa[10],fa[11],fa[12]);
749     /*@=usedef@*/
750
751     ffi_call(&cif, FFI_FN(many), &f, values);
752
753     /*@-realcompare@*/
754     if (f - ff < FLT_EPSILON)
755     /*@=realcompare@*/
756         printf("many arg tests ok!\n");
757     else
758 #ifdef POWERPC
759         printf("many arg tests failed!  This is a gcc bug.\n");
760 #else
761         CHECK(0);
762 #endif
763   }
764
765   /* promotion tests */
766   {
767     args[0] = &ffi_type_schar;
768     args[1] = &ffi_type_sshort;
769     args[2] = &ffi_type_uchar;
770     args[3] = &ffi_type_ushort;
771     values[0] = &sc;
772     values[1] = &ss;
773     values[2] = &uc;
774     values[3] = &us;
775     
776     /* Initialize the cif */
777     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, 
778                        &ffi_type_sint, args) == FFI_OK);
779
780     us = 0;
781     ul = 0;
782
783     for (sc = (signed char) -127; 
784          sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/)
785       for (ss = -30000; ss <= 30000; ss += 10000)
786         for (uc = (unsigned char) 0; 
787              uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/)
788           for (us = 0; us <= 60000; us += 10000)
789             {
790               ul++;
791               ffi_call(&cif, FFI_FN(promotion), &rint, values);
792               CHECK((int)rint == (signed char) sc + (signed short) ss +
793                     (unsigned char) uc + (unsigned short) us);
794             }
795     printf("%lu promotion tests run\n", ul);
796   }
797
798 #ifndef X86_WIN32 /* Structures dont work on Win32 */
799
800   /* struct tests */
801   {
802     test_structure_1 ts1_arg;
803     /* This is a hack to get a properly aligned result buffer */
804     test_structure_1 *ts1_result = 
805       (test_structure_1 *) malloc (sizeof(test_structure_1));
806
807     args[0] = &ts1_type;
808     values[0] = &ts1_arg;
809     
810     /* Initialize the cif */
811     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
812                        &ts1_type, args) == FFI_OK);
813
814     ts1_arg.uc = '\x01';
815     ts1_arg.d = 3.14159;
816     ts1_arg.ui = 555;
817
818     ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
819
820     CHECK(ts1_result->ui == 556);
821     CHECK(ts1_result->d == 3.14159 - 1);
822
823     puts ("structure test 1 ok!\n");
824
825     free (ts1_result);
826   }
827
828   /* struct tests */
829   {
830     test_structure_2 ts2_arg;
831
832     /* This is a hack to get a properly aligned result buffer */
833     test_structure_2 *ts2_result = 
834       (test_structure_2 *) malloc (sizeof(test_structure_2));
835
836     args[0] = &ts2_type;
837     values[0] = &ts2_arg;
838     
839     /* Initialize the cif */
840     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK);
841
842     ts2_arg.d1 = 5.55;
843     ts2_arg.d2 = 6.66;
844
845     printf ("%g\n", ts2_arg.d1);
846     printf ("%g\n", ts2_arg.d2);
847
848     ffi_call(&cif, FFI_FN(struct2), ts2_result, values);
849
850     printf ("%g\n", ts2_result->d1);
851     printf ("%g\n", ts2_result->d2);
852     
853     CHECK(ts2_result->d1 == 5.55 - 1);
854     CHECK(ts2_result->d2 == 6.66 - 1);
855
856     printf("structure test 2 ok!\n");
857
858     free (ts2_result);
859   }
860
861   /* struct tests */
862   {
863     int compare_value;
864     test_structure_3 ts3_arg;
865     test_structure_3 *ts3_result = 
866       (test_structure_3 *) malloc (sizeof(test_structure_3));
867
868     args[0] = &ts3_type;
869     values[0] = &ts3_arg;
870     
871     /* Initialize the cif */
872     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, 
873                        &ts3_type, args) == FFI_OK);
874
875     ts3_arg.si = -123;
876     compare_value = ts3_arg.si;
877
878     ffi_call(&cif, FFI_FN(struct3), ts3_result, values);
879
880     printf ("%d %d\n", ts3_result->si, -(compare_value*2));
881
882     if (ts3_result->si == -(ts3_arg.si*2))
883         puts ("structure test 3 ok!");
884     else
885       {
886         puts ("Structure test 3 found structure passing bug.");
887         puts ("  Current versions of GCC are not 100% compliant with the");
888         puts ("  n32 ABI.  There is a known problem related to passing");
889         puts ("  small structures.  Send a bug report to the gcc maintainers.");
890       }
891
892     free (ts3_result);
893   }
894
895   /* struct tests */
896   {
897     test_structure_4 ts4_arg;
898
899     /* This is a hack to get a properly aligned result buffer */
900     test_structure_4 *ts4_result = 
901       (test_structure_4 *) malloc (sizeof(test_structure_4));
902
903     args[0] = &ts4_type;
904     values[0] = &ts4_arg;
905     
906     /* Initialize the cif */
907     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK);
908
909     ts4_arg.ui1 = 2;
910     ts4_arg.ui2 = 3;
911     ts4_arg.ui3 = 4;
912
913     ffi_call (&cif, FFI_FN(struct4), ts4_result, values);
914     
915     if (ts4_result->ui3 == 2U * 3U * 4U)
916       puts ("structure test 4 ok!");
917     else
918       puts ("Structure test 4 found GCC's structure passing bug.");
919
920     free (ts4_result);
921   }
922
923   /* struct tests */
924   {
925     test_structure_5 ts5_arg1, ts5_arg2;
926
927     /* This is a hack to get a properly aligned result buffer */
928     test_structure_5 *ts5_result = 
929       (test_structure_5 *) malloc (sizeof(test_structure_5));
930
931     args[0] = &ts5_type;
932     args[1] = &ts5_type;
933     values[0] = &ts5_arg1;
934     values[1] = &ts5_arg2;
935     
936     /* Initialize the cif */
937     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK);
938
939     ts5_arg1.c1 = 2;
940     ts5_arg1.c2 = 6;
941     ts5_arg2.c1 = 5;
942     ts5_arg2.c2 = 3;
943
944     ffi_call (&cif, FFI_FN(struct5), ts5_result, values);
945     
946     if (ts5_result->c1 == 7 
947         && ts5_result->c2 == 3)
948       puts ("structure test 5 ok!");
949     else
950       puts ("Structure test 5 found GCC's structure passing bug.");
951
952     free (ts5_result);
953   }
954
955   /* struct tests */
956   {
957     test_structure_6 ts6_arg;
958
959     /* This is a hack to get a properly aligned result buffer */
960     test_structure_6 *ts6_result = 
961       (test_structure_6 *) malloc (sizeof(test_structure_6));
962
963     args[0] = &ts6_type;
964     values[0] = &ts6_arg;
965
966     /* Initialize the cif */
967     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts6_type, args) == FFI_OK);
968
969     ts6_arg.f = 5.55f;
970     ts6_arg.d = 6.66;
971
972     printf ("%g\n", ts6_arg.f);
973     printf ("%g\n", ts6_arg.d);
974
975     ffi_call(&cif, FFI_FN(struct6), ts6_result, values);
976
977     printf ("%g\n", ts6_result->f);
978     printf ("%g\n", ts6_result->d);
979
980     CHECK(ts6_result->f == 5.55f + 1);
981     CHECK(ts6_result->d == 6.66 + 1);
982
983     printf("structure test 6 ok!\n");
984
985     free (ts6_result);
986   }
987
988   /* struct tests */
989   {
990     test_structure_7 ts7_arg;
991
992     /* This is a hack to get a properly aligned result buffer */
993     test_structure_7 *ts7_result = 
994       (test_structure_7 *) malloc (sizeof(test_structure_7));
995
996     args[0] = &ts7_type;
997     values[0] = &ts7_arg;
998
999     /* Initialize the cif */
1000     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts7_type, args) == FFI_OK);
1001
1002     ts7_arg.f1 = 5.55f;
1003     ts7_arg.f2 = 55.5f;
1004     ts7_arg.d = 6.66;
1005
1006     printf ("%g\n", ts7_arg.f1);
1007     printf ("%g\n", ts7_arg.f2);
1008     printf ("%g\n", ts7_arg.d);
1009
1010     ffi_call(&cif, FFI_FN(struct7), ts7_result, values);
1011
1012     printf ("%g\n", ts7_result->f1);
1013     printf ("%g\n", ts7_result->f2);
1014     printf ("%g\n", ts7_result->d);
1015
1016     CHECK(ts7_result->f1 == 5.55f + 1);
1017     CHECK(ts7_result->f2 == 55.5f + 1);
1018     CHECK(ts7_result->d == 6.66 + 1);
1019
1020     printf("structure test 7 ok!\n");
1021
1022     free (ts7_result);
1023   }
1024
1025   /* struct tests */
1026   {
1027     test_structure_8 ts8_arg;
1028
1029     /* This is a hack to get a properly aligned result buffer */
1030     test_structure_8 *ts8_result = 
1031       (test_structure_8 *) malloc (sizeof(test_structure_8));
1032
1033     args[0] = &ts8_type;
1034     values[0] = &ts8_arg;
1035
1036     /* Initialize the cif */
1037     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts8_type, args) == FFI_OK);
1038
1039     ts8_arg.f1 = 5.55f;
1040     ts8_arg.f2 = 55.5f;
1041     ts8_arg.f3 = -5.55f;
1042     ts8_arg.f4 = -55.5f;
1043
1044     printf ("%g\n", ts8_arg.f1);
1045     printf ("%g\n", ts8_arg.f2);
1046     printf ("%g\n", ts8_arg.f3);
1047     printf ("%g\n", ts8_arg.f4);
1048
1049     ffi_call(&cif, FFI_FN(struct8), ts8_result, values);
1050
1051     printf ("%g\n", ts8_result->f1);
1052     printf ("%g\n", ts8_result->f2);
1053     printf ("%g\n", ts8_result->f3);
1054     printf ("%g\n", ts8_result->f4);
1055
1056     CHECK(ts8_result->f1 == 5.55f + 1);
1057     CHECK(ts8_result->f2 == 55.5f + 1);
1058     CHECK(ts8_result->f3 == -5.55f + 1);
1059     CHECK(ts8_result->f4 == -55.5f + 1);
1060
1061     printf("structure test 8 ok!\n");
1062
1063     free (ts8_result);
1064   }
1065
1066   /* struct tests */
1067   {
1068     test_structure_9 ts9_arg;
1069
1070     /* This is a hack to get a properly aligned result buffer */
1071     test_structure_9 *ts9_result = 
1072       (test_structure_9 *) malloc (sizeof(test_structure_9));
1073
1074     args[0] = &ts9_type;
1075     values[0] = &ts9_arg;
1076
1077     /* Initialize the cif */
1078     CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts9_type, args) == FFI_OK);
1079
1080     ts9_arg.f = 5.55f;
1081     ts9_arg.i = 5;
1082
1083     printf ("%g\n", ts9_arg.f);
1084     printf ("%d\n", ts9_arg.i);
1085
1086     ffi_call(&cif, FFI_FN(struct9), ts9_result, values);
1087
1088     printf ("%g\n", ts9_result->f);
1089     printf ("%d\n", ts9_result->i);
1090
1091     CHECK(ts9_result->f == 5.55f + 1);
1092     CHECK(ts9_result->i == 5 + 1);
1093
1094     printf("structure test 9 ok!\n");
1095
1096     free (ts9_result);
1097   }
1098
1099 #else
1100   printf("Structure passing doesn't work on Win32.\n");
1101 #endif /* X86_WIN32 */
1102
1103 #ifdef X86_WIN32
1104   /* stdcall strlen tests */
1105   {
1106     args[0] = &ffi_type_pointer;
1107     values[0] = (void*) &s;
1108
1109     /* Initialize the cif */
1110     CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 1,
1111                        &ffi_type_sint, args) == FFI_OK);
1112
1113     s = "a";
1114     ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
1115     CHECK(rint == 1);
1116
1117     s = "1234567";
1118     ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
1119     CHECK(rint == 7);
1120
1121     s = "1234567890123456789012345";
1122     ffi_call(&cif, FFI_FN(my_stdcall_strlen), &rint, values);
1123     CHECK(rint == 25);
1124
1125     printf("stdcall strlen tests passed\n");
1126   }
1127
1128   /* stdcall many arg tests */
1129   {
1130     float ff;
1131     float fa[13];
1132
1133     for (ul = 0; ul < 13; ul++)
1134       {
1135         args[ul] = &ffi_type_float;
1136         values[ul] = &fa[ul];
1137         fa[ul] = (float) ul;
1138       }
1139
1140     /* Initialize the cif */
1141     CHECK(ffi_prep_cif(&cif, FFI_STDCALL, 13,
1142                        &ffi_type_float, args) == FFI_OK);
1143
1144     /*@-usedef@*/
1145     ff =  stdcall_many(fa[0], fa[1],
1146                fa[2], fa[3],
1147                fa[4], fa[5],
1148                fa[6], fa[7],
1149                fa[8], fa[9],
1150                fa[10],fa[11],fa[12]);
1151     /*@=usedef@*/
1152
1153     ffi_call(&cif, FFI_FN(stdcall_many), &f, values);
1154
1155     /*@-realcompare@*/
1156     if (f - ff < FLT_EPSILON)
1157     /*@=realcompare@*/
1158         printf("stdcall many arg tests ok!\n");
1159     else
1160         CHECK(0);
1161   }
1162 #endif /* X86_WIN32 */
1163
1164 # if FFI_CLOSURES
1165 #  if __GNUC__ >= 2
1166    /* Hide before the compiler that pcl is &cl, since on
1167       some architectures it is not possible to call a data
1168       object using direct function call.  */
1169    asm ("" : "=g" (pcl) : "0" (pcl));
1170 #  endif
1171
1172   /* A simple closure test */
1173     {
1174       (void) puts("\nEnter FFI_CLOSURES\n");
1175
1176       cl_arg_types[0] = &ffi_type_uint64;
1177       cl_arg_types[1] = &ffi_type_uint;
1178       cl_arg_types[2] = &ffi_type_uint64;
1179       cl_arg_types[3] = &ffi_type_uint;
1180       cl_arg_types[4] = &ffi_type_sshort;
1181       cl_arg_types[5] = &ffi_type_uint64;
1182       cl_arg_types[6] = &ffi_type_uint;
1183       cl_arg_types[7] = &ffi_type_uint;
1184       cl_arg_types[8] = &ffi_type_double;
1185       cl_arg_types[9] = &ffi_type_uint;
1186       cl_arg_types[10] = &ffi_type_uint;
1187       cl_arg_types[11] = &ffi_type_float;
1188       cl_arg_types[12] = &ffi_type_uint;
1189       cl_arg_types[13] = &ffi_type_uint;
1190       cl_arg_types[14] = &ffi_type_uint;
1191       cl_arg_types[15] = &ffi_type_uint;
1192       cl_arg_types[16] = NULL;   
1193
1194       /* Initialize the cif */
1195       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
1196                          &ffi_type_sint, cl_arg_types) == FFI_OK);
1197
1198       CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn,
1199                              (void *) 3 /* userdata */) == FFI_OK);
1200       
1201       CHECK((*((closure_test_type)pcl))
1202             (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13, 
1203              19, 21, 1) == 680);
1204     }
1205
1206     {
1207
1208       cl_arg_types[0] = &ffi_type_float;
1209       cl_arg_types[1] = &ffi_type_float;
1210       cl_arg_types[2] = &ffi_type_float;
1211       cl_arg_types[3] = &ffi_type_float;
1212       cl_arg_types[4] = &ffi_type_sshort;
1213       cl_arg_types[5] = &ffi_type_float;
1214       cl_arg_types[6] = &ffi_type_float;
1215       cl_arg_types[7] = &ffi_type_uint;
1216       cl_arg_types[8] = &ffi_type_double;
1217       cl_arg_types[9] = &ffi_type_uint;
1218       cl_arg_types[10] = &ffi_type_uint;
1219       cl_arg_types[11] = &ffi_type_float;
1220       cl_arg_types[12] = &ffi_type_uint;
1221       cl_arg_types[13] = &ffi_type_uint;
1222       cl_arg_types[14] = &ffi_type_uint;
1223       cl_arg_types[15] = &ffi_type_uint;
1224       cl_arg_types[16] = NULL;
1225       
1226       /* Initialize the cif */
1227       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
1228                          &ffi_type_sint, cl_arg_types) == FFI_OK);
1229
1230       CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn1,
1231                              (void *) 3 /* userdata */)  == FFI_OK);
1232       
1233       CHECK((*((closure_test_type1)pcl))
1234             (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13,
1235              19, 21, 1) == 255);
1236     }
1237
1238     {
1239
1240       cl_arg_types[0] = &ffi_type_double;
1241       cl_arg_types[1] = &ffi_type_double;
1242       cl_arg_types[2] = &ffi_type_double;
1243       cl_arg_types[3] = &ffi_type_double;
1244       cl_arg_types[4] = &ffi_type_sshort;
1245       cl_arg_types[5] = &ffi_type_double;
1246       cl_arg_types[6] = &ffi_type_double;
1247       cl_arg_types[7] = &ffi_type_uint;
1248       cl_arg_types[8] = &ffi_type_double;
1249       cl_arg_types[9] = &ffi_type_uint;
1250       cl_arg_types[10] = &ffi_type_uint;
1251       cl_arg_types[11] = &ffi_type_float;
1252       cl_arg_types[12] = &ffi_type_uint;
1253       cl_arg_types[13] = &ffi_type_float;
1254       cl_arg_types[14] = &ffi_type_uint;
1255       cl_arg_types[15] = &ffi_type_uint;
1256       cl_arg_types[16] = NULL;
1257       
1258       /* Initialize the cif */
1259       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
1260                          &ffi_type_sint, cl_arg_types) == FFI_OK);
1261
1262       CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn2,
1263                              (void *) 3 /* userdata */) == FFI_OK);
1264
1265       CHECK((*((closure_test_type2)pcl))
1266             (1, 2, 3, 4, 127, 5, 6, 8, 9, 10, 11, 12.0, 13,
1267              19.0, 21, 1) == 255);
1268
1269     }
1270
1271     {
1272
1273       cl_arg_types[0] = &ffi_type_float;
1274       cl_arg_types[1] = &ffi_type_float;
1275       cl_arg_types[2] = &ffi_type_float;
1276       cl_arg_types[3] = &ffi_type_float;
1277       cl_arg_types[4] = &ffi_type_float;
1278       cl_arg_types[5] = &ffi_type_float;
1279       cl_arg_types[6] = &ffi_type_float;
1280       cl_arg_types[7] = &ffi_type_float;
1281       cl_arg_types[8] = &ffi_type_double;
1282       cl_arg_types[9] = &ffi_type_uint;
1283       cl_arg_types[10] = &ffi_type_float;
1284       cl_arg_types[11] = &ffi_type_float;
1285       cl_arg_types[12] = &ffi_type_uint;
1286       cl_arg_types[13] = &ffi_type_float;
1287       cl_arg_types[14] = &ffi_type_float;
1288       cl_arg_types[15] = &ffi_type_uint;
1289       cl_arg_types[16] = NULL;
1290       
1291       /* Initialize the cif */
1292       CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16,
1293                          &ffi_type_sint, cl_arg_types) == FFI_OK);
1294
1295       CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn3,
1296                              (void *) 3 /* userdata */)  == FFI_OK);
1297       
1298       CHECK((*((closure_test_type3)pcl))
1299             (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13,
1300              19.19, 21.21, 1) == 135);
1301     }
1302
1303     (void) puts("\nFinished FFI_CLOSURES\n");
1304
1305 # endif
1306
1307   /* If we arrived here, all is good */
1308   (void) puts("\nLooks good. No surprises.\n");
1309
1310   /*@-compdestroy@*/
1311
1312   return 0;
1313 }
1314