1 ! Copyright (C) 2008, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs arrays layouts math math.order math.parser
4 combinators combinators.short-circuit fry make sequences
5 sequences.generalizations alien alien.private alien.strings
6 alien.c-types alien.libraries classes.struct namespaces kernel
7 strings libc locals quotations words cpu.architecture
8 compiler.utilities compiler.tree compiler.cfg
9 compiler.cfg.builder compiler.cfg.builder.alien.params
10 compiler.cfg.builder.alien.boxing compiler.cfg.builder.blocks
11 compiler.cfg.instructions compiler.cfg.stack-frame
12 compiler.cfg.stacks compiler.cfg.registers compiler.cfg.hats ;
13 FROM: compiler.errors => no-such-symbol no-such-library ;
14 IN: compiler.cfg.builder.alien
16 : unbox-parameters ( parameters -- vregs reps )
18 [ length iota <reversed> ] keep
19 [ [ <ds-loc> ^^peek ] [ base-type ] bi* unbox-parameter ]
20 2 2 mnmap [ concat ] bi@
22 [ length neg ##inc-d ] bi ;
24 : prepare-struct-caller ( vregs reps return -- vregs' reps' return-vreg/f )
26 heap-size cell f ^^local-allot [
28 [ int-rep struct-return-on-stack? 2array prefix ] bi*
32 : caller-parameter ( vreg rep on-stack? -- insn )
33 [ dup reg-class-of reg-class-full? ] dip or
34 [ [ alloc-stack-param ] keep \ ##store-stack-param new-insn ]
35 [ [ next-reg-param ] keep \ ##store-reg-param new-insn ]
38 : (caller-parameters) ( vregs reps -- )
39 ! Place ##store-stack-param instructions first. This ensures
40 ! that no registers are used after the ##store-reg-param
42 [ first2 caller-parameter ] 2map
43 [ ##store-stack-param? ] partition [ % ] bi@ ;
45 : caller-parameters ( params -- stack-size )
46 [ abi>> ] [ parameters>> ] [ return>> ] tri
49 _ prepare-struct-caller struct-return-area set
52 struct-return-area get
54 struct-return-area set ;
56 : box-return* ( node -- )
57 return>> [ ] [ base-type box-return 1 ##inc-d D 0 ##replace ] if-void ;
59 GENERIC# dlsym-valid? 1 ( symbols dll -- ? )
61 M: string dlsym-valid? dlsym ;
63 M: array dlsym-valid? '[ _ dlsym ] any? ;
65 : check-dlsym ( symbols dll -- )
68 [ drop ] [ cfg get word>> no-such-symbol ] if
69 ] [ dll-path cfg get word>> no-such-library drop ] if ;
71 : decorated-symbol ( params -- symbols )
72 [ function>> ] [ parameters>> [ stack-size ] map-sum number>string ] bi
76 [ "@" glue "_" prepend ]
77 [ "@" glue "@" prepend ]
81 : alien-invoke-dlsym ( params -- symbols dll )
82 [ dup abi>> callee-cleanup? [ decorated-symbol ] [ function>> ] if ]
83 [ library>> load-library ]
86 : alien-node-height ( params -- )
87 [ out-d>> length ] [ in-d>> length ] bi - adjust-d ;
89 : emit-alien-block ( node quot: ( params -- ) -- )
93 _ [ alien-node-height ] bi
94 ] emit-trivial-block ; inline
96 : emit-stack-frame ( stack-size params -- )
97 [ [ return>> ] [ abi>> ] bi stack-cleanup ##cleanup ]
98 [ drop ##stack-frame ]
101 M: #alien-invoke emit-node
104 [ caller-parameters ]
105 [ ##prepare-var-args alien-invoke-dlsym ##alien-invoke ]
111 M:: #alien-indirect emit-node ( node -- )
113 D 0 ^^peek -1 ##inc-d ^^unbox-any-c-ptr :> src
114 [ caller-parameters src ##alien-indirect ]
120 M: #alien-assembly emit-node
123 [ caller-parameters ]
124 [ quot>> ##alien-assembly ]
130 : callee-parameter ( rep on-stack? -- dst insn )
131 [ next-vreg dup ] 2dip
132 [ dup reg-class-of reg-class-full? ] dip or
133 [ [ alloc-stack-param ] keep \ ##load-stack-param new-insn ]
134 [ [ next-reg-param ] keep \ ##load-reg-param new-insn ]
137 : prepare-struct-callee ( c-type -- vreg )
139 [ int-rep struct-return-on-stack? callee-parameter , ] [ f ] if ;
141 : (callee-parameters) ( params -- vregs reps )
142 [ flatten-parameter-type ] map
144 [ [ first2 callee-parameter ] 1 2 mnmap ] 1 2 mnmap
145 concat [ ##load-reg-param? ] partition [ % ] bi@
150 : box-parameters ( vregs reps params -- )
152 next-vreg next-vreg ##restore-context
154 next-vreg next-vreg ##save-context
156 1 ##inc-d D 0 ##replace
159 : callee-parameters ( params -- stack-size )
160 [ abi>> ] [ return>> ] [ parameters>> ] tri
162 _ prepare-struct-callee struct-return-area set
163 _ [ base-type ] map [ (callee-parameters) ] [ box-parameters ] bi
165 struct-return-area get
167 struct-return-area set ;
169 : callback-stack-cleanup ( stack-size params -- )
170 [ nip xt>> ] [ [ return>> ] [ abi>> ] bi stack-cleanup ] 2bi
171 "stack-cleanup" set-word-prop ;
173 : needs-frame-pointer ( -- )
174 cfg get t >>frame-pointer? drop ;
176 M: #alien-callback emit-node
177 dup params>> xt>> dup
184 [ callee-parameters ]
185 [ quot>> ##alien-callback ]
187 return>> [ ##end-callback ] [
190 base-type unbox-return
193 [ callback-stack-cleanup ]