factor/basis/compiler/cfg/builder/builder.factor

229 lines
5.7 KiB
Factor
Raw Normal View History

! Copyright (C) 2004, 2010 Slava Pestov.
2008-07-20 05:24:37 -04:00
! See http://factorcode.org/license.txt for BSD license.
2008-09-10 23:11:03 -04:00
USING: accessors arrays assocs combinators hashtables kernel
2008-09-17 19:52:11 -04:00
math fry namespaces make sequences words byte-arrays
layouts alien.c-types
2008-10-20 02:56:28 -04:00
stack-checker.inlining cpu.architecture
2008-08-11 03:49:37 -04:00
compiler.tree
2008-09-10 23:11:03 -04:00
compiler.tree.builder
2008-08-11 03:49:37 -04:00
compiler.tree.combinators
compiler.tree.propagation.info
compiler.cfg
compiler.cfg.hats
compiler.cfg.utilities
2008-09-15 02:54:48 -04:00
compiler.cfg.registers
compiler.cfg.intrinsics
compiler.cfg.comparisons
compiler.cfg.stack-frame
2008-10-20 02:56:28 -04:00
compiler.cfg.instructions
compiler.cfg.predecessors
compiler.cfg.builder.blocks
compiler.cfg.stacks
2010-05-11 23:23:41 -04:00
compiler.cfg.stacks.local ;
2008-07-20 05:24:37 -04:00
IN: compiler.cfg.builder
! Convert tree SSA IR to CFG IR. The result is not in SSA form; this is
! constructed later by calling compiler.cfg.ssa.construction:construct-ssa.
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
SYMBOL: procedures
SYMBOL: loops
2008-07-20 05:24:37 -04:00
: begin-cfg ( word label -- cfg )
initial-basic-block
2008-09-10 23:11:03 -04:00
H{ } clone loops set
[ basic-block get ] 2dip <cfg> dup cfg set ;
: begin-procedure ( word label -- )
begin-cfg procedures get push ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: with-cfg-builder ( nodes word label quot -- )
'[
begin-stack-analysis
begin-procedure
@
end-stack-analysis
] 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
'[ _ t t [ _ call( node -- ) ] with-cfg-builder ] with-variable
] { } make drop ;
GENERIC: emit-node ( node -- )
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: emit-nodes ( nodes -- )
[ basic-block get [ emit-node ] [ drop ] if ] each ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: begin-word ( -- )
make-kill-block
##safepoint,
##prologue,
##branch,
begin-basic-block ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: (build-cfg) ( nodes word label -- )
2008-07-20 05:24:37 -04:00
[
2008-09-10 23:11:03 -04:00
begin-word
2008-10-12 17:46:59 -04:00
emit-nodes
2008-09-10 23:11:03 -04:00
] with-cfg-builder ;
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
: emit-loop-call ( basic-block -- )
##safepoint,
##branch,
2008-09-10 23:11:03 -04:00
basic-block get successors>> push
end-basic-block ;
2008-09-10 23:11:03 -04:00
: emit-call ( word height -- )
over loops get key?
[ drop loops get at emit-loop-call ]
[
[
[ ##call, ] [ adjust-d ] bi*
make-kill-block
] emit-trivial-block
] if ;
2008-09-10 23:11:03 -04:00
! #recursive
: recursive-height ( #recursive -- n )
[ label>> return>> in-d>> length ] [ in-d>> length ] bi - ;
2009-06-30 22:07:55 -04:00
: emit-recursive ( #recursive -- )
[ [ label>> id>> ] [ recursive-height ] bi emit-call ]
2008-09-10 23:11:03 -04:00
[ [ child>> ] [ label>> word>> ] [ label>> id>> ] tri (build-cfg) ] bi ;
2008-10-10 03:33:32 -04:00
: remember-loop ( label -- )
basic-block get swap loops get set-at ;
: emit-loop ( node -- )
##branch,
2008-09-10 23:11:03 -04:00
begin-basic-block
[ label>> id>> remember-loop ] [ child>> emit-nodes ] bi ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
M: #recursive emit-node
2009-05-19 18:28:13 -04:00
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
2008-10-20 02:56:28 -04:00
: emit-branch ( obj -- final-bb )
[ emit-nodes ] with-branch ;
2008-07-20 05:24:37 -04:00
2008-10-20 02:56:28 -04:00
: emit-if ( node -- )
children>> [ emit-branch ] map emit-conditional ;
2008-09-17 01:46:38 -04: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 ;
: 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 ;
: emit-actual-if ( #if -- )
! Inputs to the final instruction need to be copied because of
! loc>vreg sync
ds-pop any-rep ^^copy f cc/= ##compare-imm-branch, emit-if ;
2008-09-10 23:11:03 -04:00
M: #if emit-node
{
{ [ dup trivial-if? ] [ drop emit-trivial-if ] }
{ [ dup trivial-not-if? ] [ drop emit-trivial-not-if ] }
[ emit-actual-if ]
} cond ;
2008-09-10 23:11:03 -04:00
! #dispatch
M: #dispatch emit-node
! Inputs to the final instruction need to be copied because of
! loc>vreg sync. ^^offset>slot always returns a fresh vreg,
! though.
ds-pop ^^offset>slot next-vreg ##dispatch, emit-if ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
! #call
M: #call emit-node
2008-10-20 02:56:28 -04:00
dup word>> dup "intrinsic" word-prop
[ emit-intrinsic ] [ swap call-height emit-call ] if ;
2008-09-10 23:11:03 -04:00
! #call-recursive
M: #call-recursive emit-node [ label>> id>> ] [ call-height ] bi emit-call ;
2008-09-10 23:11:03 -04:00
! #push
M: #push emit-node
literal>> ^^load-literal ds-push ;
2008-09-10 23:11:03 -04:00
! #shuffle
! 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 )
! Assoc maps high-level IR values to stack locations.
[
[ in-d>> <reversed> [ <ds-loc> swap set ] each-index ]
[ in-r>> <reversed> [ <rs-loc> swap set ] each-index ] bi
] H{ } make-assoc ;
: make-output-seq ( values mapping input-map -- vregs )
'[ _ at _ at peek-loc ] map ;
: load-shuffle ( #shuffle mapping input-map -- ds-vregs rs-vregs )
[ [ out-d>> ] 2dip make-output-seq ]
[ [ out-r>> ] 2dip make-output-seq ] 3bi ;
: store-shuffle ( #shuffle ds-vregs rs-vregs -- )
[ [ in-d>> length neg inc-d ] dip ds-store ]
[ [ in-r>> length neg inc-r ] dip rs-store ]
bi-curry* bi ;
2008-09-10 23:11:03 -04:00
M: #shuffle emit-node
dup dup [ mapping>> ] [ make-input-map ] bi load-shuffle store-shuffle ;
2008-09-10 23:11:03 -04:00
! #return
2010-07-02 15:44:12 -04:00
: end-word ( -- )
##branch,
begin-basic-block
make-kill-block
##safepoint,
##epilogue,
##return, ;
2010-07-02 15:44:12 -04:00
M: #return emit-node drop end-word ;
2008-09-10 23:11:03 -04:00
M: #return-recursive emit-node
2010-07-02 15:44:12 -04:00
label>> id>> loops get key? [ end-word ] unless ;
2008-09-10 23:11:03 -04:00
! #terminate
M: #terminate emit-node drop ##no-tco, end-basic-block ;
2008-09-10 23:11:03 -04:00
! No-op nodes
M: #introduce emit-node drop ;
2008-07-20 05:24:37 -04:00
M: #copy emit-node drop ;
2008-08-11 03:49:37 -04:00
M: #enter-recursive emit-node drop ;
2008-08-11 03:49:37 -04:00
M: #phi emit-node drop ;
M: #declare emit-node drop ;