factor/library/compiler/linearizer.factor

103 lines
3.1 KiB
Factor
Raw Normal View History

! Copyright (C) 2004, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
2005-05-09 02:34:15 -04:00
IN: compiler-frontend
USING: compiler-backend inference kernel lists math namespaces
words strings errors prettyprint kernel-internals ;
: >linear ( node -- )
#! Dataflow OPs have a linearizer word property. This
#! quotation is executed to convert the node into linear
#! form.
2005-05-06 18:33:40 -04:00
"linearizer" [ "No linearizer" throw ] apply-dataflow ;
: (linearize) ( dataflow -- )
[ >linear ] each ;
: linearize ( dataflow -- linear )
#! Transform dataflow IR into linear IR. This strips out
#! stack flow information, flattens conditionals into
#! jumps and labels, and turns dataflow IR nodes into
#! lists where the first element is an operation, and the
#! rest is arguments.
2005-05-06 18:33:40 -04:00
[ %prologue , (linearize) ] make-list ;
: linearize-simple-label ( node -- )
#! Some labels become simple labels after the optimization
#! stage.
2005-05-06 18:33:40 -04:00
dup [ node-label get ] bind %label ,
2004-12-05 23:00:52 -05:00
[ node-param get ] bind (linearize) ;
#simple-label [
linearize-simple-label
] "linearizer" set-word-prop
2004-12-05 23:00:52 -05:00
: linearize-label ( node -- )
#! Labels are tricky, because they might contain non-tail
#! calls. So we push the address of the location right after
2005-05-06 18:33:40 -04:00
#! the #label , then linearize the #label , then add a #return
2004-12-05 23:00:52 -05:00
#! node to the linear IR. The simplifier will take care of
#! this in the common case where the labelled block does
#! not contain non-tail recursive calls to itself.
2005-05-06 18:33:40 -04:00
<label> dup %return-to , >r
linearize-simple-label
2005-05-09 02:34:15 -04:00
f %return ,
2005-05-06 18:33:40 -04:00
r> %label , ;
2004-12-05 23:00:52 -05:00
#label [
linearize-label
] "linearizer" set-word-prop
2004-12-05 23:00:52 -05:00
2005-05-06 18:33:40 -04:00
#call [
[ node-param get ] bind %call ,
] "linearizer" set-word-prop
2005-05-08 00:58:06 -04:00
#call-label [
[ node-param get ] bind %call-label ,
] "linearizer" set-word-prop
: ifte-head ( label -- )
2005-05-06 18:33:40 -04:00
in-1 1 %dec-d , 0 %jump-t , ;
: linearize-ifte ( param -- )
#! The parameter is a list of two lists, each one a dataflow
#! IR.
2unlist <label> [
ifte-head
(linearize) ( false branch )
2005-05-06 18:33:40 -04:00
<label> dup %jump-label ,
] keep %label , ( branch target of BRANCH-T )
swap (linearize) ( true branch )
2005-05-06 18:33:40 -04:00
%label , ( branch target of false branch end ) ;
\ ifte [
2004-12-05 23:00:52 -05:00
[ node-param get ] bind linearize-ifte
] "linearizer" set-word-prop
2004-12-05 23:00:52 -05:00
2004-12-13 16:28:28 -05:00
: dispatch-head ( vtable -- end label/code )
2004-12-05 21:17:09 -05:00
#! Output the jump table insn and return a list of
#! label/branch pairs.
in-1
1 %dec-d ,
0 %untag-fixnum ,
0 %dispatch ,
2004-12-05 21:17:09 -05:00
<label> ( end label ) swap
2005-05-06 18:33:40 -04:00
[ <label> dup %target-label , cons ] map
%end-dispatch , ;
2004-12-05 21:17:09 -05:00
2004-12-13 16:28:28 -05:00
: dispatch-body ( end label/param -- )
2004-12-05 21:17:09 -05:00
#! Output each branch, with a jump to the end label.
2005-05-06 18:33:40 -04:00
[ uncons %label , (linearize) %jump-label , ] each-with ;
2004-12-13 16:28:28 -05:00
: linearize-dispatch ( vtable -- )
2004-12-05 21:17:09 -05:00
#! The parameter is a list of lists, each one is a branch to
#! take in case the top of stack has that type.
2005-05-06 18:33:40 -04:00
dispatch-head dupd dispatch-body %label , ;
2004-12-05 21:17:09 -05:00
\ dispatch [
2004-12-13 16:28:28 -05:00
[ node-param get ] bind linearize-dispatch
] "linearizer" set-word-prop
#values [ drop ] "linearizer" set-word-prop
2005-05-09 02:34:15 -04:00
#return [ drop f %return , ] "linearizer" set-word-prop