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
|
2014-12-13 21:44:35 -05:00
|
|
|
compiler.cfg.builder.blocks compiler.cfg.comparisons
|
|
|
|
compiler.cfg.hats compiler.cfg.instructions
|
|
|
|
compiler.cfg.intrinsics compiler.cfg.registers
|
|
|
|
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-03-06 22:42:28 -05:00
|
|
|
M: #push emit-node ( block node -- block' )
|
|
|
|
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 )
|
|
|
|
{ [ 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
|
|
|
|
2015-03-19 13:03:49 -04:00
|
|
|
: extract-outputs ( #shuffle -- seq )
|
|
|
|
[ out-d>> ds-loc 2array ] [ out-r>> rs-loc 2array ] bi 2array ;
|
2009-08-03 08:08:28 -04:00
|
|
|
|
2015-03-19 13:03:49 -04:00
|
|
|
: out-vregs/stack ( #shuffle -- seq )
|
|
|
|
[ make-input-map ] [ mapping>> ] [ extract-outputs ] tri
|
|
|
|
[ first2 [ [ of of peek-loc ] 2with map ] dip 2array ] 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-03-05 02:30:00 -05:00
|
|
|
[ first2 store-vregs ] each ;
|
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 ;
|