132 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Factor
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			132 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Factor
		
	
	
		
			Executable File
		
	
| ! Copyright (C) 2008, 2009 Slava Pestov.
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| USING: kernel math accessors sequences namespaces make
 | |
| combinators assocs arrays locals cpu.architecture
 | |
| compiler.cfg
 | |
| compiler.cfg.rpo
 | |
| compiler.cfg.liveness
 | |
| compiler.cfg.stack-frame
 | |
| compiler.cfg.instructions ;
 | |
| IN: compiler.cfg.linearization
 | |
| 
 | |
| ! Convert CFG IR to machine IR.
 | |
| GENERIC: linearize-insn ( basic-block insn -- )
 | |
| 
 | |
| : linearize-basic-block ( bb -- )
 | |
|     [ number>> _label ]
 | |
|     [ dup instructions>> [ linearize-insn ] with each ]
 | |
|     bi ;
 | |
| 
 | |
| M: insn linearize-insn , drop ;
 | |
| 
 | |
| : useless-branch? ( basic-block successor -- ? )
 | |
|     #! If our successor immediately follows us in RPO, then we
 | |
|     #! don't need to branch.
 | |
|     [ number>> ] bi@ 1 - = ; inline
 | |
| 
 | |
| : branch-to-branch? ( successor -- ? )
 | |
|     #! A branch to a block containing just a jump return is cloned.
 | |
|     instructions>> dup length 2 = [
 | |
|         [ first ##epilogue? ]
 | |
|         [ second [ ##return? ] [ ##jump? ] bi or ] bi and
 | |
|     ] [ drop f ] if ;
 | |
| 
 | |
| : emit-branch ( basic-block successor -- )
 | |
|     {
 | |
|         { [ 2dup useless-branch? ] [ 2drop ] }
 | |
|         { [ dup branch-to-branch? ] [ nip linearize-basic-block ] }
 | |
|         [ nip number>> _branch ]
 | |
|     } cond ;
 | |
| 
 | |
| M: ##branch linearize-insn
 | |
|     drop dup successors>> first emit-branch ;
 | |
| 
 | |
| : (binary-conditional) ( basic-block insn -- basic-block successor1 successor2 src1 src2 cc )
 | |
|     [ dup successors>> first2 ]
 | |
|     [ [ src1>> ] [ src2>> ] [ cc>> ] tri ] bi* ; inline
 | |
| 
 | |
| : binary-conditional ( basic-block insn -- basic-block successor label2 src1 src2 cc )
 | |
|     [ (binary-conditional) ]
 | |
|     [ drop dup successors>> second useless-branch? ] 2bi
 | |
|     [ [ swap number>> ] 3dip ] [ [ number>> ] 3dip negate-cc ] if ;
 | |
| 
 | |
| : with-regs ( insn quot -- )
 | |
|     over regs>> [ call ] dip building get last (>>regs) ; inline
 | |
| 
 | |
| M: ##compare-branch linearize-insn
 | |
|     [ binary-conditional _compare-branch ] with-regs emit-branch ;
 | |
| 
 | |
| M: ##compare-imm-branch linearize-insn
 | |
|     [ binary-conditional _compare-imm-branch ] with-regs emit-branch ;
 | |
| 
 | |
| M: ##compare-float-branch linearize-insn
 | |
|     [ binary-conditional _compare-float-branch ] with-regs emit-branch ;
 | |
| 
 | |
| M: ##dispatch linearize-insn
 | |
|     swap
 | |
|     [ [ [ src>> ] [ temp>> ] bi _dispatch ] with-regs ]
 | |
|     [ successors>> [ number>> _dispatch-label ] each ]
 | |
|     bi* ;
 | |
| 
 | |
| : gc-root-registers ( n live-registers -- n )
 | |
|     [
 | |
|         [ second 2array , ]
 | |
|         [ first reg-class>> reg-size + ]
 | |
|         2bi
 | |
|     ] each ;
 | |
| 
 | |
| : gc-root-spill-slots ( n live-spill-slots -- n )
 | |
|     [
 | |
|         dup first reg-class>> int-regs eq? [
 | |
|             [ second <spill-slot> 2array , ]
 | |
|             [ first reg-class>> reg-size + ]
 | |
|             2bi
 | |
|         ] [ drop ] if
 | |
|     ] each ;
 | |
| 
 | |
| : oop-registers ( regs -- regs' )
 | |
|     [ first reg-class>> int-regs eq? ] filter ;
 | |
| 
 | |
| : data-registers ( regs -- regs' )
 | |
|     [ first reg-class>> double-float-regs eq? ] filter ;
 | |
| 
 | |
| :: compute-gc-roots ( live-registers live-spill-slots -- alist )
 | |
|     [
 | |
|         0
 | |
|         ! we put float registers last; the GC doesn't actually scan them
 | |
|         live-registers oop-registers gc-root-registers
 | |
|         live-spill-slots gc-root-spill-slots
 | |
|         live-registers data-registers gc-root-registers
 | |
|         drop
 | |
|     ] { } make ;
 | |
| 
 | |
| : count-gc-roots ( live-registers live-spill-slots -- n )
 | |
|     ! Size of GC root area, minus the float registers
 | |
|     [ oop-registers length ] bi@ + ;
 | |
| 
 | |
| M: ##gc linearize-insn
 | |
|     nip
 | |
|     [
 | |
|         [ temp1>> ]
 | |
|         [ temp2>> ]
 | |
|         [
 | |
|             [ live-registers>> ] [ live-spill-slots>> ] bi
 | |
|             [ compute-gc-roots ]
 | |
|             [ count-gc-roots ]
 | |
|             [ gc-roots-size ]
 | |
|             2tri
 | |
|         ] tri
 | |
|         _gc
 | |
|     ] with-regs ;
 | |
| 
 | |
| : linearize-basic-blocks ( cfg -- insns )
 | |
|     [
 | |
|         [ [ linearize-basic-block ] each-basic-block ]
 | |
|         [ spill-counts>> _spill-counts ]
 | |
|         bi
 | |
|     ] { } make ;
 | |
| 
 | |
| : flatten-cfg ( cfg -- mr )
 | |
|     [ linearize-basic-blocks ] [ word>> ] [ label>> ] tri
 | |
|     <mr> ;
 |