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