]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/tests/alien.factor
FFI rewrite part 1: split up ##alien-invoke and friends into smaller instructions
[factor.git] / basis / compiler / tests / alien.factor
1 USING: accessors alien alien.c-types alien.libraries
2 alien.syntax arrays classes.struct combinators
3 compiler continuations effects generalizations io
4 io.backend io.pathnames io.streams.string kernel
5 math memory namespaces namespaces.private parser
6 quotations sequences specialized-arrays stack-checker
7 stack-checker.errors system threads tools.test words
8 alien.complex concurrency.promises ;
9 FROM: alien.c-types => float short ;
10 SPECIALIZED-ARRAY: float
11 SPECIALIZED-ARRAY: char
12 IN: compiler.tests.alien
13
14 <<
15 : libfactor-ffi-tests-path ( -- string )
16     "resource:" absolute-path
17     {
18         { [ os winnt? ]  [ "libfactor-ffi-test.dll" ] }
19         { [ os macosx? ] [ "libfactor-ffi-test.dylib" ] }
20         { [ os unix?  ]  [ "libfactor-ffi-test.so" ] }
21     } cond append-path ;
22
23 : mingw? ( -- ? ) os windows? vm-compiler "GCC" head? and ;
24
25 "f-cdecl" libfactor-ffi-tests-path mingw? mingw cdecl ? add-library
26
27 "f-stdcall" libfactor-ffi-tests-path stdcall add-library
28
29 "f-fastcall" libfactor-ffi-tests-path fastcall add-library
30 >>
31
32 LIBRARY: f-cdecl
33
34 FUNCTION: void ffi_test_0 ;
35 [ ] [ ffi_test_0 ] unit-test
36
37 FUNCTION: int ffi_test_1 ;
38 [ 3 ] [ ffi_test_1 ] unit-test
39
40 FUNCTION: int ffi_test_2 int x int y ;
41 [ 5 ] [ 2 3 ffi_test_2 ] unit-test
42 [ "hi" 3 ffi_test_2 ] must-fail
43
44 FUNCTION: int ffi_test_3 int x int y int z int t ;
45 [ 25 ] [ 2 3 4 5 ffi_test_3 ] unit-test
46
47 FUNCTION: float ffi_test_4 ;
48 [ 1.5 ] [ ffi_test_4 ] unit-test
49
50 FUNCTION: double ffi_test_5 ;
51 [ 1.5 ] [ ffi_test_5 ] unit-test
52
53 FUNCTION: int ffi_test_9 int a int b int c int d int e int f int g ;
54 [ 28 ] [ 1 2 3 4 5 6 7 ffi_test_9 ] unit-test
55 [ "a" 2 3 4 5 6 7 ffi_test_9 ] must-fail
56 [ 1 2 3 4 5 6 "a" ffi_test_9 ] must-fail
57
58 STRUCT: FOO { x int } { y int } ;
59
60 : make-FOO ( x y -- FOO )
61     FOO <struct> swap >>y swap >>x ;
62
63 FUNCTION: int ffi_test_11 int a FOO b int c ;
64
65 [ 14 ] [ 1 2 3 make-FOO 4 ffi_test_11 ] unit-test
66
67 FUNCTION: int ffi_test_13 int a int b int c int d int e int f int g int h int i int j int k ;
68
69 [ 66 ] [ 1 2 3 4 5 6 7 8 9 10 11 ffi_test_13 ] unit-test
70
71 FUNCTION: FOO ffi_test_14 int x int y ;
72
73 [ 11 6 ] [ 11 6 ffi_test_14 [ x>> ] [ y>> ] bi ] unit-test
74
75 FUNCTION: c-string ffi_test_15 c-string x c-string y ;
76
77 [ "foo" ] [ "xy" "zt" ffi_test_15 ] unit-test
78 [ "bar" ] [ "xy" "xy" ffi_test_15 ] unit-test
79 [ 1 2 ffi_test_15 ] must-fail
80
81 STRUCT: BAR { x long } { y long } { z long } ;
82
83 FUNCTION: BAR ffi_test_16 long x long y long z ;
84
85 [ 11 6 -7 ] [
86     11 6 -7 ffi_test_16 [ x>> ] [ y>> ] [ z>> ] tri
87 ] unit-test
88
89 STRUCT: TINY { x int } ;
90
91 FUNCTION: TINY ffi_test_17 int x ;
92
93 [ 11 ] [ 11 ffi_test_17 x>> ] unit-test
94
95 [ [ alien-indirect ] infer ] [ inference-error? ] must-fail-with
96
97 : indirect-test-1 ( ptr -- result )
98     int { } cdecl alien-indirect ;
99
100 { 1 1 } [ indirect-test-1 ] must-infer-as
101
102 [ B{ } indirect-test-1 ] [ { "kernel-error" 3 6 B{ } } = ] must-fail-with
103
104 [ 3 ] [ &: ffi_test_1 indirect-test-1 ] unit-test
105
106 : indirect-test-1' ( ptr -- )
107     int { } cdecl alien-indirect drop ;
108
109 { 1 0 } [ indirect-test-1' ] must-infer-as
110
111 [ ] [ &: ffi_test_1 indirect-test-1' ] unit-test
112
113 [ -1 indirect-test-1 ] must-fail
114
115 : indirect-test-2 ( x y ptr -- result )
116     int { int int } cdecl alien-indirect gc ;
117
118 { 3 1 } [ indirect-test-2 ] must-infer-as
119
120 [ 5 ]
121 [ 2 3 &: ffi_test_2 indirect-test-2 ]
122 unit-test
123
124 : indirect-test-3 ( a b c d ptr -- result )
125     int { int int int int } stdcall alien-indirect
126     gc ;
127
128 [ f ] [ "f-stdcall" load-library f = ] unit-test
129 [ stdcall ] [ "f-stdcall" library abi>> ] unit-test
130
131 : ffi_test_18 ( w x y z -- int )
132     int "f-stdcall" "ffi_test_18" { int int int int }
133     alien-invoke gc ;
134
135 [ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test
136
137 : ffi_test_19 ( x y z -- BAR )
138     BAR "f-stdcall" "ffi_test_19" { long long long }
139     alien-invoke gc ;
140
141 [ 11 6 -7 ] [
142     11 6 -7 ffi_test_19 [ x>> ] [ y>> ] [ z>> ] tri
143 ] unit-test
144
145 : multi_ffi_test_18 ( w x y z w' x' y' z' -- int int )
146     [ int "f-stdcall" "ffi_test_18" { int int int int } alien-invoke ]
147     4 ndip
148     int "f-stdcall" "ffi_test_18" { int int int int } alien-invoke
149     gc ;
150
151 [ 25 85 ] [ 2 3 4 5 6 7 8 9 multi_ffi_test_18 ] unit-test
152
153 FUNCTION: double ffi_test_6 float x float y ;
154 [ 6.0 ] [ 3.0 2.0 ffi_test_6 ] unit-test
155 [ "a" "b" ffi_test_6 ] must-fail
156
157 FUNCTION: double ffi_test_7 double x double y ;
158 [ 6.0 ] [ 3.0 2.0 ffi_test_7 ] unit-test
159
160 FUNCTION: double ffi_test_8 double x float y double z float t int w ;
161 [ 19.0 ] [ 3.0 2.0 1.0 6.0 7 ffi_test_8 ] unit-test
162
163 FUNCTION: int ffi_test_10 int a int b double c int d float e int f int g int h ;
164 [ -34 ] [ 1 2 3.0 4 5.0 6 7 8 ffi_test_10 ] unit-test
165
166 FUNCTION: void ffi_test_20 double x1, double x2, double x3,
167     double y1, double y2, double y3,
168     double z1, double z2, double z3 ;
169
170 [ ] [ 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 ffi_test_20 ] unit-test
171
172 ! Make sure XT doesn't get clobbered in stack frame
173
174 : ffi_test_31 ( a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- result y )
175     int
176     "f-cdecl" "ffi_test_31"
177     { int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int int }
178     alien-invoke gc 3 ;
179
180 [ 861 3 ] [ 42 [ ] each-integer ffi_test_31 ] unit-test
181
182 : ffi_test_31_point_5 ( a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a -- result )
183     float
184     "f-cdecl" "ffi_test_31_point_5"
185     { float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float float }
186     alien-invoke ;
187
188 [ 861.0 ] [ 42 [ >float ] each-integer ffi_test_31_point_5 ] unit-test
189
190 FUNCTION: longlong ffi_test_21 long x long y ;
191
192 [ 121932631112635269 ]
193 [ 123456789 987654321 ffi_test_21 ] unit-test
194
195 FUNCTION: long ffi_test_22 long x longlong y longlong z ;
196
197 [ 987655432 ]
198 [ 1111 121932631112635269 123456789 ffi_test_22 ] unit-test
199
200 [ 1111 f 123456789 ffi_test_22 ] must-fail
201
202 STRUCT: RECT
203     { x float } { y float }
204     { w float } { h float } ;
205
206 : <RECT> ( x y w h -- rect )
207     RECT <struct>
208         swap >>h
209         swap >>w
210         swap >>y
211         swap >>x ;
212
213 FUNCTION: int ffi_test_12 int a int b RECT c int d int e int f ;
214
215 [ 45 ] [ 1 2 3.0 4.0 5.0 6.0 <RECT> 7 8 9 ffi_test_12 ] unit-test
216
217 [ 1 2 { 1 2 3 } 7 8 9 ffi_test_12 ] must-fail
218
219 FUNCTION: float ffi_test_23 ( float[3] x, float[3] y ) ;
220
221 [ 32.0 ] [
222     { 1.0 2.0 3.0 } >float-array
223     { 4.0 5.0 6.0 } >float-array
224     ffi_test_23
225 ] unit-test
226
227 ! Test odd-size structs
228 STRUCT: test-struct-1 { x char[1] } ;
229
230 FUNCTION: test-struct-1 ffi_test_24 ;
231
232 [ S{ test-struct-1 { x char-array{ 1 } } } ] [ ffi_test_24 ] unit-test
233
234 STRUCT: test-struct-2 { x char[2] } ;
235
236 FUNCTION: test-struct-2 ffi_test_25 ;
237
238 [ S{ test-struct-2 { x char-array{ 1 2 } } } ] [ ffi_test_25 ] unit-test
239
240 STRUCT: test-struct-3 { x char[3] } ;
241
242 FUNCTION: test-struct-3 ffi_test_26 ;
243
244 [ S{ test-struct-3 { x char-array{ 1 2 3 } } } ] [ ffi_test_26 ] unit-test
245
246 STRUCT: test-struct-4 { x char[4] } ;
247
248 FUNCTION: test-struct-4 ffi_test_27 ;
249
250 [ S{ test-struct-4 { x char-array{ 1 2 3 4 } } } ] [ ffi_test_27 ] unit-test
251
252 STRUCT: test-struct-5 { x char[5] } ;
253
254 FUNCTION: test-struct-5 ffi_test_28 ;
255
256 [ S{ test-struct-5 { x char-array{ 1 2 3 4 5 } } } ] [ ffi_test_28 ] unit-test
257
258 STRUCT: test-struct-6 { x char[6] } ;
259
260 FUNCTION: test-struct-6 ffi_test_29 ;
261
262 [ S{ test-struct-6 { x char-array{ 1 2 3 4 5 6 } } } ] [ ffi_test_29 ] unit-test
263
264 STRUCT: test-struct-7 { x char[7] } ;
265
266 FUNCTION: test-struct-7 ffi_test_30 ;
267
268 [ S{ test-struct-7 { x char-array{ 1 2 3 4 5 6 7 } } } ] [ ffi_test_30 ] unit-test
269
270 STRUCT: test-struct-8 { x double } { y double } ;
271
272 FUNCTION: double ffi_test_32 test-struct-8 x int y ;
273
274 [ 9.0 ] [
275     test-struct-8 <struct>
276     1.0 >>x
277     2.0 >>y
278     3 ffi_test_32
279 ] unit-test
280
281 STRUCT: test-struct-9 { x float } { y float } ;
282
283 FUNCTION: double ffi_test_33 test-struct-9 x int y ;
284
285 [ 9.0 ] [
286     test-struct-9 <struct>
287     1.0 >>x
288     2.0 >>y
289     3 ffi_test_33
290 ] unit-test
291
292 STRUCT: test-struct-10 { x float } { y int } ;
293
294 FUNCTION: double ffi_test_34 test-struct-10 x int y ;
295
296 [ 9.0 ] [
297     test-struct-10 <struct>
298     1.0 >>x
299     2 >>y
300     3 ffi_test_34
301 ] unit-test
302
303 STRUCT: test-struct-11 { x int } { y int } ;
304
305 FUNCTION: double ffi_test_35 test-struct-11 x int y ;
306
307 [ 9.0 ] [
308     test-struct-11 <struct>
309     1 >>x
310     2 >>y
311     3 ffi_test_35
312 ] unit-test
313
314 STRUCT: test-struct-12 { a int } { x double } ;
315
316 : make-struct-12 ( x -- alien )
317     test-struct-12 <struct>
318         swap >>x ;
319
320 FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
321
322 [ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test
323
324 FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;
325
326 [ t ] [ 31 2^ 32 2^ ffi_test_38 63 2^ = ] unit-test
327
328 ! Test callbacks
329
330 : callback-1 ( -- callback ) void { } cdecl [ ] alien-callback ;
331
332 [ 0 1 ] [ [ callback-1 ] infer [ in>> length ] [ out>> length ] bi ] unit-test
333
334 [ t ] [ callback-1 alien? ] unit-test
335
336 : callback_test_1 ( ptr -- ) void { } cdecl alien-indirect ;
337
338 [ ] [ callback-1 callback_test_1 ] unit-test
339
340 : callback-2 ( -- callback ) void { } cdecl [ [ 5 throw ] ignore-errors ] alien-callback ;
341
342 [ ] [ callback-2 callback_test_1 ] unit-test
343
344 : callback-3 ( -- callback ) void { } cdecl [ 5 "x" set ] alien-callback ;
345
346 [ t 3 5 ] [
347     [
348         namestack*
349         3 "x" set callback-3 callback_test_1
350         namestack* eq?
351         "x" get "x" get-global
352     ] with-scope
353 ] unit-test
354
355 : callback-5 ( -- callback )
356     void { } cdecl [ gc ] alien-callback ;
357
358 [ "testing" ] [
359     "testing" callback-5 callback_test_1
360 ] unit-test
361
362 : callback-5b ( -- callback )
363     void { } cdecl [ compact-gc ] alien-callback ;
364
365 [ "testing" ] [
366     "testing" callback-5b callback_test_1
367 ] unit-test
368
369 : callback-6 ( -- callback )
370     void { } cdecl [ [ continue ] callcc0 ] alien-callback ;
371
372 [ 1 2 3 ] [ callback-6 callback_test_1 1 2 3 ] unit-test
373
374 : callback-7 ( -- callback )
375     void { } cdecl [ 1000000 sleep ] alien-callback ;
376
377 [ 1 2 3 ] [ callback-7 callback_test_1 1 2 3 ] unit-test
378
379 [ f ] [ namespace global eq? ] unit-test
380
381 : callback-8 ( -- callback )
382     void { } cdecl [ [ ] in-thread yield ] alien-callback ;
383
384 [ ] [ callback-8 callback_test_1 ] unit-test
385
386 : callback-9 ( -- callback )
387     int { int int int } cdecl [
388         + + 1 +
389     ] alien-callback ;
390
391 FUNCTION: void ffi_test_36_point_5 ( ) ;
392
393 [ ] [ ffi_test_36_point_5 ] unit-test
394
395 FUNCTION: int ffi_test_37 ( void* func ) ;
396
397 [ 1 ] [ callback-9 ffi_test_37 ] unit-test
398
399 [ 7 ] [ callback-9 ffi_test_37 ] unit-test
400
401 STRUCT: test_struct_13
402 { x1 float }
403 { x2 float }
404 { x3 float }
405 { x4 float }
406 { x5 float }
407 { x6 float } ;
408
409 : make-test-struct-13 ( -- alien )
410     test_struct_13 <struct>
411         1.0 >>x1
412         2.0 >>x2
413         3.0 >>x3
414         4.0 >>x4
415         5.0 >>x5
416         6.0 >>x6 ;
417
418 FUNCTION: int ffi_test_39 ( long a, long b, test_struct_13 s ) ;
419
420 [ 21 ] [ 12347 12347 make-test-struct-13 ffi_test_39 ] unit-test
421
422 ! Joe Groff found this problem
423 STRUCT: double-rect
424 { a double }
425 { b double }
426 { c double }
427 { d double } ;
428
429 : <double-rect> ( a b c d -- foo )
430     double-rect <struct>
431         swap >>d
432         swap >>c
433         swap >>b
434         swap >>a ;
435
436 : >double-rect< ( foo -- a b c d )
437     {
438         [ a>> ]
439         [ b>> ]
440         [ c>> ]
441         [ d>> ]
442     } cleave ;
443
444 : double-rect-callback ( -- alien )
445     void { void* void* double-rect } cdecl
446     [ "example" set-global 2drop ] alien-callback ;
447
448 : double-rect-test ( arg callback -- arg' )
449     [ f f ] 2dip
450     void { void* void* double-rect } cdecl alien-indirect
451     "example" get-global ;
452
453 [ 1.0 2.0 3.0 4.0 ]
454 [
455     1.0 2.0 3.0 4.0 <double-rect>
456     double-rect-callback double-rect-test
457     >double-rect<
458 ] unit-test
459
460 STRUCT: test_struct_14
461     { x1 double }
462     { x2 double } ;
463
464 FUNCTION: test_struct_14 ffi_test_40 ( double x1, double x2 ) ;
465
466 [ 1.0 2.0 ] [
467     1.0 2.0 ffi_test_40 [ x1>> ] [ x2>> ] bi
468 ] unit-test
469
470 : callback-10 ( -- callback )
471     test_struct_14 { double double } cdecl
472     [
473         test_struct_14 <struct>
474             swap >>x2
475             swap >>x1
476     ] alien-callback ;
477
478 : callback-10-test ( x1 x2 callback -- result )
479     test_struct_14 { double double } cdecl alien-indirect ;
480
481 [ 1.0 2.0 ] [
482     1.0 2.0 callback-10 callback-10-test
483     [ x1>> ] [ x2>> ] bi
484 ] unit-test
485
486 FUNCTION: test-struct-12 ffi_test_41 ( int a, double x ) ;
487
488 [ 1 2.0 ] [
489     1 2.0 ffi_test_41
490     [ a>> ] [ x>> ] bi
491 ] unit-test
492
493 : callback-11 ( -- callback )
494     test-struct-12 { int double } cdecl
495     [
496         test-struct-12 <struct>
497             swap >>x
498             swap >>a
499     ] alien-callback ;
500
501 : callback-11-test ( x1 x2 callback -- result )
502     test-struct-12 { int double } cdecl alien-indirect ;
503
504 [ 1 2.0 ] [
505     1 2.0 callback-11 callback-11-test
506     [ a>> ] [ x>> ] bi
507 ] unit-test
508
509 STRUCT: test_struct_15
510     { x float }
511     { y float } ;
512
513 FUNCTION: test_struct_15 ffi_test_42 ( float x, float y ) ;
514
515 [ 1.0 2.0 ] [ 1.0 2.0 ffi_test_42 [ x>> ] [ y>> ] bi ] unit-test
516
517 : callback-12 ( -- callback )
518     test_struct_15 { float float } cdecl
519     [
520         test_struct_15 <struct>
521             swap >>y
522             swap >>x
523     ] alien-callback ;
524
525 : callback-12-test ( x1 x2 callback -- result )
526     test_struct_15 { float float } cdecl alien-indirect ;
527
528 [ 1.0 2.0 ] [
529     1.0 2.0 callback-12 callback-12-test [ x>> ] [ y>> ] bi
530 ] unit-test
531
532 STRUCT: test_struct_16
533     { x float }
534     { a int } ;
535
536 FUNCTION: test_struct_16 ffi_test_43 ( float x, int a ) ;
537
538 [ 1.0 2 ] [ 1.0 2 ffi_test_43 [ x>> ] [ a>> ] bi ] unit-test
539
540 : callback-13 ( -- callback )
541     test_struct_16 { float int } cdecl
542     [
543         test_struct_16 <struct>
544             swap >>a
545             swap >>x
546     ] alien-callback ;
547
548 : callback-13-test ( x1 x2 callback -- result )
549     test_struct_16 { float int } cdecl alien-indirect ;
550
551 [ 1.0 2 ] [
552     1.0 2 callback-13 callback-13-test
553     [ x>> ] [ a>> ] bi
554 ] unit-test
555
556 FUNCTION: test_struct_14 ffi_test_44 ( ) ; inline
557
558 [ 1.0 2.0 ] [ ffi_test_44 [ x1>> ] [ x2>> ] bi ] unit-test
559
560 : stack-frame-bustage ( -- a b ) ffi_test_44 gc 3 ;
561
562 [ ] [ stack-frame-bustage 2drop ] unit-test
563
564 ! C99 tests
565 os windows? [
566
567 FUNCTION: complex-float ffi_test_45 ( int x ) ;
568
569 [ C{ 3.0 0.0 } ] [ 3 ffi_test_45 ] unit-test
570
571 FUNCTION: complex-double ffi_test_46 ( int x ) ;
572
573 [ C{ 3.0 0.0 } ] [ 3 ffi_test_46 ] unit-test
574
575 FUNCTION: complex-float ffi_test_47 ( complex-float x, complex-double y ) ;
576
577 [ C{ 4.0 4.0 } ] [
578     C{ 1.0 2.0 }
579     C{ 1.5 1.0 } ffi_test_47
580 ] unit-test
581
582 ! Reported by jedahu
583 STRUCT: bool-field-test
584     { name c-string }
585     { on bool }
586     { parents short } ;
587
588 FUNCTION: short ffi_test_48 ( bool-field-test x ) ;
589
590 [ 123 ] [
591     bool-field-test <struct>
592         123 >>parents
593     ffi_test_48
594 ] unit-test
595
596 ] unless
597
598 ! Test interaction between threads and callbacks
599 : thread-callback-1 ( -- callback )
600     int { } cdecl [ yield 100 ] alien-callback ;
601
602 : thread-callback-2 ( -- callback )
603     int { } cdecl [ yield 200 ] alien-callback ;
604
605 : thread-callback-invoker ( callback -- n )
606     int { } cdecl alien-indirect ;
607
608 <promise> "p" set
609 [ thread-callback-1 thread-callback-invoker "p" get fulfill ] in-thread
610 [ 200 ] [ thread-callback-2 thread-callback-invoker ] unit-test
611 [ 100 ] [ "p" get ?promise ] unit-test
612
613 ! More alien-assembly tests are in cpu.* vocabs
614 : assembly-test-1 ( -- ) void { } cdecl [ ] alien-assembly ;
615
616 [ ] [ assembly-test-1 ] unit-test
617
618 [ f ] [ "f-fastcall" load-library f = ] unit-test
619 [ fastcall ] [ "f-fastcall" library abi>> ] unit-test
620
621 : ffi_test_49 ( x -- int )
622     int "f-fastcall" "ffi_test_49" { int }
623     alien-invoke gc ;
624 : ffi_test_50 ( x y -- int )
625     int "f-fastcall" "ffi_test_50" { int int }
626     alien-invoke gc ;
627 : ffi_test_51 ( x y z -- int )
628     int "f-fastcall" "ffi_test_51" { int int int }
629     alien-invoke gc ;
630 : multi_ffi_test_51 ( x y z x' y' z' -- int int )
631     [ int "f-fastcall" "ffi_test_51" { int int int } alien-invoke ]
632     3dip
633     int "f-fastcall" "ffi_test_51" { int int int } alien-invoke gc ;
634     
635 [ 4 ] [ 3 ffi_test_49 ] unit-test
636 [ 8 ] [ 3 4 ffi_test_50 ] unit-test
637 [ 13 ] [ 3 4 5 ffi_test_51 ] unit-test
638 [ 13 22 ] [ 3 4 5 6 7 8 multi_ffi_test_51 ] unit-test
639
640 : ffi_test_52 ( x y z -- int )
641     int "f-fastcall" "ffi_test_52" { int float int }
642     alien-invoke gc ;
643 : ffi_test_53 ( x y z w -- int )
644     int "f-fastcall" "ffi_test_53" { int float int int }
645     alien-invoke gc ;
646 : ffi_test_57 ( x y -- test-struct-11 )
647     test-struct-11 "f-fastcall" "ffi_test_57" { int int }
648     alien-invoke gc ;
649 : ffi_test_58 ( x y z -- test-struct-11 )
650     test-struct-11 "f-fastcall" "ffi_test_58" { int int int }
651     alien-invoke gc ;
652
653 ! GCC bugs
654 mingw? [
655     [ 13 ] [ 3 4.0 5 ffi_test_52 ] unit-test
656
657     [ 19 ] [ 3 4.0 5 6 ffi_test_53 ] unit-test
658 ] unless
659
660 [ S{ test-struct-11 f 7 -1 } ] [ 3 4 ffi_test_57 ] unit-test
661
662 [ S{ test-struct-11 f 7 -3 } ] [ 3 4 7 ffi_test_58 ] unit-test
663
664 : fastcall-ii-indirect ( x y ptr -- result )
665     int { int int } fastcall alien-indirect ;
666
667 : fastcall-iii-indirect ( x y z ptr -- result )
668     int { int int int } fastcall alien-indirect ;
669
670 : fastcall-ifi-indirect ( x y z ptr -- result )
671     int { int float int } fastcall alien-indirect ;
672
673 : fastcall-ifii-indirect ( x y z w ptr -- result )
674     int { int float int int } fastcall alien-indirect ;
675
676 : fastcall-struct-return-ii-indirect ( x y ptr -- result )
677     test-struct-11 { int int } fastcall alien-indirect ;
678
679 : fastcall-struct-return-iii-indirect ( x y z ptr -- result )
680     test-struct-11 { int int int } fastcall alien-indirect ;
681
682 : win32? ( -- ? ) os windows? cpu x86.32? and ;
683
684 [ 8 ] [
685     3 4
686     win32? [ &: @ffi_test_50@8 ] [ &: ffi_test_50 ] if
687     fastcall-ii-indirect
688 ] unit-test
689
690 [ 13 ] [
691     3 4 5
692     win32? [ &: @ffi_test_51@12 ] [ &: ffi_test_51 ] if
693     fastcall-iii-indirect
694 ] unit-test
695
696 mingw? [
697     [ 13 ] [
698         3 4.0 5
699         win32? [ &: @ffi_test_52@12 ] [ &: ffi_test_52 ] if
700         fastcall-ifi-indirect
701     ] unit-test
702
703     [ 19 ] [
704         3 4.0 5 6
705         win32? [ &: @ffi_test_53@16 ] [ &: ffi_test_53 ] if
706         fastcall-ifii-indirect
707     ] unit-test
708 ] unless
709
710 [ S{ test-struct-11 f 7 -1 } ]
711 [
712     3 4
713     win32? [ &: @ffi_test_57@8 ] [ &: ffi_test_57 ] if
714     fastcall-struct-return-ii-indirect
715 ] unit-test
716
717 [ S{ test-struct-11 f 7 -3 } ]
718 [
719     3 4 7
720     win32? [ &: @ffi_test_58@12 ] [ &: ffi_test_58 ] if
721     fastcall-struct-return-iii-indirect
722 ] unit-test
723
724 : fastcall-ii-callback ( -- ptr )
725     int { int int } fastcall [ + 1 + ] alien-callback ;
726
727 : fastcall-iii-callback ( -- ptr )
728     int { int int int } fastcall [ + + 1 + ] alien-callback ;
729
730 : fastcall-ifi-callback ( -- ptr )
731     int { int float int } fastcall
732     [ [ >integer ] dip + + 1 + ] alien-callback ;
733
734 : fastcall-ifii-callback ( -- ptr )
735     int { int float int int } fastcall
736     [ [ >integer ] 2dip + + + 1 + ] alien-callback ;
737
738 : fastcall-struct-return-ii-callback ( -- ptr )
739     test-struct-11 { int int } fastcall
740     [ [ + ] [ - ] 2bi test-struct-11 <struct-boa> ] alien-callback ;
741
742 : fastcall-struct-return-iii-callback ( -- ptr )
743     test-struct-11 { int int int } fastcall
744     [ [ drop + ] [ - nip ] 3bi test-struct-11 <struct-boa> ] alien-callback ;
745
746 [ 8 ] [ 3 4 fastcall-ii-callback fastcall-ii-indirect ] unit-test
747
748 [ 13 ] [ 3 4 5 fastcall-iii-callback fastcall-iii-indirect ] unit-test
749
750 [ 13 ] [ 3 4.0 5 fastcall-ifi-callback fastcall-ifi-indirect ] unit-test
751
752 [ 19 ] [ 3 4.0 5 6 fastcall-ifii-callback fastcall-ifii-indirect ] unit-test
753
754 [ S{ test-struct-11 f 7 -1 } ]
755 [ 3 4 fastcall-struct-return-ii-callback fastcall-struct-return-ii-indirect ] unit-test
756
757 [ S{ test-struct-11 f 7 -3 } ]
758 [ 3 4 7 fastcall-struct-return-iii-callback fastcall-struct-return-iii-indirect ] unit-test