1 ! Copyright (C) 2007, 2010 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays bit-arrays byte-arrays byte-vectors generic assocs
4 hashtables io.binary kernel kernel.private math namespaces make
5 sequences words quotations strings sorting alien.accessors
6 alien.strings layouts system combinators math.bitwise math.order
7 combinators.short-circuit combinators.smart accessors growable
8 fry memoize compiler.constants compiler.cfg.instructions
10 IN: compiler.codegen.fixup
13 : push-uint ( value vector -- )
14 [ length ] [ B{ 0 0 0 0 } swap push-all ] [ underlying>> ] tri
15 swap set-alien-unsigned-4 ;
18 SYMBOL: parameter-table
20 : add-parameter ( obj -- ) parameter-table get push ;
25 : add-literal ( obj -- ) literal-table get push ;
32 : <label> ( -- label ) label new ;
33 : define-label ( name -- ) <label> swap set ;
35 : compiled-offset ( -- n ) building get length ;
37 : resolve-label ( label/name -- )
38 dup label? [ get ] unless
39 compiled-offset >>offset drop ;
41 TUPLE: label-fixup { label label } { class integer } { offset integer } ;
43 : label-fixup ( label class -- )
44 compiled-offset \ label-fixup boa label-table get push ;
47 SYMBOL: relocation-table
49 : add-relocation-entry ( type class offset -- )
50 { 0 24 28 } bitfield relocation-table get push-uint ;
52 : rel-fixup ( class type -- )
53 swap compiled-offset add-relocation-entry ;
55 ! Binary literal table
56 SYMBOL: binary-literal-table
58 : add-binary-literal ( obj -- label )
59 <label> [ 2array binary-literal-table get push ] keep ;
61 ! Caching common symbol names reduces image size a bit
62 MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
64 : add-dlsym-parameters ( symbol dll -- )
65 [ cached-string>symbol add-parameter ] [ add-parameter ] bi* ;
67 : rel-dlsym ( name dll class -- )
68 [ add-dlsym-parameters ] dip rt-dlsym rel-fixup ;
70 : rel-dlsym-toc ( name dll class -- )
71 [ add-dlsym-parameters ] dip rt-dlsym-toc rel-fixup ;
73 : rel-word ( word class -- )
74 [ add-literal ] dip rt-entry-point rel-fixup ;
76 : rel-word-pic ( word class -- )
77 [ add-literal ] dip rt-entry-point-pic rel-fixup ;
79 : rel-word-pic-tail ( word class -- )
80 [ add-literal ] dip rt-entry-point-pic-tail rel-fixup ;
82 : rel-literal ( literal class -- )
83 [ add-literal ] dip rt-literal rel-fixup ;
85 : rel-binary-literal ( literal class -- )
86 [ add-binary-literal ] dip label-fixup ;
88 : rel-this ( class -- )
91 : rel-here ( offset class -- )
92 [ add-literal ] dip rt-here rel-fixup ;
94 : rel-vm ( offset class -- )
95 [ add-parameter ] dip rt-vm rel-fixup ;
97 : rel-cards-offset ( class -- )
98 rt-cards-offset rel-fixup ;
100 : rel-decks-offset ( class -- )
101 rt-decks-offset rel-fixup ;
104 : compute-target ( label-fixup -- offset )
105 label>> offset>> [ "Unresolved label" throw ] unless* ;
107 : compute-relative-label ( label-fixup -- label )
108 [ class>> ] [ offset>> ] [ compute-target ] tri 3array ;
110 : compute-absolute-label ( label-fixup -- )
111 [ compute-target neg add-literal ]
112 [ [ rt-here ] dip [ class>> ] [ offset>> ] bi add-relocation-entry ] bi ;
114 : compute-labels ( label-fixups -- labels' )
115 [ class>> rc-absolute? ] partition
116 [ [ compute-absolute-label ] each ]
117 [ [ compute-relative-label ] map concat ]
121 : alignment ( align -- n )
122 [ compiled-offset dup ] dip align swap - ;
124 : (align-code) ( n -- )
127 : align-code ( n -- )
128 alignment (align-code) ;
130 : emit-data ( obj label -- )
131 over length align-code
133 building get push-all ;
135 : emit-binary-literals ( -- )
136 binary-literal-table get [ emit-data ] assoc-each ;
140 ! Every code block either ends with
146 ! bitmap, byte aligned, three subsequences:
147 ! - <scrubbed data stack locations>
148 ! - <scrubbed retain stack locations>
149 ! - <GC root spill slots>
150 ! uint[] <base pointers>
151 ! uint[] <return addresses>
152 ! uint <largest scrubbed data stack location>
153 ! uint <largest scrubbed retain stack location>
154 ! uint <largest GC root spill slot>
155 ! uint <largest derived root spill slot>
156 ! int <number of return addresses>
158 SYMBOLS: return-addresses gc-maps ;
160 : gc-map-needed? ( gc-map -- ? )
161 ! If there are no stack locations to scrub and no GC roots,
162 ! there's no point storing the GC map.
167 [ gc-roots>> empty? ]
168 [ derived-roots>> empty? ]
172 : gc-map-here ( gc-map -- )
175 compiled-offset return-addresses get push
178 : longest ( seqs -- n )
179 [ length ] [ max ] map-reduce ;
181 : emit-scrub ( seqs -- n )
182 ! seqs is a sequence of sequences of 0/1
184 [ '[ [ 0 = ] ?{ } map-as _ f pad-tail % ] each ] keep ;
186 : integers>bits ( seq n -- bit-array )
187 <bit-array> [ '[ [ t ] dip _ set-nth ] each ] keep ;
189 : largest-spill-slot ( seqs -- n )
190 [ [ 0 ] [ supremum 1 + ] if-empty ] [ max ] map-reduce ;
192 : emit-gc-roots ( seqs -- n )
193 ! seqs is a sequence of sequences of integers 0..n-1
194 dup largest-spill-slot
195 [ '[ _ integers>bits % ] each ] keep ;
198 building get push-uint ;
200 : emit-uints ( n -- )
203 : gc-root-offsets ( gc-map -- offsets )
204 gc-roots>> [ gc-root-offset ] map ;
206 : emit-gc-info-bitmaps ( -- scrub-d-count scrub-r-count gc-root-count )
209 [ [ scrub-d>> ] map emit-scrub ]
210 [ [ scrub-r>> ] map emit-scrub ]
211 [ [ gc-root-offsets ] map emit-gc-roots ]
213 ] ?{ } make underlying>> % ;
215 : emit-base-table ( alist longest -- )
216 -1 <array> <enum> swap assoc-union! seq>> emit-uints ;
218 : derived-root-offsets ( gc-map -- offsets )
219 derived-roots>> [ [ gc-root-offset ] bi@ ] assoc-map ;
221 : emit-base-tables ( -- count )
222 gc-maps get [ derived-root-offsets ] map
223 dup [ keys ] map largest-spill-slot
224 [ '[ _ emit-base-table ] each ] keep ;
226 : emit-return-addresses ( -- )
227 return-addresses get emit-uints ;
229 : gc-info ( -- byte-array )
231 return-addresses get empty? [ 0 emit-uint ] [
234 emit-return-addresses
236 return-addresses get length emit-uint
240 : emit-gc-info ( -- )
241 ! We want to place the GC info so that the end is aligned
242 ! on a 16-byte boundary.
244 length compiled-offset +
245 [ data-alignment get align ] keep -
250 V{ } clone parameter-table set
251 V{ } clone literal-table set
252 V{ } clone label-table set
253 BV{ } clone relocation-table set
254 V{ } clone binary-literal-table set
255 V{ } clone return-addresses set
256 V{ } clone gc-maps set ;
258 : check-fixup ( seq -- )
259 length data-alignment get mod 0 assert= ;
261 : with-fixup ( quot -- code )
268 label-table [ compute-labels ] change
269 parameter-table get >array
270 literal-table get >array
271 relocation-table get >byte-array
275 ] output>array ; inline