2004-12-01 19:48:08 -05:00
|
|
|
! :folding=indent:collapseFolds=1:
|
|
|
|
|
|
|
|
! $Id$
|
|
|
|
!
|
|
|
|
! Copyright (C) 2004 Slava Pestov.
|
|
|
|
!
|
|
|
|
! Redistribution and use in source and binary forms, with or without
|
|
|
|
! modification, are permitted provided that the following conditions are met:
|
|
|
|
!
|
|
|
|
! 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
! this list of conditions and the following disclaimer.
|
|
|
|
!
|
|
|
|
! 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
! this list of conditions and the following disclaimer in the documentation
|
|
|
|
! and/or other materials provided with the distribution.
|
|
|
|
!
|
|
|
|
! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
|
|
! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
|
! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
|
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
2004-12-02 22:44:36 -05:00
|
|
|
IN: compiler
|
|
|
|
USE: inference
|
2004-12-10 17:27:07 -05:00
|
|
|
USE: kernel
|
2004-12-10 19:29:07 -05:00
|
|
|
USE: lists
|
|
|
|
USE: math
|
|
|
|
USE: namespaces
|
|
|
|
USE: words
|
2004-12-13 16:28:28 -05:00
|
|
|
USE: strings
|
|
|
|
USE: errors
|
2004-12-01 19:48:08 -05:00
|
|
|
|
2004-12-05 21:17:09 -05:00
|
|
|
! The linear IR is close to assembly language. It also resembles
|
|
|
|
! Forth code in some sense. It exists so that pattern matching
|
|
|
|
! optimization can be performed against it.
|
|
|
|
|
2004-12-01 19:48:08 -05:00
|
|
|
! Linear IR nodes. This is in addition to the symbols already
|
2004-12-05 23:00:52 -05:00
|
|
|
! defined in inference vocab.
|
2004-12-01 19:48:08 -05:00
|
|
|
|
2004-12-10 17:27:07 -05:00
|
|
|
SYMBOL: #push-immediate
|
|
|
|
SYMBOL: #push-indirect
|
2004-12-13 18:40:21 -05:00
|
|
|
SYMBOL: #jump-t ( branch if top of stack is true )
|
2004-12-01 19:48:08 -05:00
|
|
|
SYMBOL: #jump ( tail-call )
|
2004-12-05 23:00:52 -05:00
|
|
|
SYMBOL: #return-to ( push addr on C stack )
|
2004-12-01 19:48:08 -05:00
|
|
|
|
2004-12-13 16:28:28 -05:00
|
|
|
! #dispatch is linearized as #dispatch followed by a #target
|
|
|
|
! for each dispatch table entry. The linearizer ensures the
|
|
|
|
! correct number of #targets is emitted.
|
|
|
|
SYMBOL: #target ( part of jump table )
|
|
|
|
|
2004-12-03 22:12:58 -05:00
|
|
|
: linear, ( node -- )
|
|
|
|
#! Add a node to the linear IR.
|
|
|
|
[ node-op get node-param get ] bind cons , ;
|
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.
|
2004-12-03 22:12:58 -05:00
|
|
|
"linearizer" [ linear, ] 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.
|
2004-12-03 22:12:58 -05:00
|
|
|
[ (linearize) ] make-list ;
|
2004-12-01 19:48:08 -05:00
|
|
|
|
2004-12-10 17:27:07 -05:00
|
|
|
: immediate? ( obj -- ? )
|
|
|
|
#! fixnums and f have a pointerless representation, and
|
|
|
|
#! are compiled immediately. Everything else can be moved
|
|
|
|
#! by GC, and is indexed through a table.
|
|
|
|
dup fixnum? swap f eq? or ;
|
|
|
|
|
|
|
|
#push [
|
|
|
|
[ node-param get ] bind
|
|
|
|
dup immediate? #push-immediate #push-indirect ?
|
|
|
|
swons ,
|
|
|
|
] "linearizer" set-word-property
|
|
|
|
|
2004-12-13 18:40:21 -05:00
|
|
|
#call [
|
|
|
|
dup [ node-param get ] bind postpone-word
|
|
|
|
linear,
|
|
|
|
] "linearizer" set-word-property
|
|
|
|
|
|
|
|
#call-label [
|
|
|
|
[ node-param get ] bind #call swons ,
|
|
|
|
] "linearizer" set-word-property
|
|
|
|
|
2004-12-01 19:48:08 -05:00
|
|
|
: <label> ( -- label )
|
2004-12-13 18:40:21 -05:00
|
|
|
gensym
|
|
|
|
dup t "label" set-word-property ;
|
2004-12-01 19:48:08 -05:00
|
|
|
|
|
|
|
: label, ( label -- )
|
2004-12-03 22:12:58 -05:00
|
|
|
#label swons , ;
|
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.
|
2004-12-05 23:00:52 -05:00
|
|
|
dup [ node-label get ] bind label,
|
|
|
|
[ node-param get ] bind (linearize) ;
|
|
|
|
|
2004-12-11 18:18:43 -05:00
|
|
|
#simple-label [
|
|
|
|
linearize-simple-label
|
|
|
|
] "linearizer" set-word-property
|
|
|
|
|
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
|
|
|
|
#! the label, then linearize the label, then add a #return
|
|
|
|
#! 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.
|
|
|
|
<label> dup #return-to swons , >r
|
2004-12-11 18:18:43 -05:00
|
|
|
linearize-simple-label
|
2004-12-05 23:00:52 -05:00
|
|
|
[ #return ] ,
|
|
|
|
r> label, ;
|
|
|
|
|
2004-12-11 18:18:43 -05:00
|
|
|
#label [
|
|
|
|
linearize-label
|
|
|
|
] "linearizer" set-word-property
|
2004-12-05 23:00:52 -05:00
|
|
|
|
2004-12-01 19:48:08 -05:00
|
|
|
: linearize-ifte ( param -- )
|
|
|
|
#! The parameter is a list of two lists, each one a dataflow
|
|
|
|
#! IR.
|
|
|
|
uncons car
|
|
|
|
<label> [
|
2004-12-13 18:40:21 -05:00
|
|
|
#jump-t swons ,
|
2004-12-01 19:48:08 -05:00
|
|
|
(linearize) ( false branch )
|
2004-12-13 18:40:21 -05:00
|
|
|
<label> dup #jump swons ,
|
2004-12-01 19:48:08 -05:00
|
|
|
] keep label, ( branch target of BRANCH-T )
|
|
|
|
swap (linearize) ( true branch )
|
|
|
|
label, ( branch target of false branch end ) ;
|
|
|
|
|
2004-12-05 23:00:52 -05:00
|
|
|
#ifte [
|
|
|
|
[ node-param get ] bind linearize-ifte
|
|
|
|
] "linearizer" set-word-property
|
|
|
|
|
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.
|
2004-12-13 16:28:28 -05:00
|
|
|
[ #dispatch ] ,
|
2004-12-05 21:17:09 -05:00
|
|
|
<label> ( end label ) swap
|
2004-12-13 16:28:28 -05:00
|
|
|
[ <label> dup #target swons , cons ] map ;
|
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.
|
2004-12-13 18:40:21 -05:00
|
|
|
[ uncons label, (linearize) dup #jump swons , ] each drop ;
|
2004-12-05 21:17:09 -05:00
|
|
|
|
2004-12-13 16:28:28 -05:00
|
|
|
: check-dispatch ( vtable -- )
|
|
|
|
length num-types = [
|
|
|
|
"Dispatch must have " num-types " entries" cat3 throw
|
|
|
|
] unless ;
|
|
|
|
|
|
|
|
: 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.
|
2004-12-13 16:28:28 -05:00
|
|
|
dup check-dispatch dispatch-head dupd dispatch-body label, ;
|
2004-12-05 21:17:09 -05:00
|
|
|
|
2004-12-13 16:28:28 -05:00
|
|
|
#dispatch [
|
|
|
|
[ node-param get ] bind linearize-dispatch
|
2004-12-05 21:17:09 -05:00
|
|
|
] "linearizer" set-word-property
|
2004-12-08 18:39:36 -05:00
|
|
|
|
|
|
|
#values [ drop ] "linearizer" set-word-property
|
2004-12-13 16:28:28 -05:00
|
|
|
|
|
|
|
[
|
|
|
|
[ #drop drop ]
|
|
|
|
[ #dup dup ]
|
|
|
|
[ #swap swap ]
|
|
|
|
[ #over over ]
|
|
|
|
[ #pick pick ]
|
|
|
|
[ #>r >r ]
|
|
|
|
[ #r> r> ]
|
|
|
|
] [
|
|
|
|
uncons
|
|
|
|
[ car #call swons , drop ] cons
|
|
|
|
"linearizer" set-word-property
|
|
|
|
] each
|