factor/library/compiler/generator/templates.factor

283 lines
7.1 KiB
Factor
Raw Normal View History

! Copyright (C) 2006 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler
2006-04-22 15:26:32 -04:00
USING: arrays generic hashtables inference io kernel math
2006-04-17 17:17:34 -04:00
namespaces prettyprint sequences vectors words ;
! Register allocation
SYMBOL: free-vregs
: alloc-reg ( -- n )
free-vregs get pop ;
: alloc-reg# ( n -- regs )
free-vregs [ cut ] change ;
: requested-vregs ( template -- n )
0 [ [ 1+ ] unless ] reduce ;
: template-vreg# ( template template -- n )
[ requested-vregs ] 2apply + ;
: alloc-vregs ( template -- template )
[ first [ alloc-reg ] unless* ] map ;
: adjust-free-vregs ( seq -- )
free-vregs [ diff ] change ;
2006-04-09 23:11:19 -04:00
! A data stack location.
TUPLE: ds-loc n ;
! A call stack location.
TUPLE: cs-loc n ;
UNION: loc ds-loc cs-loc ;
2006-04-09 23:11:19 -04:00
TUPLE: phantom-stack height ;
2006-04-09 22:23:00 -04:00
C: phantom-stack ( -- stack )
0 over set-phantom-stack-height
2006-04-09 23:11:19 -04:00
V{ } clone over set-delegate ;
2006-04-09 22:23:00 -04:00
GENERIC: finalize-height ( n stack -- )
GENERIC: <loc> ( n stack -- loc )
: (loc)
#! Utility for methods on <loc>
phantom-stack-height - ;
2006-04-09 22:23:00 -04:00
: (finalize-height) ( stack word -- )
#! We consolidate multiple stack height changes until the
#! last moment, and we emit the final height changing
#! instruction here.
2006-04-09 22:23:00 -04:00
swap [
phantom-stack-height
2006-04-28 18:38:48 -04:00
dup zero? [ 2drop ] [ swap execute ] if
2006-04-09 22:23:00 -04:00
0
] keep set-phantom-stack-height ; inline
TUPLE: phantom-datastack ;
C: phantom-datastack
[ >r <phantom-stack> r> set-delegate ] keep ;
M: phantom-datastack <loc> (loc) <ds-loc> ;
M: phantom-datastack finalize-height
\ %inc-d (finalize-height) ;
TUPLE: phantom-callstack ;
C: phantom-callstack
[ >r <phantom-stack> r> set-delegate ] keep ;
M: phantom-callstack <loc> (loc) <cs-loc> ;
M: phantom-callstack finalize-height
\ %inc-r (finalize-height) ;
: phantom-locs ( n phantom -- locs )
#! A sequence of n ds-locs or cs-locs indexing the stack.
2006-04-09 23:11:19 -04:00
swap reverse-slice [ swap <loc> ] map-with ;
2006-04-09 22:23:00 -04:00
: phantom-locs* ( phantom -- locs )
2006-04-09 23:11:19 -04:00
dup length swap phantom-locs ;
2006-04-09 22:23:00 -04:00
: adjust-phantom ( n phantom -- )
#! Change stack heiht.
2006-04-09 22:23:00 -04:00
[ phantom-stack-height + ] keep set-phantom-stack-height ;
2006-04-11 02:45:24 -04:00
GENERIC: cut-phantom ( n phantom -- seq )
M: phantom-stack cut-phantom ( n phantom -- seq )
[ delegate cut* swap ] keep set-delegate ;
2006-04-09 22:23:00 -04:00
SYMBOL: phantom-d
SYMBOL: phantom-r
: phantoms ( -- phantom phantom ) phantom-d get phantom-r get ;
2006-04-09 22:23:00 -04:00
: init-templates ( -- )
<phantom-datastack> phantom-d set
<phantom-callstack> phantom-r set ;
: finalize-heights ( -- )
phantoms [ finalize-height ] 2apply ;
2006-04-22 15:26:32 -04:00
: stack>vreg ( vreg# loc -- operand )
2006-04-28 18:38:48 -04:00
>r <vreg> dup r> %peek ;
2006-04-22 15:26:32 -04:00
: stack>new-vreg ( loc -- vreg )
alloc-reg swap stack>vreg ;
: vreg>stack ( value loc -- )
over loc? [
2drop
] [
2006-04-28 18:38:48 -04:00
over [ %replace ] [ 2drop ] if
2006-04-22 15:26:32 -04:00
] if ;
: vregs>stack ( phantom -- )
[
dup phantom-locs* [ vreg>stack ] 2each 0
] keep set-length ;
: (live-locs) ( seq -- seq )
dup phantom-locs* [ 2array ] 2map
[ first2 over loc? >r = not r> and ] subset
[ first ] map ;
: live-locs ( phantom phantom -- hash )
[ (live-locs) ] 2apply append prune
[ dup stack>new-vreg ] map>hash ;
: lazy-store ( value loc -- )
over loc? [
2dup = [
2drop
] [
2006-04-22 15:26:32 -04:00
>r \ live-locs get hash r> vreg>stack
] if
] [
2006-04-22 15:26:32 -04:00
2drop
] if ;
2006-04-11 02:45:24 -04:00
2006-04-22 15:26:32 -04:00
: flush-locs ( phantom phantom -- )
2dup live-locs \ live-locs set
[ dup phantom-locs* [ lazy-store ] 2each ] 2apply ;
: finalize-contents ( -- )
2006-04-23 01:40:49 -04:00
phantoms 2dup flush-locs [ vregs>stack ] 2apply ;
2006-04-08 03:13:01 -04:00
: end-basic-block ( -- )
finalize-contents finalize-heights ;
2006-04-11 02:45:24 -04:00
: used-vregs ( -- seq )
2006-04-23 01:40:49 -04:00
phantoms append [ vreg? ] subset [ vreg-n ] map ;
2006-04-11 02:45:24 -04:00
: compute-free-vregs ( -- )
used-vregs vregs length reverse diff
2006-04-11 02:45:24 -04:00
>vector free-vregs set ;
2006-04-23 01:40:49 -04:00
: additional-vregs# ( seq seq -- n )
2array phantoms 2array [ [ length ] map ] 2apply v-
0 [ 0 max + ] reduce ;
: free-vregs* ( -- n )
free-vregs get length
phantoms [ [ loc? ] subset length ] 2apply + - ;
: ensure-vregs ( n -- )
compute-free-vregs free-vregs* <=
[ finalize-contents compute-free-vregs ] unless ;
2006-04-22 15:26:32 -04:00
: lazy-load ( value loc -- value )
over loc?
[ dupd = [ drop f ] [ stack>new-vreg ] if ] [ drop ] if ;
: phantom-vregs ( values template -- )
[ >r f lazy-load r> second set ] 2each ;
2006-04-08 03:13:01 -04:00
2006-04-17 17:17:34 -04:00
: stack>vregs ( phantom template -- values )
2006-04-09 22:23:00 -04:00
[
alloc-vregs dup length rot phantom-locs
2006-04-17 17:17:34 -04:00
[ stack>vreg ] 2map
2006-04-11 02:45:24 -04:00
] 2keep length neg swap adjust-phantom ;
2006-04-08 03:13:01 -04:00
: compatible-values? ( value template -- ? )
{
{ [ over loc? ] [ 2drop t ] }
2006-04-11 02:45:24 -04:00
{ [ dup not ] [ 2drop t ] }
{ [ over not ] [ 2drop f ] }
2006-04-17 17:17:34 -04:00
{ [ dup integer? ] [ swap vreg-n = ] }
2006-04-08 03:13:01 -04:00
} cond ;
2006-04-11 02:45:24 -04:00
: template-match? ( template phantom -- ? )
[ reverse-slice ] 2apply
t [ swap first compatible-values? and ] 2reduce ;
2006-04-08 03:13:01 -04:00
: split-template ( template phantom -- slow fast )
2006-04-20 16:28:08 -04:00
over length over length <=
[ drop { } swap ] [ length swap cut* ] if ;
2006-04-11 02:45:24 -04:00
: match-template ( template -- slow fast )
phantom-d get 2dup template-match?
[ split-template ] [ drop { } ] if ;
: fast-input ( template -- )
phantom-d get
2006-04-11 02:45:24 -04:00
over length neg over adjust-phantom
over length swap cut-phantom
2006-04-11 02:45:24 -04:00
swap phantom-vregs ;
2006-04-09 22:23:00 -04:00
2006-05-01 23:30:24 -04:00
: phantom-push ( obj stack -- )
1 over adjust-phantom push ;
: phantom-append ( seq stack -- )
over length over adjust-phantom swap nappend ;
: (template-outputs) ( seq stack -- )
phantoms swapd phantom-append phantom-append ;
SYMBOL: +input
SYMBOL: +output
SYMBOL: +scratch
SYMBOL: +clobber
: fix-spec ( spec -- spec )
H{
{ +input { } }
{ +output { } }
{ +scratch { } }
{ +clobber { } }
} swap hash-union ;
: output-vregs ( -- seq seq )
+output +clobber [ get [ get ] map ] 2apply ;
: outputs-clash? ( -- ? )
output-vregs append phantoms append
[ swap member? ] contains-with? ;
: slow-input ( template -- )
! Are we loading stuff from the stack? Then flush out
! remaining vregs, not slurped in by fast-input.
dup empty? [ finalize-contents ] unless
! Do the outputs clash with vregs on the phantom stacks?
! Then we must flush them first.
outputs-clash? [ finalize-contents ] when
phantom-d get swap [ stack>vregs ] keep phantom-vregs ;
: input-vregs ( -- seq )
+input +scratch [ get [ second get vreg-n ] map ] 2apply
append ;
: guess-vregs ( -- n )
2006-05-01 23:30:24 -04:00
+input get { } additional-vregs# +scratch get length + ;
: alloc-scratch ( -- )
+scratch get [ alloc-vregs [ <vreg> ] map ] keep
phantom-vregs ;
: template-inputs ( -- )
! Ensure we have enough to hold any new stack elements we
! will read (if any), and scratch.
guess-vregs ensure-vregs
! Split the template into available (fast) parts and those
! that require allocating registers and reading the stack
2006-05-01 23:30:24 -04:00
+input get match-template fast-input
used-vregs adjust-free-vregs
slow-input
alloc-scratch
input-vregs adjust-free-vregs ;
2006-04-11 02:45:24 -04:00
: template-outputs ( -- )
+output get [ get ] map { } (template-outputs) ;
: with-template ( quot spec -- )
fix-spec [ template-inputs call template-outputs ] bind
compute-free-vregs ; inline
2006-04-28 18:38:48 -04:00
: operand ( var -- op ) get v>operand ; inline