| 
									
										
										
										
											2010-01-02 07:03:30 -05:00
										 |  |  | ! Copyright (C) 2004, 2010 Slava Pestov. | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2015-03-19 13:03:49 -04:00
										 |  |  | USING: accessors arrays assocs combinators compiler.cfg | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  | compiler.cfg.builder.blocks compiler.cfg.comparisons compiler.cfg.hats | 
					
						
							|  |  |  | compiler.cfg.instructions compiler.cfg.intrinsics compiler.cfg.registers | 
					
						
							| 
									
										
										
										
											2014-12-13 21:44:35 -05:00
										 |  |  | compiler.cfg.stacks compiler.cfg.stacks.local compiler.tree | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | compiler.cfg.utilities cpu.architecture fry kernel locals make math | 
					
						
							|  |  |  | namespaces sequences words ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | IN: compiler.cfg.builder | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | SYMBOL: procedures | 
					
						
							|  |  |  | SYMBOL: loops | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-23 21:54:38 -04:00
										 |  |  | : begin-cfg ( word label -- cfg )
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  |     H{ } clone loops set
 | 
					
						
							| 
									
										
										
										
											2015-03-24 12:38:42 -04:00
										 |  |  |     <basic-block> dup set-basic-block <cfg> dup cfg set ;
 | 
					
						
							| 
									
										
										
										
											2009-07-23 21:54:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-05 02:30:00 -05:00
										 |  |  | : with-cfg-builder ( nodes word label quot: ( ..a block -- ..b ) -- )
 | 
					
						
							| 
									
										
										
										
											2009-07-23 21:54:38 -04:00
										 |  |  |     '[ | 
					
						
							|  |  |  |         begin-stack-analysis | 
					
						
							| 
									
										
										
										
											2016-03-15 19:09:55 -04:00
										 |  |  |         begin-cfg | 
					
						
							|  |  |  |         [ procedures get push ] | 
					
						
							|  |  |  |         [ entry>> @ ] | 
					
						
							|  |  |  |         [ end-stack-analysis ] tri
 | 
					
						
							| 
									
										
										
										
											2009-07-23 21:54:38 -04:00
										 |  |  |     ] with-scope ; inline
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-24 14:37:28 -05:00
										 |  |  | : with-dummy-cfg-builder ( node quot -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ V{ } clone procedures ] 2dip
 | 
					
						
							| 
									
										
										
										
											2015-11-21 19:06:11 -05:00
										 |  |  |         '[ _ t t [ drop _ call( node -- ) ] with-cfg-builder ] with-variable
 | 
					
						
							| 
									
										
										
										
											2009-11-24 14:37:28 -05:00
										 |  |  |     ] { } make drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | GENERIC: emit-node ( block node -- block' )
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-nodes ( block nodes -- block' )
 | 
					
						
							|  |  |  |     [ over [ emit-node ] [ drop ] if ] each ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : begin-word ( block -- block' )
 | 
					
						
							| 
									
										
										
										
											2016-03-16 07:26:03 -04:00
										 |  |  |     t >>kill-block? | 
					
						
							| 
									
										
										
										
											2015-11-18 18:53:46 -05:00
										 |  |  |     ##safepoint, ##prologue, ##branch, | 
					
						
							| 
									
										
										
										
											2009-06-30 21:13:35 -04:00
										 |  |  |     begin-basic-block ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | : (build-cfg) ( nodes word label -- )
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  |     [ begin-word swap emit-nodes drop ] with-cfg-builder ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-17 01:46:38 -04:00
										 |  |  | : build-cfg ( nodes word -- procedures )
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  |     V{ } clone [ | 
					
						
							|  |  |  |         procedures [ | 
					
						
							| 
									
										
										
										
											2008-09-17 01:46:38 -04:00
										 |  |  |             dup (build-cfg) | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  |         ] with-variable
 | 
					
						
							|  |  |  |     ] keep ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-18 18:53:46 -05:00
										 |  |  | : emit-loop-call ( successor-block current-block -- )
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  |     ##safepoint, ##branch, | 
					
						
							| 
									
										
										
										
											2015-11-18 18:53:46 -05:00
										 |  |  |     [ swap connect-bbs ] [ end-basic-block ] bi ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-call ( block word height -- block' )
 | 
					
						
							|  |  |  |     over loops get at [ | 
					
						
							|  |  |  |         2nip swap emit-loop-call f
 | 
					
						
							|  |  |  |     ] [ emit-trivial-call ] if* ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! #recursive | 
					
						
							| 
									
										
										
										
											2009-07-19 00:08:53 -04:00
										 |  |  | : recursive-height ( #recursive -- n )
 | 
					
						
							|  |  |  |     [ label>> return>> in-d>> length ] [ in-d>> length ] bi - ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-recursive ( block #recursive -- block' )
 | 
					
						
							| 
									
										
										
										
											2016-03-05 02:30:00 -05:00
										 |  |  |     [ [ label>> id>> ] [ recursive-height ] bi emit-call ] keep
 | 
					
						
							|  |  |  |     [ child>> ] [ label>> word>> ] [ label>> id>> ] tri (build-cfg) ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-loop ( block #recursive -- block' )
 | 
					
						
							|  |  |  |     ##branch, [ begin-basic-block ] dip
 | 
					
						
							|  |  |  |     [ label>> id>> loops get set-at ] [ child>> emit-nodes ] 2bi ;
 | 
					
						
							| 
									
										
										
										
											2008-10-10 03:33:32 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #recursive emit-node ( block node -- block' )
 | 
					
						
							|  |  |  |     dup label>> loop?>> [ emit-loop ] [ emit-recursive ] if ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | ! #if | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-branch ( nodes block -- pair/f )
 | 
					
						
							| 
									
										
										
										
											2016-03-07 00:40:27 -05:00
										 |  |  |     [ swap emit-nodes ] with-branch ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-if ( block node -- block' )
 | 
					
						
							|  |  |  |     children>> over '[ _ emit-branch ] map emit-conditional ;
 | 
					
						
							| 
									
										
										
										
											2008-09-17 01:46:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-06 10:09:21 -05:00
										 |  |  | : trivial-branch? ( nodes -- value ? )
 | 
					
						
							|  |  |  |     dup length 1 = [ | 
					
						
							|  |  |  |         first dup #push? [ literal>> t ] [ drop f f ] if
 | 
					
						
							|  |  |  |     ] [ drop f f ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : trivial-if? ( #if -- ? )
 | 
					
						
							|  |  |  |     children>> first2
 | 
					
						
							|  |  |  |     [ trivial-branch? [ t eq? ] when ] | 
					
						
							|  |  |  |     [ trivial-branch? [ f eq? ] when ] bi*
 | 
					
						
							|  |  |  |     and ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : emit-trivial-if ( -- )
 | 
					
						
							| 
									
										
										
										
											2010-04-22 04:21:23 -04:00
										 |  |  |     [ f cc/= ^^compare-imm ] unary-op ;
 | 
					
						
							| 
									
										
										
										
											2008-11-06 10:09:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : trivial-not-if? ( #if -- ? )
 | 
					
						
							|  |  |  |     children>> first2
 | 
					
						
							|  |  |  |     [ trivial-branch? [ f eq? ] when ] | 
					
						
							|  |  |  |     [ trivial-branch? [ t eq? ] when ] bi*
 | 
					
						
							|  |  |  |     and ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : emit-trivial-not-if ( -- )
 | 
					
						
							| 
									
										
										
										
											2010-04-22 04:21:23 -04:00
										 |  |  |     [ f cc= ^^compare-imm ] unary-op ;
 | 
					
						
							| 
									
										
										
										
											2008-11-06 10:09:21 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : emit-actual-if ( block #if -- block' )
 | 
					
						
							| 
									
										
										
										
											2009-07-24 04:37:18 -04:00
										 |  |  |     ! Inputs to the final instruction need to be copied because of | 
					
						
							|  |  |  |     ! loc>vreg sync | 
					
						
							| 
									
										
										
										
											2011-11-11 22:48:38 -05:00
										 |  |  |     ds-pop any-rep ^^copy f cc/= ##compare-imm-branch, emit-if ;
 | 
					
						
							| 
									
										
										
										
											2009-07-24 04:37:18 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #if emit-node ( block node -- block' )
 | 
					
						
							| 
									
										
										
										
											2008-11-06 10:09:21 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  |         { [ dup trivial-if? ] [ drop emit-trivial-if ] } | 
					
						
							|  |  |  |         { [ dup trivial-not-if? ] [ drop emit-trivial-not-if ] } | 
					
						
							| 
									
										
										
										
											2009-07-24 04:37:18 -04:00
										 |  |  |         [ emit-actual-if ] | 
					
						
							| 
									
										
										
										
											2009-06-30 21:13:35 -04:00
										 |  |  |     } cond ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #dispatch emit-node ( block node -- block' )
 | 
					
						
							| 
									
										
										
										
											2009-07-24 04:37:18 -04:00
										 |  |  |     ! Inputs to the final instruction need to be copied because of | 
					
						
							|  |  |  |     ! loc>vreg sync. ^^offset>slot always returns a fresh vreg, | 
					
						
							|  |  |  |     ! though. | 
					
						
							| 
									
										
										
										
											2011-11-11 22:48:38 -05:00
										 |  |  |     ds-pop ^^offset>slot next-vreg ##dispatch, emit-if ;
 | 
					
						
							| 
									
										
										
										
											2008-08-11 03:49:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #call emit-node ( block node -- block' )
 | 
					
						
							|  |  |  |     dup word>> dup "intrinsic" word-prop [ | 
					
						
							| 
									
										
										
										
											2016-03-08 08:38:48 -05:00
										 |  |  |         nip call( block #call -- block' ) | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  |     ] [ swap call-height emit-call ] if* ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #call-recursive emit-node ( block node -- block' )
 | 
					
						
							| 
									
										
										
										
											2015-11-21 19:06:11 -05:00
										 |  |  |     [ label>> id>> ] [ call-height ] bi emit-call ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  | M: #push emit-node ( block node -- block )
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  |     literal>> ^^load-literal ds-push ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! #shuffle | 
					
						
							| 
									
										
										
										
											2009-08-03 08:08:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Even though low level IR has its own dead code elimination pass, | 
					
						
							|  |  |  | ! we try not to introduce useless ##peeks here, since this reduces | 
					
						
							|  |  |  | ! the accuracy of global stack analysis. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : make-input-map ( #shuffle -- assoc )
 | 
					
						
							| 
									
										
										
										
											2015-03-19 13:03:49 -04:00
										 |  |  |     [ in-d>> ds-loc ] [ in-r>> rs-loc ] bi
 | 
					
						
							| 
									
										
										
										
											2015-03-24 10:23:58 -04:00
										 |  |  |     [ over length stack-locs zip ] 2bi@ append ;
 | 
					
						
							| 
									
										
										
										
											2015-03-19 13:03:49 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : height-changes ( #shuffle -- height-changes )
 | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  |     { [ out-d>> ] [ in-d>> ] [ out-r>> ] [ in-r>> ] } cleave 4array
 | 
					
						
							|  |  |  |     [ length ] map first4 [ - ] 2bi@ 2array ;
 | 
					
						
							| 
									
										
										
										
											2009-08-03 08:08:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-19 13:03:49 -04:00
										 |  |  | : store-height-changes ( #shuffle -- )
 | 
					
						
							|  |  |  |     height-changes { ds-loc rs-loc } [ new swap >>n inc-stack ] 2each ;
 | 
					
						
							| 
									
										
										
										
											2009-08-03 08:08:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  | : extract-outputs ( #shuffle -- pair )
 | 
					
						
							|  |  |  |     [ out-d>> ] [ out-r>> ] bi 2array ;
 | 
					
						
							| 
									
										
										
										
											2009-08-03 08:08:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  | : out-vregs/stack ( #shuffle -- pair )
 | 
					
						
							| 
									
										
										
										
											2015-03-19 13:03:49 -04:00
										 |  |  |     [ make-input-map ] [ mapping>> ] [ extract-outputs ] tri
 | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  |     [ [ of of peek-loc ] 2with map ] 2with map ;
 | 
					
						
							| 
									
										
										
										
											2009-08-03 08:08:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-21 17:15:20 -04:00
										 |  |  | M: #shuffle emit-node ( block node -- block )
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  |     [ out-vregs/stack ] keep store-height-changes | 
					
						
							| 
									
										
										
										
											2016-09-04 00:22:54 -04:00
										 |  |  |     first2 [ ds-loc store-vregs ] [ rs-loc store-vregs ] bi* ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! #return | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | : end-word ( block -- block' )
 | 
					
						
							| 
									
										
										
										
											2015-11-21 19:06:11 -05:00
										 |  |  |     ##branch, begin-basic-block | 
					
						
							| 
									
										
										
										
											2016-03-16 07:26:03 -04:00
										 |  |  |     t >>kill-block? | 
					
						
							|  |  |  |     ##safepoint, ##epilogue, ##return, ;
 | 
					
						
							| 
									
										
										
										
											2009-07-22 20:17:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #return emit-node ( block node -- block' )
 | 
					
						
							| 
									
										
										
										
											2016-03-05 02:30:00 -05:00
										 |  |  |     drop end-word ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #return-recursive emit-node ( block node -- block' )
 | 
					
						
							|  |  |  |     label>> id>> loops get key? [ ] [ end-word ] if ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! #terminate | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #terminate emit-node ( block node -- block' )
 | 
					
						
							|  |  |  |     drop ##no-tco, end-basic-block f ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:03 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! No-op nodes | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #introduce emit-node drop ;
 | 
					
						
							| 
									
										
										
										
											2008-07-20 05:24:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #copy emit-node drop ;
 | 
					
						
							| 
									
										
										
										
											2008-08-11 03:49:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #enter-recursive emit-node drop ;
 | 
					
						
							| 
									
										
										
										
											2008-08-11 03:49:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #phi emit-node drop ;
 | 
					
						
							| 
									
										
										
										
											2009-08-09 17:29:21 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-06 22:42:28 -05:00
										 |  |  | M: #declare emit-node drop ;
 |