1 ! Copyright (C) 2004, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: arrays assembler errors generic hashtables inference
5 kernel kernel-internals math namespaces sequences words ;
7 GENERIC: stack-reserve* ( node -- n )
9 M: object stack-reserve* drop 0 ;
11 : stack-reserve ( node -- n )
12 0 swap [ stack-reserve* max ] each-node ;
14 : intrinsic ( #call -- quot )
15 node-param "intrinsic" word-prop ;
17 : if-intrinsic ( #call -- quot )
18 node-param "if-intrinsic" word-prop ;
22 PREDICATE: #merge #terminal-merge node-successor #terminal? ;
24 PREDICATE: #values #terminal-values node-successor #terminal? ;
26 PREDICATE: #call #terminal-call
27 dup node-successor #if?
28 over node-successor node-successor #terminal? and
29 swap if-intrinsic and ;
32 POSTPONE: f #return #terminal-values #terminal-merge ;
36 dup #terminal-call? swap node-successor #terminal? or
39 : generate-code ( node quot -- )
40 over stack-reserve %prologue call ; inline
42 : init-generator ( word -- )
43 #! The first entry in the literal table is the word itself,
44 #! this is for compiled call traces
45 V{ } clone relocation-table set
46 V{ } clone literal-table set
47 V{ } clone label-table set
48 V{ } clone word-table set
49 literal-table get push ;
51 : generate-1 ( word node quot -- )
52 #! Generate the code, then dump three vectors to pass to
53 #! add-compiled-block.
62 ] V{ } make code-format add-compiled-block save-xt ;
64 GENERIC: generate-node ( node -- next )
66 : generate-nodes ( node -- )
67 [ node@ generate-node ] iterate-nodes end-basic-block ;
69 : generate-branch ( node -- )
70 [ generate-nodes ] keep-templates ;
72 : generate ( word node -- )
73 [ [ generate-nodes ] with-node-iterator ] generate-1 ;
76 M: node generate-node drop iterate-next ;
79 : generate-call ( label -- next )
81 tail-call? [ %jump f ] [ %call iterate-next ] if ;
83 M: #label generate-node
84 dup node-param dup generate-call >r
85 swap node-child generate r> ;
88 : end-false-branch ( label -- )
89 tail-call? [ %return drop ] [ %jump-label ] if ;
91 : generate-if ( node label -- next )
93 >r >r node-children first2 generate-branch
94 r> r> end-false-branch resolve-label
97 ] keep resolve-label iterate-next ;
100 [ <label> dup %jump-t ]
101 H{ { +input+ { { f "flag" } } } }
106 : [with-template] ( quot template -- quot )
107 \ with-template 3array >quotation ;
109 : define-intrinsic ( word quot template -- )
110 [with-template] "intrinsic" set-word-prop ;
112 : define-if>branch-intrinsic ( word quot inputs -- )
114 [with-template] "if-intrinsic" set-word-prop ;
116 : if>boolean-intrinsic ( quot -- )
120 f "if-scratch" get load-literal
121 "end" get %jump-label
123 t "if-scratch" get load-literal
125 "if-scratch" get phantom-d get phantom-push
126 compute-free-vregs ; inline
128 : define-if>boolean-intrinsic ( word quot inputs -- )
130 { { f "if-scratch" } } +scratch+ associate
132 >r [ if>boolean-intrinsic ] curry r>
133 [with-template] "intrinsic" set-word-prop ;
135 : define-if-intrinsic ( word quot inputs -- )
136 3dup define-if>branch-intrinsic define-if>boolean-intrinsic ;
138 : do-if-intrinsic ( node -- next )
139 dup node-successor dup #if? [
140 <label> [ rot if-intrinsic call ] keep
141 generate-if node-successor
143 drop intrinsic call iterate-next
146 M: #call generate-node
148 { [ dup if-intrinsic ] [ do-if-intrinsic ] }
149 { [ dup intrinsic ] [ intrinsic call iterate-next ] }
150 { [ t ] [ node-param generate-call ] }
154 M: #call-label generate-node
155 node-param generate-call ;
158 : dispatch-head ( node -- label/node )
159 #! Return a list of label/branch pairs.
160 node-children [ <label> dup %target 2array ] map ;
162 : dispatch-body ( label/node -- )
164 first2 resolve-label generate-branch
166 ] each resolve-label init-templates ;
168 M: #dispatch generate-node
169 #! The parameter is a list of nodes, each one is a branch to
170 #! take in case the top of stack has that type.
171 %dispatch dispatch-head dispatch-body iterate-next ;
174 UNION: immediate fixnum POSTPONE: f ;
176 : generate-push ( node -- )
178 dup length ?fp-scratch + 0 ensure-vregs
179 [ f spec>vreg [ load-literal ] keep ] map
180 phantom-d get phantom-append ;
182 M: #push generate-node
183 generate-push iterate-next ;
186 : phantom-shuffle-input ( n phantom -- seq )
190 [ phantom-locs ] keep [ length head-slice* ] keep
191 [ append ] keep delete-all
194 : adjust-shuffle ( shuffle -- )
195 effect-in length neg phantom-d get adjust-phantom ;
197 : phantom-shuffle ( shuffle -- )
198 dup effect-in 0 additional-vregs 0 ensure-vregs
200 effect-in length phantom-d get phantom-shuffle-input
202 [ shuffle* ] keep adjust-shuffle
203 phantom-d get phantom-append ;
205 M: #shuffle generate-node
206 node-shuffle phantom-shuffle iterate-next ;
210 1 0 additional-vregs 0 ensure-vregs
211 1 phantom-d get phantom-shuffle-input
212 -1 phantom-d get adjust-phantom
213 phantom-r get phantom-append
218 0 1 additional-vregs 0 ensure-vregs
219 1 phantom-r get phantom-shuffle-input
220 -1 phantom-r get adjust-phantom
221 phantom-d get phantom-append
225 M: #return generate-node drop end-basic-block %return f ;
227 ! These constants must match vm/memory.h
229 : card-mark HEX: 80 ;
231 ! These constants must match vm/layouts.h
232 : float-offset 8 float-tag - ;
233 : string-offset 3 cells object-tag - ;