1 | /* ----------------------------------------------------------------------- |
---|
2 | ffitest.c - Copyright (c) 1996, 1997, 1998 Cygnus Solutions |
---|
3 | |
---|
4 | $Id$ |
---|
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 | #include <rtems.h> |
---|
32 | #include <rtems/error.h> |
---|
33 | |
---|
34 | /* This is lame. Long double support is barely there under SunOS 4.x */ |
---|
35 | #if defined(SPARC) && (SIZEOF_LONG_DOUBLE != 16) |
---|
36 | #define BROKEN_LONG_DOUBLE |
---|
37 | #endif |
---|
38 | |
---|
39 | #define CHECK(x) !(x) ? fail(__FILE__, __LINE__) : 0 |
---|
40 | |
---|
41 | static int fail(char *file, int line) |
---|
42 | { |
---|
43 | fprintf(stderr, "Test failure: %s line %d\n", file, line); |
---|
44 | exit(EXIT_FAILURE); |
---|
45 | /*@notreached@*/ |
---|
46 | return 0; |
---|
47 | } |
---|
48 | |
---|
49 | #define MAX_ARGS 256 |
---|
50 | |
---|
51 | static size_t my_strlen(char *s) |
---|
52 | { |
---|
53 | return (strlen(s)); |
---|
54 | } |
---|
55 | |
---|
56 | static int promotion(signed char sc, signed short ss, |
---|
57 | unsigned char uc, unsigned short us) |
---|
58 | { |
---|
59 | int r = (int) sc + (int) ss + (int) uc + (int) us; |
---|
60 | |
---|
61 | return r; |
---|
62 | } |
---|
63 | |
---|
64 | static signed char return_sc(signed char sc) |
---|
65 | { |
---|
66 | return sc; |
---|
67 | } |
---|
68 | |
---|
69 | static unsigned char return_uc(unsigned char uc) |
---|
70 | { |
---|
71 | return uc; |
---|
72 | } |
---|
73 | |
---|
74 | static long long return_ll(long long ll) |
---|
75 | { |
---|
76 | return ll; |
---|
77 | } |
---|
78 | |
---|
79 | static int floating(int a, float b, double c, long double d, int e) |
---|
80 | { |
---|
81 | int i; |
---|
82 | |
---|
83 | #if 0 |
---|
84 | /* This is ifdef'd out for now. long double support under SunOS/gcc |
---|
85 | is pretty much non-existent. You'll get the odd bus error in library |
---|
86 | routines like printf(). */ |
---|
87 | printf("%d %f %f %Lf %d\n", a, (double)b, c, d, e); |
---|
88 | #endif |
---|
89 | |
---|
90 | i = (int) ((float)a/b + ((float)c/(float)d)); |
---|
91 | |
---|
92 | return i; |
---|
93 | } |
---|
94 | |
---|
95 | static float many(float f1, |
---|
96 | float f2, |
---|
97 | float f3, |
---|
98 | float f4, |
---|
99 | float f5, |
---|
100 | float f6, |
---|
101 | float f7, |
---|
102 | float f8, |
---|
103 | float f9, |
---|
104 | float f10, |
---|
105 | float f11, |
---|
106 | float f12, |
---|
107 | float f13) |
---|
108 | { |
---|
109 | #if 0 |
---|
110 | printf("%f %f %f %f %f %f %f %f %f %f %f %f %f\n", |
---|
111 | (double) f1, (double) f2, (double) f3, (double) f4, (double) f5, |
---|
112 | (double) f6, (double) f7, (double) f8, (double) f9, (double) f10, |
---|
113 | (double) f11, (double) f12, (double) f13); |
---|
114 | #endif |
---|
115 | |
---|
116 | return ((f1/f2+f3/f4+f5/f6+f7/f8+f9/f10+f11/f12) * f13); |
---|
117 | } |
---|
118 | |
---|
119 | static double dblit(float f) |
---|
120 | { |
---|
121 | return f/3.0; |
---|
122 | } |
---|
123 | |
---|
124 | static long double ldblit(float f) |
---|
125 | { |
---|
126 | return (long double) (((long double) f)/ (long double) 3.0); |
---|
127 | } |
---|
128 | |
---|
129 | typedef struct |
---|
130 | { |
---|
131 | unsigned char uc; |
---|
132 | double d; |
---|
133 | unsigned int ui; |
---|
134 | } test_structure_1; |
---|
135 | |
---|
136 | typedef struct |
---|
137 | { |
---|
138 | double d1; |
---|
139 | double d2; |
---|
140 | } test_structure_2; |
---|
141 | |
---|
142 | typedef struct |
---|
143 | { |
---|
144 | int si; |
---|
145 | } test_structure_3; |
---|
146 | |
---|
147 | typedef struct |
---|
148 | { |
---|
149 | unsigned ui1; |
---|
150 | unsigned ui2; |
---|
151 | unsigned ui3; |
---|
152 | } test_structure_4; |
---|
153 | |
---|
154 | typedef struct |
---|
155 | { |
---|
156 | char c1; |
---|
157 | char c2; |
---|
158 | } test_structure_5; |
---|
159 | |
---|
160 | static test_structure_1 struct1(test_structure_1 ts) |
---|
161 | { |
---|
162 | /*@-type@*/ |
---|
163 | ts.uc++; |
---|
164 | /*@=type@*/ |
---|
165 | ts.d--; |
---|
166 | ts.ui++; |
---|
167 | |
---|
168 | return ts; |
---|
169 | } |
---|
170 | |
---|
171 | static test_structure_2 struct2(test_structure_2 ts) |
---|
172 | { |
---|
173 | ts.d1--; |
---|
174 | ts.d2--; |
---|
175 | |
---|
176 | return ts; |
---|
177 | } |
---|
178 | |
---|
179 | static test_structure_3 struct3(test_structure_3 ts) |
---|
180 | { |
---|
181 | ts.si = -(ts.si*2); |
---|
182 | |
---|
183 | return ts; |
---|
184 | } |
---|
185 | |
---|
186 | static test_structure_4 struct4(test_structure_4 ts) |
---|
187 | { |
---|
188 | ts.ui3 = ts.ui1 * ts.ui2 * ts.ui3; |
---|
189 | |
---|
190 | return ts; |
---|
191 | } |
---|
192 | |
---|
193 | static test_structure_5 struct5(test_structure_5 ts1, test_structure_5 ts2) |
---|
194 | { |
---|
195 | ts1.c1 += ts2.c1; |
---|
196 | ts1.c2 -= ts2.c2; |
---|
197 | |
---|
198 | return ts1; |
---|
199 | } |
---|
200 | |
---|
201 | /* Take an int and a float argument, together with int userdata, and */ |
---|
202 | /* return the sum. */ |
---|
203 | static void closure_test_fn(ffi_cif* cif,void* resp,void** args, void* userdata) |
---|
204 | { |
---|
205 | *(int*)resp = |
---|
206 | *(int *)args[0] + (int)(*(float *)args[1]) + (int)(long)userdata; |
---|
207 | } |
---|
208 | |
---|
209 | typedef int (*closure_test_type)(int, float); |
---|
210 | |
---|
211 | int ffi_main( void ) |
---|
212 | { |
---|
213 | ffi_cif cif; |
---|
214 | ffi_type *args[MAX_ARGS]; |
---|
215 | void *values[MAX_ARGS]; |
---|
216 | char *s; |
---|
217 | signed char sc; |
---|
218 | unsigned char uc; |
---|
219 | signed short ss; |
---|
220 | unsigned short us; |
---|
221 | unsigned long ul; |
---|
222 | long long ll; |
---|
223 | float f; |
---|
224 | double d; |
---|
225 | long double ld; |
---|
226 | signed int si1; |
---|
227 | signed int si2; |
---|
228 | |
---|
229 | #if defined(ALPHA) || defined(IA64) || defined(SPARC64) || (defined(MIPS) && (_MIPS_SIM == _ABIN32)) |
---|
230 | long long rint; |
---|
231 | #else |
---|
232 | int rint; |
---|
233 | #endif |
---|
234 | long long rlonglong; |
---|
235 | |
---|
236 | ffi_type ts1_type; |
---|
237 | ffi_type ts2_type; |
---|
238 | ffi_type ts3_type; |
---|
239 | ffi_type ts4_type; |
---|
240 | ffi_type ts5_type; |
---|
241 | ffi_type *ts1_type_elements[4]; |
---|
242 | ffi_type *ts2_type_elements[3]; |
---|
243 | ffi_type *ts3_type_elements[2]; |
---|
244 | ffi_type *ts4_type_elements[4]; |
---|
245 | ffi_type *ts5_type_elements[3]; |
---|
246 | |
---|
247 | ts1_type.size = 0; |
---|
248 | ts1_type.alignment = 0; |
---|
249 | ts1_type.type = FFI_TYPE_STRUCT; |
---|
250 | |
---|
251 | ts2_type.size = 0; |
---|
252 | ts2_type.alignment = 0; |
---|
253 | ts2_type.type = FFI_TYPE_STRUCT; |
---|
254 | |
---|
255 | ts3_type.size = 0; |
---|
256 | ts3_type.alignment = 0; |
---|
257 | ts3_type.type = FFI_TYPE_STRUCT; |
---|
258 | |
---|
259 | ts4_type.size = 0; |
---|
260 | ts4_type.alignment = 0; |
---|
261 | ts4_type.type = FFI_TYPE_STRUCT; |
---|
262 | |
---|
263 | ts5_type.size = 0; |
---|
264 | ts5_type.alignment = 0; |
---|
265 | ts5_type.type = FFI_TYPE_STRUCT; |
---|
266 | |
---|
267 | /*@-immediatetrans@*/ |
---|
268 | ts1_type.elements = ts1_type_elements; |
---|
269 | ts2_type.elements = ts2_type_elements; |
---|
270 | ts3_type.elements = ts3_type_elements; |
---|
271 | ts4_type.elements = ts4_type_elements; |
---|
272 | ts5_type.elements = ts5_type_elements; |
---|
273 | /*@=immediatetrans@*/ |
---|
274 | |
---|
275 | ts1_type_elements[0] = &ffi_type_uchar; |
---|
276 | ts1_type_elements[1] = &ffi_type_double; |
---|
277 | ts1_type_elements[2] = &ffi_type_uint; |
---|
278 | ts1_type_elements[3] = NULL; |
---|
279 | |
---|
280 | ts2_type_elements[0] = &ffi_type_double; |
---|
281 | ts2_type_elements[1] = &ffi_type_double; |
---|
282 | ts2_type_elements[2] = NULL; |
---|
283 | |
---|
284 | ts3_type_elements[0] = &ffi_type_sint; |
---|
285 | ts3_type_elements[1] = NULL; |
---|
286 | |
---|
287 | ts4_type_elements[0] = &ffi_type_uint; |
---|
288 | ts4_type_elements[1] = &ffi_type_uint; |
---|
289 | ts4_type_elements[2] = &ffi_type_uint; |
---|
290 | ts4_type_elements[3] = NULL; |
---|
291 | |
---|
292 | ts5_type_elements[0] = &ffi_type_schar; |
---|
293 | ts5_type_elements[1] = &ffi_type_schar; |
---|
294 | ts5_type_elements[2] = NULL; |
---|
295 | |
---|
296 | ul = 0; |
---|
297 | |
---|
298 | /* return value tests */ |
---|
299 | { |
---|
300 | #if defined(MIPS) /* || defined(ARM) */ |
---|
301 | puts ("long long tests not run. This is a known bug on this architecture."); |
---|
302 | #else |
---|
303 | args[0] = &ffi_type_sint64; |
---|
304 | values[0] = ≪ |
---|
305 | |
---|
306 | /* Initialize the cif */ |
---|
307 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
308 | &ffi_type_sint64, args) == FFI_OK); |
---|
309 | |
---|
310 | for (ll = 0LL; ll < 100LL; ll++) |
---|
311 | { |
---|
312 | ul++; |
---|
313 | ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); |
---|
314 | CHECK(rlonglong == ll); |
---|
315 | } |
---|
316 | |
---|
317 | for (ll = 55555555555000LL; ll < 55555555555100LL; ll++) |
---|
318 | { |
---|
319 | ul++; |
---|
320 | ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); |
---|
321 | CHECK(rlonglong == ll); |
---|
322 | } |
---|
323 | #endif |
---|
324 | |
---|
325 | args[0] = &ffi_type_schar; |
---|
326 | values[0] = ≻ |
---|
327 | |
---|
328 | /* Initialize the cif */ |
---|
329 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
330 | &ffi_type_schar, args) == FFI_OK); |
---|
331 | |
---|
332 | for (sc = (signed char) -127; |
---|
333 | sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/) |
---|
334 | { |
---|
335 | ul++; |
---|
336 | ffi_call(&cif, FFI_FN(return_sc), &rint, values); |
---|
337 | CHECK(rint == (int) sc); |
---|
338 | } |
---|
339 | |
---|
340 | args[0] = &ffi_type_uchar; |
---|
341 | values[0] = &uc; |
---|
342 | |
---|
343 | /* Initialize the cif */ |
---|
344 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
345 | &ffi_type_uchar, args) == FFI_OK); |
---|
346 | |
---|
347 | for (uc = (unsigned char) '\x00'; |
---|
348 | uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/) |
---|
349 | { |
---|
350 | ul++; |
---|
351 | ffi_call(&cif, FFI_FN(return_uc), &rint, values); |
---|
352 | CHECK(rint == (signed int) uc); |
---|
353 | } |
---|
354 | |
---|
355 | printf("%lu return value tests run\n", ul); |
---|
356 | } |
---|
357 | |
---|
358 | #ifdef BROKEN_LONG_DOUBLE |
---|
359 | printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n"); |
---|
360 | #else |
---|
361 | /* float arg tests */ |
---|
362 | { |
---|
363 | args[0] = &ffi_type_float; |
---|
364 | values[0] = &f; |
---|
365 | |
---|
366 | /* Initialize the cif */ |
---|
367 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
368 | &ffi_type_longdouble, args) == FFI_OK); |
---|
369 | |
---|
370 | f = 3.14159; |
---|
371 | |
---|
372 | #if 0 |
---|
373 | /* This is ifdef'd out for now. long double support under SunOS/gcc |
---|
374 | is pretty much non-existent. You'll get the odd bus error in library |
---|
375 | routines like printf(). */ |
---|
376 | printf ("%Lf\n", ldblit(f)); |
---|
377 | #endif |
---|
378 | ld = 666; |
---|
379 | ffi_call(&cif, FFI_FN(ldblit), &ld, values); |
---|
380 | |
---|
381 | #if 0 |
---|
382 | /* This is ifdef'd out for now. long double support under SunOS/gcc |
---|
383 | is pretty much non-existent. You'll get the odd bus error in library |
---|
384 | routines like printf(). */ |
---|
385 | printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON); |
---|
386 | #endif |
---|
387 | |
---|
388 | /* These are not always the same!! Check for a reasonable delta */ |
---|
389 | /*@-realcompare@*/ |
---|
390 | if (ld - ldblit(f) < LDBL_EPSILON) |
---|
391 | /*@=realcompare@*/ |
---|
392 | puts("long double return value tests ok!"); |
---|
393 | else |
---|
394 | CHECK(0); |
---|
395 | } |
---|
396 | |
---|
397 | /* float arg tests */ |
---|
398 | { |
---|
399 | args[0] = &ffi_type_sint; |
---|
400 | values[0] = &si1; |
---|
401 | args[1] = &ffi_type_float; |
---|
402 | values[1] = &f; |
---|
403 | args[2] = &ffi_type_double; |
---|
404 | values[2] = &d; |
---|
405 | args[3] = &ffi_type_longdouble; |
---|
406 | values[3] = &ld; |
---|
407 | args[4] = &ffi_type_sint; |
---|
408 | values[4] = &si2; |
---|
409 | |
---|
410 | /* Initialize the cif */ |
---|
411 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5, |
---|
412 | &ffi_type_sint, args) == FFI_OK); |
---|
413 | |
---|
414 | si1 = 6; |
---|
415 | f = 3.14159; |
---|
416 | d = (double)1.0/(double)3.0; |
---|
417 | ld = 2.71828182846L; |
---|
418 | si2 = 10; |
---|
419 | |
---|
420 | floating (si1, f, d, ld, si2); |
---|
421 | |
---|
422 | ffi_call(&cif, FFI_FN(floating), &rint, values); |
---|
423 | |
---|
424 | printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2)); |
---|
425 | |
---|
426 | CHECK(rint == floating(si1, f, d, ld, si2)); |
---|
427 | |
---|
428 | printf("float arg tests ok!\n"); |
---|
429 | } |
---|
430 | #endif |
---|
431 | |
---|
432 | /* strlen tests */ |
---|
433 | { |
---|
434 | args[0] = &ffi_type_pointer; |
---|
435 | values[0] = (void*) &s; |
---|
436 | |
---|
437 | /* Initialize the cif */ |
---|
438 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
439 | &ffi_type_sint, args) == FFI_OK); |
---|
440 | |
---|
441 | s = "a"; |
---|
442 | ffi_call(&cif, FFI_FN(my_strlen), &rint, values); |
---|
443 | CHECK(rint == 1); |
---|
444 | |
---|
445 | s = "1234567"; |
---|
446 | ffi_call(&cif, FFI_FN(my_strlen), &rint, values); |
---|
447 | CHECK(rint == 7); |
---|
448 | |
---|
449 | s = "1234567890123456789012345"; |
---|
450 | ffi_call(&cif, FFI_FN(my_strlen), &rint, values); |
---|
451 | CHECK(rint == 25); |
---|
452 | |
---|
453 | printf("strlen tests passed\n"); |
---|
454 | } |
---|
455 | |
---|
456 | /* float arg tests */ |
---|
457 | { |
---|
458 | args[0] = &ffi_type_float; |
---|
459 | values[0] = &f; |
---|
460 | |
---|
461 | /* Initialize the cif */ |
---|
462 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
463 | &ffi_type_double, args) == FFI_OK); |
---|
464 | |
---|
465 | f = 3.14159; |
---|
466 | |
---|
467 | ffi_call(&cif, FFI_FN(dblit), &d, values); |
---|
468 | |
---|
469 | /* These are not always the same!! Check for a reasonable delta */ |
---|
470 | /*@-realcompare@*/ |
---|
471 | CHECK(d - dblit(f) < DBL_EPSILON); |
---|
472 | /*@=realcompare@*/ |
---|
473 | |
---|
474 | printf("double return value tests ok!\n"); |
---|
475 | } |
---|
476 | |
---|
477 | /* many arg tests */ |
---|
478 | { |
---|
479 | float ff; |
---|
480 | float fa[13]; |
---|
481 | |
---|
482 | for (ul = 0; ul < 13; ul++) |
---|
483 | { |
---|
484 | args[ul] = &ffi_type_float; |
---|
485 | values[ul] = &fa[ul]; |
---|
486 | fa[ul] = (float) ul; |
---|
487 | } |
---|
488 | |
---|
489 | /* Initialize the cif */ |
---|
490 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, |
---|
491 | &ffi_type_float, args) == FFI_OK); |
---|
492 | |
---|
493 | /*@-usedef@*/ |
---|
494 | ff = many(fa[0], fa[1], |
---|
495 | fa[2], fa[3], |
---|
496 | fa[4], fa[5], |
---|
497 | fa[6], fa[7], |
---|
498 | fa[8], fa[9], |
---|
499 | fa[10],fa[11],fa[12]); |
---|
500 | /*@=usedef@*/ |
---|
501 | |
---|
502 | ffi_call(&cif, FFI_FN(many), &f, values); |
---|
503 | |
---|
504 | /*@-realcompare@*/ |
---|
505 | if (f - ff < FLT_EPSILON) |
---|
506 | /*@=realcompare@*/ |
---|
507 | printf("many arg tests ok!\n"); |
---|
508 | else |
---|
509 | #ifdef POWERPC |
---|
510 | printf("many arg tests failed! This is a gcc bug.\n"); |
---|
511 | #else |
---|
512 | CHECK(0); |
---|
513 | #endif |
---|
514 | } |
---|
515 | |
---|
516 | /* promotion tests */ |
---|
517 | { |
---|
518 | args[0] = &ffi_type_schar; |
---|
519 | args[1] = &ffi_type_sshort; |
---|
520 | args[2] = &ffi_type_uchar; |
---|
521 | args[3] = &ffi_type_ushort; |
---|
522 | values[0] = ≻ |
---|
523 | values[1] = &ss; |
---|
524 | values[2] = &uc; |
---|
525 | values[3] = &us; |
---|
526 | |
---|
527 | /* Initialize the cif */ |
---|
528 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, |
---|
529 | &ffi_type_sint, args) == FFI_OK); |
---|
530 | |
---|
531 | us = 0; |
---|
532 | ul = 0; |
---|
533 | |
---|
534 | for (sc = (signed char) -127; |
---|
535 | sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/) |
---|
536 | for (ss = -30000; ss <= 30000; ss += 10000) |
---|
537 | for (uc = (unsigned char) 0; |
---|
538 | uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/) |
---|
539 | for (us = 0; us <= 60000; us += 10000) |
---|
540 | { |
---|
541 | ul++; |
---|
542 | ffi_call(&cif, FFI_FN(promotion), &rint, values); |
---|
543 | CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us); |
---|
544 | } |
---|
545 | printf("%lu promotion tests run\n", ul); |
---|
546 | } |
---|
547 | |
---|
548 | /* struct tests */ |
---|
549 | { |
---|
550 | test_structure_1 ts1_arg; |
---|
551 | /* This is a hack to get a properly aligned result buffer */ |
---|
552 | test_structure_1 *ts1_result = |
---|
553 | (test_structure_1 *) malloc (sizeof(test_structure_1)); |
---|
554 | if (! ts1_result ) |
---|
555 | rtems_panic("Could not get memory for struct 1 result."); |
---|
556 | args[0] = &ts1_type; |
---|
557 | values[0] = &ts1_arg; |
---|
558 | |
---|
559 | /* Initialize the cif */ |
---|
560 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
561 | &ts1_type, args) == FFI_OK); |
---|
562 | |
---|
563 | ts1_arg.uc = '\x01'; |
---|
564 | ts1_arg.d = 3.14159; |
---|
565 | ts1_arg.ui = 555; |
---|
566 | |
---|
567 | ffi_call(&cif, FFI_FN(struct1), ts1_result, values); |
---|
568 | |
---|
569 | CHECK(ts1_result->ui == 556); |
---|
570 | CHECK(ts1_result->d == 3.14159 - 1); |
---|
571 | |
---|
572 | puts ("structure test 1 ok!\n"); |
---|
573 | |
---|
574 | free (ts1_result); |
---|
575 | } |
---|
576 | |
---|
577 | /* struct tests */ |
---|
578 | { |
---|
579 | test_structure_2 ts2_arg; |
---|
580 | |
---|
581 | /* This is a hack to get a properly aligned result buffer */ |
---|
582 | test_structure_2 *ts2_result = |
---|
583 | (test_structure_2 *) malloc (sizeof(test_structure_2)); |
---|
584 | |
---|
585 | args[0] = &ts2_type; |
---|
586 | values[0] = &ts2_arg; |
---|
587 | |
---|
588 | /* Initialize the cif */ |
---|
589 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
590 | &ts2_type, args) == FFI_OK); |
---|
591 | |
---|
592 | ts2_arg.d1 = 5.55; |
---|
593 | ts2_arg.d2 = 6.66; |
---|
594 | |
---|
595 | printf ("%g\n", ts2_result->d1); |
---|
596 | printf ("%g\n", ts2_result->d2); |
---|
597 | |
---|
598 | ffi_call(&cif, FFI_FN(struct2), ts2_result, values); |
---|
599 | |
---|
600 | printf ("%g\n", ts2_result->d1); |
---|
601 | printf ("%g\n", ts2_result->d2); |
---|
602 | |
---|
603 | CHECK(ts2_result->d1 == 5.55 - 1); |
---|
604 | CHECK(ts2_result->d2 == 6.66 - 1); |
---|
605 | |
---|
606 | printf("structure test 2 ok!\n"); |
---|
607 | |
---|
608 | free (ts2_result); |
---|
609 | } |
---|
610 | |
---|
611 | /* struct tests */ |
---|
612 | { |
---|
613 | int compare_value; |
---|
614 | test_structure_3 ts3_arg; |
---|
615 | test_structure_3 *ts3_result = |
---|
616 | (test_structure_3 *) malloc (sizeof(test_structure_3)); |
---|
617 | |
---|
618 | args[0] = &ts3_type; |
---|
619 | values[0] = &ts3_arg; |
---|
620 | |
---|
621 | /* Initialize the cif */ |
---|
622 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
623 | &ts3_type, args) == FFI_OK); |
---|
624 | |
---|
625 | ts3_arg.si = -123; |
---|
626 | compare_value = ts3_arg.si; |
---|
627 | |
---|
628 | ffi_call(&cif, FFI_FN(struct3), ts3_result, values); |
---|
629 | |
---|
630 | printf ("%d %d\n", ts3_result->si, -(compare_value*2)); |
---|
631 | |
---|
632 | if (ts3_result->si == -(ts3_arg.si*2)) |
---|
633 | puts ("structure test 3 ok!"); |
---|
634 | else |
---|
635 | { |
---|
636 | puts ("Structure test 3 found structure passing bug."); |
---|
637 | puts (" Current versions of GCC are not 100% compliant with the"); |
---|
638 | puts (" n32 ABI. There is a known problem related to passing"); |
---|
639 | puts (" small structures. Send a bug report to the gcc maintainers."); |
---|
640 | } |
---|
641 | |
---|
642 | free (ts3_result); |
---|
643 | } |
---|
644 | |
---|
645 | /* struct tests */ |
---|
646 | { |
---|
647 | test_structure_4 ts4_arg; |
---|
648 | |
---|
649 | /* This is a hack to get a properly aligned result buffer */ |
---|
650 | test_structure_4 *ts4_result = |
---|
651 | (test_structure_4 *) malloc (sizeof(test_structure_4)); |
---|
652 | |
---|
653 | args[0] = &ts4_type; |
---|
654 | values[0] = &ts4_arg; |
---|
655 | |
---|
656 | /* Initialize the cif */ |
---|
657 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, |
---|
658 | &ts4_type, args) == FFI_OK); |
---|
659 | |
---|
660 | ts4_arg.ui1 = 2; |
---|
661 | ts4_arg.ui2 = 3; |
---|
662 | ts4_arg.ui3 = 4; |
---|
663 | |
---|
664 | ffi_call (&cif, FFI_FN(struct4), ts4_result, values); |
---|
665 | |
---|
666 | if (ts4_result->ui3 == 2U * 3U * 4U) |
---|
667 | puts ("structure test 4 ok!"); |
---|
668 | else |
---|
669 | puts ("Structure test 4 found GCC's structure passing bug."); |
---|
670 | |
---|
671 | free (ts4_result); |
---|
672 | } |
---|
673 | |
---|
674 | /* struct tests */ |
---|
675 | { |
---|
676 | test_structure_5 ts5_arg1, ts5_arg2; |
---|
677 | |
---|
678 | /* This is a hack to get a properly aligned result buffer */ |
---|
679 | test_structure_5 *ts5_result = |
---|
680 | (test_structure_5 *) malloc (sizeof(test_structure_5)); |
---|
681 | |
---|
682 | args[0] = &ts5_type; |
---|
683 | args[1] = &ts5_type; |
---|
684 | values[0] = &ts5_arg1; |
---|
685 | values[1] = &ts5_arg2; |
---|
686 | |
---|
687 | /* Initialize the cif */ |
---|
688 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, |
---|
689 | &ts5_type, args) == FFI_OK); |
---|
690 | |
---|
691 | ts5_arg1.c1 = 2; |
---|
692 | ts5_arg1.c2 = 6; |
---|
693 | ts5_arg2.c1 = 5; |
---|
694 | ts5_arg2.c2 = 3; |
---|
695 | |
---|
696 | ffi_call (&cif, FFI_FN(struct5), ts5_result, values); |
---|
697 | |
---|
698 | if (ts5_result->c1 == 7 |
---|
699 | && ts5_result->c2 == 3) |
---|
700 | puts ("structure test 5 ok!"); |
---|
701 | else |
---|
702 | puts ("Structure test 5 found GCC's structure passing bug."); |
---|
703 | |
---|
704 | free (ts5_result); |
---|
705 | } |
---|
706 | |
---|
707 | # if FFI_CLOSURES |
---|
708 | /* A simple closure test */ |
---|
709 | { |
---|
710 | ffi_closure cl; |
---|
711 | ffi_type * cl_arg_types[3]; |
---|
712 | |
---|
713 | cl_arg_types[0] = &ffi_type_sint; |
---|
714 | cl_arg_types[1] = &ffi_type_float; |
---|
715 | cl_arg_types[2] = NULL; |
---|
716 | |
---|
717 | /* Initialize the cif */ |
---|
718 | CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, |
---|
719 | &ffi_type_sint, cl_arg_types) == FFI_OK); |
---|
720 | |
---|
721 | CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn, |
---|
722 | (void *) 3 /* userdata */) |
---|
723 | == FFI_OK); |
---|
724 | CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6); |
---|
725 | } |
---|
726 | # endif |
---|
727 | |
---|
728 | /* If we arrived here, all is good */ |
---|
729 | (void) puts("\nLooks good. No surprises.\n"); |
---|
730 | |
---|
731 | /*@-compdestroy@*/ |
---|
732 | |
---|
733 | return 0; |
---|
734 | } |
---|
735 | |
---|