1 ! Copyright (C) 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays kernel assocs sequences sequences.lib fry accessors
4 namespaces math combinators math.order
6 compiler.tree.combinators
7 compiler.tree.propagation.info
10 compiler.vops.builder ;
11 IN: compiler.cfg.builder
13 ! Convert tree SSA IR to CFG SSA IR.
15 ! We construct the graph and set successors first, then we
16 ! set predecessors in a separate pass. This simplifies the
25 GENERIC: convert ( node -- )
27 M: #introduce convert drop ;
30 H{ } clone values>vregs set ;
32 : end-basic-block ( -- )
33 basic-block get [ %b emit ] when ;
35 : set-basic-block ( basic-block -- )
36 [ basic-block set ] [ instructions>> building set ] bi ;
38 : begin-basic-block ( -- )
39 <basic-block> basic-block get
42 dupd successors>> push
46 : convert-nodes ( node -- )
49 : (build-cfg) ( node word -- )
52 basic-block get swap procedures get set-at
55 : build-cfg ( node word -- procedures )
57 procedures [ (build-cfg) ] with-variable
60 : value>vreg ( value -- vreg )
63 : output-vreg ( value vreg -- )
64 swap values>vregs get set-at ;
66 : produce-vreg ( value -- vreg )
67 next-vreg [ output-vreg ] keep ;
69 : (load-inputs) ( seq stack -- )
70 over empty? [ 2drop ] [
72 [ '[ produce-vreg _ , %peek emit ] each-index ]
73 [ [ length neg ] dip %height emit ]
77 : load-in-d ( node -- ) in-d>> %data (load-inputs) ;
79 : load-in-r ( node -- ) in-r>> %retain (load-inputs) ;
81 : (store-outputs) ( seq stack -- )
82 over empty? [ 2drop ] [
84 [ [ length ] dip %height emit ]
85 [ '[ value>vreg _ , %replace emit ] each-index ]
89 : store-out-d ( node -- ) out-d>> %data (store-outputs) ;
91 : store-out-r ( node -- ) out-r>> %retain (store-outputs) ;
93 : (emit-call) ( word -- )
94 begin-basic-block %call emit begin-basic-block ;
96 : intrinsic-inputs ( node -- )
98 [ in-d>> { #1 #2 #3 #4 } [ [ value>vreg ] dip set ] 2each ]
101 : intrinsic-outputs ( node -- )
102 [ out-d>> { ^1 ^2 ^3 ^4 } [ get output-vreg ] 2each ]
106 : intrinsic ( node quot -- )
112 [ intrinsic-outputs ]
114 ] with-scope ; inline
116 USING: kernel.private math.private slots.private ;
118 : maybe-emit-fixnum-shift-fast ( node -- node )
119 dup dup in-d>> second node-value-info literal>> dup fixnum? [
120 '[ , emit-fixnum-shift-fast ] intrinsic
122 drop dup word>> (emit-call)
125 : emit-call ( node -- )
127 { \ tag [ [ emit-tag ] intrinsic ] }
129 { \ slot [ [ dup emit-slot ] intrinsic ] }
130 { \ set-slot [ [ dup emit-set-slot ] intrinsic ] }
132 { \ fixnum-bitnot [ [ emit-fixnum-bitnot ] intrinsic ] }
133 { \ fixnum+fast [ [ emit-fixnum+fast ] intrinsic ] }
134 { \ fixnum-fast [ [ emit-fixnum-fast ] intrinsic ] }
135 { \ fixnum-bitand [ [ emit-fixnum-bitand ] intrinsic ] }
136 { \ fixnum-bitor [ [ emit-fixnum-bitor ] intrinsic ] }
137 { \ fixnum-bitxor [ [ emit-fixnum-bitxor ] intrinsic ] }
138 { \ fixnum*fast [ [ emit-fixnum*fast ] intrinsic ] }
139 { \ fixnum<= [ [ emit-fixnum<= ] intrinsic ] }
140 { \ fixnum>= [ [ emit-fixnum>= ] intrinsic ] }
141 { \ fixnum< [ [ emit-fixnum< ] intrinsic ] }
142 { \ fixnum> [ [ emit-fixnum> ] intrinsic ] }
143 { \ eq? [ [ emit-eq? ] intrinsic ] }
145 { \ fixnum-shift-fast [ maybe-emit-fixnum-shift-fast ] }
147 { \ float+ [ [ emit-float+ ] intrinsic ] }
148 { \ float- [ [ emit-float- ] intrinsic ] }
149 { \ float* [ [ emit-float* ] intrinsic ] }
150 { \ float/f [ [ emit-float/f ] intrinsic ] }
151 { \ float<= [ [ emit-float<= ] intrinsic ] }
152 { \ float>= [ [ emit-float>= ] intrinsic ] }
153 { \ float< [ [ emit-float< ] intrinsic ] }
154 { \ float> [ [ emit-float> ] intrinsic ] }
155 { \ float? [ [ emit-float= ] intrinsic ] }
157 ! { \ (tuple) [ dup first-input '[ , emit-(tuple) ] intrinsic ] }
158 ! { \ (array) [ dup first-input '[ , emit-(array) ] intrinsic ] }
159 ! { \ (byte-array) [ dup first-input '[ , emit-(byte-array) ] intrinsic ] }
164 M: #call convert emit-call ;
166 : emit-call-loop ( #recursive -- )
167 dup label>> loop-nesting get at basic-block get successors>> push
172 : emit-call-recursive ( #recursive -- )
173 label>> id>> (emit-call) ;
175 M: #call-recursive convert
177 [ emit-call-loop ] [ emit-call-recursive ] if ;
181 [ out-d>> first produce-vreg ]
182 [ node-output-infos first literal>> ]
187 M: #shuffle convert [ load-in-d ] [ store-out-d ] bi ;
189 M: #>r convert [ load-in-d ] [ store-out-r ] bi ;
191 M: #r> convert [ load-in-r ] [ store-out-d ] bi ;
193 M: #terminate convert drop ;
195 : integer-conditional ( in1 in2 cc -- )
196 [ [ next-vreg dup ] 2dip %icmp emit ] dip %bi emit ; inline
198 : float-conditional ( in1 in2 branch -- )
199 [ next-vreg [ %fcmp emit ] keep ] dip emit ; inline
202 in-d>> first value>vreg
203 next-vreg dup f emit-literal
204 cc/= integer-conditional ;
206 : convert-nested ( node -- last-bb )
209 [ set-basic-block ] keep
210 [ convert-nodes end-basic-block ] dip
213 [ basic-block get successors>> push ] dip ;
215 : convert-if-children ( #if -- )
216 children>> [ convert-nested ] map sift
218 [ '[ , _ successors>> push ] each ]
223 [ load-in-d ] [ emit-if ] [ convert-if-children ] tri ;
226 "Unimplemented" throw ;
228 M: #phi convert drop ;
230 M: #declare convert drop ;
232 M: #return convert drop %return emit ;
234 : convert-recursive ( #recursive -- )
235 [ [ label>> id>> ] [ child>> ] bi (build-cfg) ]
239 : begin-loop ( #recursive -- )
240 label>> basic-block get 2array loop-nesting get push ;
243 loop-nesting get pop* ;
245 : convert-loop ( #recursive -- )
248 [ child>> convert-nodes ]
252 M: #recursive convert
254 [ convert-loop ] [ convert-recursive ] if ;
256 M: #copy convert drop ;