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

354 lines
9.1 KiB
Factor
Raw Normal View History

2008-09-10 23:11:03 -04:00
! Copyright (C) 2004, 2008 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
2008-10-07 17:13:29 -04:00
locals layouts alien.c-types alien.structs
2008-09-17 19:52:11 -04:00
stack-checker.inlining
2008-10-07 21:00:38 -04:00
cpu.architecture
2008-09-17 19:52:11 -04:00
compiler.intrinsics
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
2008-09-10 23:11:03 -04:00
compiler.cfg.stacks
compiler.cfg.templates
compiler.cfg.iterator
2008-09-15 02:54:48 -04:00
compiler.cfg.instructions
compiler.cfg.registers
compiler.alien ;
2008-07-20 05:24:37 -04:00
IN: compiler.cfg.builder
2008-09-10 23:11:03 -04:00
! Convert tree SSA IR to CFG (not quite SSA yet) IR.
2008-07-20 05:24:37 -04:00
: set-basic-block ( basic-block -- )
[ basic-block set ] [ instructions>> building set ] bi ;
: begin-basic-block ( -- )
2008-09-10 23:11:03 -04:00
<basic-block> basic-block get [
2008-07-20 05:24:37 -04:00
dupd successors>> push
] when*
set-basic-block ;
2008-09-10 23:11:03 -04:00
: end-basic-block ( -- )
building off
basic-block off ;
2008-07-20 05:24:37 -04:00
2008-09-11 03:05:22 -04:00
: stop-iterating ( -- next ) end-basic-block f ;
2008-09-10 23:11:03 -04:00
SYMBOL: procedures
SYMBOL: current-word
SYMBOL: current-label
SYMBOL: loops
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
! Basic block after prologue, makes recursion faster
SYMBOL: current-label-start
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: add-procedure ( -- )
basic-block get current-word get current-label get
2008-09-11 03:05:22 -04:00
<cfg> procedures get push ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
: begin-procedure ( word label -- )
end-basic-block
begin-basic-block
H{ } clone loops set
current-label set
current-word set
add-procedure ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: with-cfg-builder ( nodes word label quot -- )
'[ begin-procedure @ ] with-scope ; inline
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
GENERIC: emit-node ( node -- next )
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: check-basic-block ( node -- node' )
basic-block get [ drop f ] unless ; inline
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: emit-nodes ( nodes -- )
[ current-node emit-node check-basic-block ] iterate-nodes
finalize-phantoms ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: remember-loop ( label -- )
basic-block get swap loops get set-at ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: begin-word ( -- )
#! We store the basic block after the prologue as a loop
#! labelled by the current word, so that self-recursive
#! calls can skip an epilogue/prologue.
init-phantoms
2008-09-17 01:46:38 -04:00
##prologue
##branch
2008-09-10 23:11:03 -04:00
begin-basic-block
current-label get remember-loop ;
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
[ emit-nodes ] with-node-iterator
] 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
2008-09-17 01:46:38 -04:00
SYMBOL: +intrinsics+
SYMBOL: +if-intrinsics+
2008-09-10 23:11:03 -04:00
: if-intrinsics ( #call -- quot )
2008-09-17 01:46:38 -04:00
word>> +if-intrinsics+ word-prop ;
2008-09-10 23:11:03 -04:00
2008-09-11 03:05:22 -04:00
: local-recursive-call ( basic-block -- next )
2008-09-17 01:46:38 -04:00
##branch
2008-09-10 23:11:03 -04:00
basic-block get successors>> push
2008-09-11 03:05:22 -04:00
stop-iterating ;
2008-09-10 23:11:03 -04:00
: emit-call ( word -- next )
finalize-phantoms
{
2008-10-07 17:13:29 -04:00
{ [ tail-call? not ] [ ##simple-stack-frame ##call iterate-next ] }
2008-09-11 03:05:22 -04:00
{ [ dup loops get key? ] [ loops get at local-recursive-call ] }
2008-09-17 01:46:38 -04:00
[ ##epilogue ##jump stop-iterating ]
2008-09-10 23:11:03 -04:00
} cond ;
! #recursive
: compile-recursive ( node -- next )
[ label>> id>> emit-call ]
[ [ child>> ] [ label>> word>> ] [ label>> id>> ] tri (build-cfg) ] bi ;
: compile-loop ( node -- next )
finalize-phantoms
begin-basic-block
[ label>> id>> remember-loop ] [ child>> emit-nodes ] bi
iterate-next ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
M: #recursive emit-node
dup label>> loop?>> [ compile-loop ] [ compile-recursive ] if ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
! #if
2008-09-17 01:46:38 -04:00
: emit-branch ( obj quot -- final-bb )
'[
2008-09-10 23:11:03 -04:00
begin-basic-block copy-phantoms
2008-09-17 01:46:38 -04:00
@
basic-block get dup [ ##branch ] when
2008-09-10 23:11:03 -04:00
] with-scope ;
2008-07-20 05:24:37 -04:00
2008-09-17 01:46:38 -04:00
: emit-branches ( seq quot -- )
'[ _ emit-branch ] map
2008-08-11 03:49:37 -04:00
end-basic-block
2008-09-10 23:11:03 -04:00
begin-basic-block
basic-block get '[ [ _ swap successors>> push ] when* ] each
2008-09-17 01:46:38 -04:00
init-phantoms ;
: emit-if ( node -- next )
children>> [ emit-nodes ] emit-branches ;
2008-09-10 23:11:03 -04:00
M: #if emit-node
2008-09-17 19:52:11 -04:00
phantom-pop ##branch-t emit-if iterate-next ;
2008-09-10 23:11:03 -04:00
! #dispatch
: dispatch-branch ( nodes word -- label )
2008-09-17 01:46:38 -04:00
#! The order here is important, dispatch-branches must
#! run after ##dispatch, so that each branch gets the
#! correct register state
2008-09-10 23:11:03 -04:00
gensym [
[
2008-10-07 21:00:38 -04:00
init-phantoms
2008-09-17 01:46:38 -04:00
##prologue
2008-09-10 23:11:03 -04:00
[ emit-nodes ] with-node-iterator
] with-cfg-builder
] keep ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
: dispatch-branches ( node -- )
children>> [
current-word get dispatch-branch
2008-09-17 01:46:38 -04:00
##dispatch-label
2008-09-10 23:11:03 -04:00
] each ;
: emit-dispatch ( node -- )
2008-09-17 19:52:11 -04:00
phantom-pop int-regs next-vreg
2008-10-07 21:00:38 -04:00
[ finalize-phantoms ##epilogue ] 2dip ##dispatch
2008-09-17 19:52:11 -04:00
dispatch-branches init-phantoms ;
2008-09-10 23:11:03 -04:00
M: #dispatch emit-node
tail-call? [
2008-10-07 21:00:38 -04:00
emit-dispatch stop-iterating
2008-09-10 23:11:03 -04:00
] [
current-word get gensym [
[
begin-word
emit-dispatch
] with-cfg-builder
] keep emit-call
] if ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
! #call
: define-intrinsics ( word intrinsics -- )
2008-09-17 01:46:38 -04:00
+intrinsics+ set-word-prop ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
: define-intrinsic ( word quot assoc -- )
2array 1array define-intrinsics ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
: define-if-intrinsics ( word intrinsics -- )
2008-09-17 01:46:38 -04:00
[ template new swap >>input ] assoc-map
+if-intrinsics+ set-word-prop ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
: define-if-intrinsic ( word quot inputs -- )
2array 1array define-if-intrinsics ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
: find-intrinsic ( #call -- pair/f )
2008-09-17 01:46:38 -04:00
word>> +intrinsics+ word-prop find-template ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: find-boolean-intrinsic ( #call -- pair/f )
2008-09-17 01:46:38 -04:00
word>> +if-intrinsics+ word-prop find-template ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: find-if-intrinsic ( #call -- pair/f )
node@ {
{ [ dup length 2 < ] [ 2drop f ] }
{ [ dup second #if? ] [ drop find-boolean-intrinsic ] }
[ 2drop f ]
} cond ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: do-if-intrinsic ( pair -- next )
2008-09-17 01:46:38 -04:00
[ ##if-intrinsic ] apply-template skip-next emit-if
iterate-next ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
: do-boolean-intrinsic ( pair -- next )
2008-09-17 01:46:38 -04:00
[ ##if-intrinsic ] apply-template
{ t f } [
<constant> phantom-push finalize-phantoms
] emit-branches
iterate-next ;
2008-09-10 23:11:03 -04:00
: do-intrinsic ( pair -- next )
2008-09-17 01:46:38 -04:00
[ ##intrinsic ] apply-template iterate-next ;
2008-09-10 23:11:03 -04:00
2008-09-17 01:46:38 -04:00
: setup-value-classes ( #call -- )
node-input-infos [ class>> ] map set-value-classes ;
2008-09-10 23:11:03 -04:00
2008-09-17 19:52:11 -04:00
{
(tuple) (array) (byte-array)
(complex) (ratio) (wrapper)
(write-barrier)
} [ t "intrinsic" set-word-prop ] each
2008-10-07 17:13:29 -04:00
: allot-size ( -- n )
2008-09-17 19:52:11 -04:00
1 phantom-datastack get phantom-input first value>> ;
:: emit-allot ( size type tag -- )
int-regs next-vreg
dup fresh-object
dup size type tag int-regs next-vreg ##allot
type tagged boa phantom-push ;
: emit-write-barrier ( -- )
phantom-pop dup >vreg fresh-object? [ drop ] [
int-regs next-vreg ##write-barrier
] if ;
: emit-intrinsic ( word -- next )
{
{ \ (tuple) [ allot-size 2 + cells tuple tuple emit-allot ] }
{ \ (array) [ allot-size 2 + cells array object emit-allot ] }
{ \ (byte-array) [ allot-size 2 cells + byte-array object emit-allot ] }
2008-09-17 19:52:11 -04:00
{ \ (complex) [ 3 cells complex complex emit-allot ] }
{ \ (ratio) [ 3 cells ratio ratio emit-allot ] }
{ \ (wrapper) [ 2 cells wrapper object emit-allot ] }
{ \ (write-barrier) [ emit-write-barrier ] }
} case
iterate-next ;
2008-09-10 23:11:03 -04:00
M: #call emit-node
2008-09-17 01:46:38 -04:00
dup setup-value-classes
2008-09-10 23:11:03 -04:00
dup find-if-intrinsic [ do-if-intrinsic ] [
dup find-boolean-intrinsic [ do-boolean-intrinsic ] [
dup find-intrinsic [ do-intrinsic ] [
2008-09-17 19:52:11 -04:00
word>> dup "intrinsic" word-prop
[ emit-intrinsic ] [ emit-call ] if
2008-09-10 23:11:03 -04:00
] ?if
] ?if
] ?if ;
! #call-recursive
M: #call-recursive emit-node label>> id>> emit-call ;
! #push
M: #push emit-node
literal>> <constant> phantom-push iterate-next ;
! #shuffle
M: #shuffle emit-node
shuffle-effect phantom-shuffle iterate-next ;
M: #>r emit-node
[ in-d>> length ] [ out-r>> empty? ] bi
[ phantom-drop ] [ phantom->r ] if
iterate-next ;
M: #r> emit-node
[ in-r>> length ] [ out-d>> empty? ] bi
[ phantom-rdrop ] [ phantom-r> ] if
iterate-next ;
! #return
M: #return emit-node
2008-10-07 21:00:38 -04:00
drop finalize-phantoms ##epilogue ##return stop-iterating ;
2008-09-10 23:11:03 -04:00
M: #return-recursive emit-node
finalize-phantoms
label>> id>> loops get key?
2008-10-07 21:00:38 -04:00
[ ##epilogue ##return ] unless stop-iterating ;
2008-09-10 23:11:03 -04:00
! #terminate
2008-10-08 04:51:44 -04:00
M: #terminate emit-node
drop finalize-phantoms stop-iterating ;
2008-09-10 23:11:03 -04:00
! FFI
2008-10-07 17:13:29 -04:00
: return-size ( ctype -- n )
#! Amount of space we reserve for a return value.
{
{ [ dup c-struct? not ] [ drop 0 ] }
{ [ dup large-struct? not ] [ drop 2 cells ] }
[ heap-size ]
} cond ;
: <alien-stack-frame> ( params -- stack-frame )
stack-frame new
swap
[ return>> return-size >>return ]
[ alien-parameters parameter-sizes drop >>params ] bi
dup [ params>> ] [ return>> ] bi + >>size ;
: alien-stack-frame ( node -- )
params>> <alien-stack-frame> ##stack-frame ;
: emit-alien-node ( node quot -- next )
[ drop alien-stack-frame ]
[ [ params>> ] dip call ] 2bi
iterate-next ; inline
2008-09-10 23:11:03 -04:00
M: #alien-invoke emit-node
2008-10-07 17:13:29 -04:00
[ ##alien-invoke ] emit-alien-node ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
M: #alien-indirect emit-node
2008-10-07 17:13:29 -04:00
[ ##alien-indirect ] emit-alien-node ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
M: #alien-callback emit-node
params>> dup xt>> dup
2008-10-07 17:13:29 -04:00
[
init-phantoms
[ ##alien-callback ] emit-alien-node drop
] with-cfg-builder
2008-09-10 23:11:03 -04:00
iterate-next ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
! No-op nodes
M: #introduce emit-node drop iterate-next ;
2008-07-20 05:24:37 -04:00
2008-09-10 23:11:03 -04:00
M: #copy emit-node drop iterate-next ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
M: #enter-recursive emit-node drop iterate-next ;
2008-08-11 03:49:37 -04:00
2008-09-10 23:11:03 -04:00
M: #phi emit-node drop iterate-next ;