2005-02-22 23:07:47 -05:00
|
|
|
! Copyright (C) 2004, 2005 Slava Pestov.
|
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
2004-12-02 22:44:36 -05:00
|
|
|
IN: compiler
|
2005-02-22 23:07:47 -05:00
|
|
|
USING: inference kernel lists math namespaces words strings
|
|
|
|
errors prettyprint kernel-internals ;
|
2004-12-01 19:48:08 -05:00
|
|
|
|
|
|
|
: >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 ;
|
2004-12-01 19:48:08 -05:00
|
|
|
|
|
|
|
: (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 ;
|
2004-12-10 17:27:07 -05:00
|
|
|
|
2004-12-01 19:48:08 -05:00
|
|
|
: <label> ( -- label )
|
2005-03-05 14:45:23 -05:00
|
|
|
gensym dup t "label" set-word-prop ;
|
2004-12-14 02:57:40 -05:00
|
|
|
|
|
|
|
: label? ( obj -- ? )
|
2005-03-05 14:45:23 -05:00
|
|
|
dup word? [ "label" word-prop ] [ drop f ] ifte ;
|
2004-12-01 19:48:08 -05:00
|
|
|
|
2004-12-11 18:18:43 -05:00
|
|
|
: 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) ;
|
|
|
|
|
2004-12-11 18:18:43 -05:00
|
|
|
#simple-label [
|
|
|
|
linearize-simple-label
|
2005-03-05 14:45:23 -05:00
|
|
|
] "linearizer" set-word-prop
|
2004-12-11 18:18:43 -05:00
|
|
|
|
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
|
2004-12-11 18:18:43 -05:00
|
|
|
linearize-simple-label
|
2005-05-06 18:33:40 -04:00
|
|
|
%return ,
|
|
|
|
r> %label , ;
|
2004-12-05 23:00:52 -05:00
|
|
|
|
2004-12-11 18:18:43 -05:00
|
|
|
#label [
|
|
|
|
linearize-label
|
2005-03-05 14:45:23 -05:00
|
|
|
] "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
|
|
|
|
|
2005-05-08 00:21:00 -04:00
|
|
|
: ifte-head ( label -- )
|
2005-05-06 18:33:40 -04:00
|
|
|
in-1 1 %dec-d , 0 %jump-t , ;
|
|
|
|
|
2004-12-01 19:48:08 -05:00
|
|
|
: linearize-ifte ( param -- )
|
|
|
|
#! The parameter is a list of two lists, each one a dataflow
|
|
|
|
#! IR.
|
2005-01-14 14:56:19 -05:00
|
|
|
2unlist <label> [
|
2005-05-08 00:21:00 -04:00
|
|
|
ifte-head
|
2004-12-01 19:48:08 -05:00
|
|
|
(linearize) ( false branch )
|
2005-05-06 18:33:40 -04:00
|
|
|
<label> dup %jump-label ,
|
|
|
|
] keep %label , ( branch target of BRANCH-T )
|
2004-12-01 19:48:08 -05:00
|
|
|
swap (linearize) ( true branch )
|
2005-05-06 18:33:40 -04:00
|
|
|
%label , ( branch target of false branch end ) ;
|
2004-12-01 19:48:08 -05:00
|
|
|
|
2005-01-14 14:56:19 -05:00
|
|
|
\ ifte [
|
2004-12-05 23:00:52 -05:00
|
|
|
[ node-param get ] bind linearize-ifte
|
2005-03-05 14:45:23 -05:00
|
|
|
] "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.
|
2005-05-06 19:49:07 -04:00
|
|
|
in-1
|
|
|
|
1 %dec-d ,
|
2005-05-08 00:21:00 -04:00
|
|
|
0 %untag-fixnum ,
|
2005-05-06 19:49:07 -04:00
|
|
|
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
|
|
|
|
2005-01-14 14:56:19 -05:00
|
|
|
\ dispatch [
|
2004-12-13 16:28:28 -05:00
|
|
|
[ node-param get ] bind linearize-dispatch
|
2005-03-05 14:45:23 -05:00
|
|
|
] "linearizer" set-word-prop
|
2004-12-08 18:39:36 -05:00
|
|
|
|
2005-03-05 14:45:23 -05:00
|
|
|
#values [ drop ] "linearizer" set-word-prop
|
2005-03-15 18:18:33 -05:00
|
|
|
|
2005-05-06 18:33:40 -04:00
|
|
|
#return [ drop %return , ] "linearizer" set-word-prop
|