2008-10-31 22:07:41 -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-20 02:56:28 -04:00
|
|
|
layouts alien.c-types alien.structs
|
|
|
|
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
|
2008-10-20 21:40:15 -04:00
|
|
|
compiler.cfg.hats
|
|
|
|
compiler.cfg.stacks
|
2008-09-10 23:11:03 -04:00
|
|
|
compiler.cfg.iterator
|
2008-10-22 19:38:30 -04:00
|
|
|
compiler.cfg.utilities
|
2008-09-15 02:54:48 -04:00
|
|
|
compiler.cfg.registers
|
2008-10-20 21:40:15 -04:00
|
|
|
compiler.cfg.intrinsics
|
2008-10-20 02:56:28 -04:00
|
|
|
compiler.cfg.instructions
|
2008-09-15 02:54:48 -04:00
|
|
|
compiler.alien ;
|
2008-07-20 05:24:37 -04:00
|
|
|
IN: compiler.cfg.builder
|
|
|
|
|
2008-10-20 02:56:28 -04:00
|
|
|
! Convert tree SSA IR to CFG SSA IR.
|
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-10-10 03:33:32 -04:00
|
|
|
SYMBOL: first-basic-block
|
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 -- )
|
2008-10-21 04:20:48 -04:00
|
|
|
[ current-node emit-node check-basic-block ] iterate-nodes ;
|
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.
|
2008-09-17 01:46:38 -04:00
|
|
|
##prologue
|
|
|
|
##branch
|
2008-09-10 23:11:03 -04:00
|
|
|
begin-basic-block
|
2008-10-10 03:33:32 -04:00
|
|
|
basic-block get first-basic-block set ;
|
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
|
|
|
V{ } clone node-stack set
|
|
|
|
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
|
|
|
|
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 )
|
|
|
|
{
|
2008-09-11 03:05:22 -04:00
|
|
|
{ [ dup loops get key? ] [ loops get at local-recursive-call ] }
|
2008-11-03 00:09:31 -05:00
|
|
|
{ [ tail-call? not ] [ ##call ##branch begin-basic-block iterate-next ] }
|
2008-10-10 03:33:32 -04:00
|
|
|
{ [ dup current-label get eq? ] [ drop first-basic-block get 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 ;
|
|
|
|
|
2008-10-10 03:33:32 -04:00
|
|
|
: remember-loop ( label -- )
|
|
|
|
basic-block get swap loops get set-at ;
|
|
|
|
|
2008-09-10 23:11:03 -04:00
|
|
|
: compile-loop ( node -- next )
|
2008-11-03 07:20:51 -05:00
|
|
|
##loop-entry
|
2008-09-10 23:11:03 -04:00
|
|
|
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-10-20 02:56:28 -04:00
|
|
|
: emit-branch ( obj -- final-bb )
|
|
|
|
[
|
2008-10-21 04:20:48 -04:00
|
|
|
begin-basic-block
|
2008-10-20 02:56:28 -04:00
|
|
|
emit-nodes
|
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-10-20 02:56:28 -04:00
|
|
|
: emit-if ( node -- )
|
|
|
|
children>> [ 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
|
2008-10-21 04:20:48 -04:00
|
|
|
basic-block get '[ [ _ swap successors>> push ] when* ] each ;
|
2008-09-17 01:46:38 -04:00
|
|
|
|
2008-10-20 02:56:28 -04:00
|
|
|
: ##branch-t ( vreg -- )
|
2008-10-20 06:55:20 -04:00
|
|
|
\ f tag-number cc/= ##compare-imm-branch ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
M: #if emit-node
|
2008-10-21 04:20:48 -04:00
|
|
|
ds-pop ##branch-t emit-if iterate-next ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
! #dispatch
|
|
|
|
: dispatch-branch ( nodes word -- label )
|
|
|
|
gensym [
|
|
|
|
[
|
2008-10-12 17:46:59 -04:00
|
|
|
V{ } clone node-stack set
|
2008-09-17 01:46:38 -04:00
|
|
|
##prologue
|
2008-10-12 17:46:59 -04:00
|
|
|
emit-nodes
|
|
|
|
basic-block get [
|
|
|
|
##epilogue
|
|
|
|
##return
|
|
|
|
end-basic-block
|
|
|
|
] when
|
2008-09-10 23:11:03 -04:00
|
|
|
] 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-10-21 04:20:48 -04:00
|
|
|
##epilogue
|
|
|
|
ds-pop ^^offset>slot i ##dispatch
|
|
|
|
dispatch-branches ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
2008-10-12 18:37:26 -04:00
|
|
|
: <dispatch-block> ( -- word )
|
|
|
|
gensym dup t "inlined-block" set-word-prop ;
|
|
|
|
|
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
|
|
|
] [
|
2008-10-12 18:37:26 -04:00
|
|
|
current-word get <dispatch-block> [
|
2008-09-10 23:11:03 -04:00
|
|
|
[
|
|
|
|
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
|
|
|
|
M: #call emit-node
|
2008-10-20 02:56:28 -04:00
|
|
|
dup word>> dup "intrinsic" word-prop
|
|
|
|
[ emit-intrinsic iterate-next ] [ nip emit-call ] if ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
! #call-recursive
|
|
|
|
M: #call-recursive emit-node label>> id>> emit-call ;
|
|
|
|
|
|
|
|
! #push
|
|
|
|
M: #push emit-node
|
2008-10-21 04:20:48 -04:00
|
|
|
literal>> ^^load-literal ds-push iterate-next ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
! #shuffle
|
2008-10-21 04:20:48 -04:00
|
|
|
: emit-shuffle ( effect -- )
|
|
|
|
[ out>> ] [ in>> dup length ds-load zip ] bi
|
|
|
|
'[ _ at ] map ds-store ;
|
|
|
|
|
2008-09-10 23:11:03 -04:00
|
|
|
M: #shuffle emit-node
|
2008-10-21 04:20:48 -04:00
|
|
|
shuffle-effect emit-shuffle iterate-next ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
M: #>r emit-node
|
|
|
|
[ in-d>> length ] [ out-r>> empty? ] bi
|
2008-10-21 04:20:48 -04:00
|
|
|
[ neg ##inc-d ] [ ds-load rs-store ] if
|
2008-09-10 23:11:03 -04:00
|
|
|
iterate-next ;
|
|
|
|
|
|
|
|
M: #r> emit-node
|
|
|
|
[ in-r>> length ] [ out-d>> empty? ] bi
|
2008-10-21 04:20:48 -04:00
|
|
|
[ neg ##inc-r ] [ rs-load ds-store ] if
|
2008-09-10 23:11:03 -04:00
|
|
|
iterate-next ;
|
|
|
|
|
|
|
|
! #return
|
|
|
|
M: #return emit-node
|
2008-10-21 04:20:48 -04:00
|
|
|
drop ##epilogue ##return stop-iterating ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
M: #return-recursive emit-node
|
|
|
|
label>> id>> loops get key?
|
2008-10-10 03:33:32 -04:00
|
|
|
[ iterate-next ] [ ##epilogue ##return stop-iterating ] if ;
|
2008-09-10 23:11:03 -04:00
|
|
|
|
|
|
|
! #terminate
|
2008-10-21 04:20:48 -04:00
|
|
|
M: #terminate emit-node drop 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 ]
|
2008-10-19 02:10:21 -04:00
|
|
|
[ alien-parameters parameter-sizes drop >>params ] bi ;
|
2008-10-07 17:13:29 -04:00
|
|
|
|
2008-10-13 00:32:14 -04:00
|
|
|
: alien-stack-frame ( params -- )
|
|
|
|
<alien-stack-frame> ##stack-frame ;
|
|
|
|
|
2008-10-07 17:13:29 -04:00
|
|
|
: emit-alien-node ( node quot -- next )
|
2008-10-13 00:32:14 -04:00
|
|
|
[ params>> ] dip [ drop alien-stack-frame ] [ call ] 2bi
|
2008-10-22 19:38:30 -04:00
|
|
|
begin-basic-block iterate-next ; inline
|
2008-10-07 17:13:29 -04:00
|
|
|
|
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
|
2008-10-12 18:37:26 -04:00
|
|
|
dup params>> xt>> dup
|
2008-10-07 17:13:29 -04:00
|
|
|
[
|
2008-10-13 00:32:14 -04:00
|
|
|
##prologue
|
|
|
|
dup [ ##alien-callback ] emit-alien-node drop
|
|
|
|
##epilogue
|
|
|
|
params>> ##callback-return
|
2008-10-07 17:13:29 -04:00
|
|
|
] 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 ;
|