2006-04-03 01:33:52 -04:00
|
|
|
! Copyright (C) 2006 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2006-04-03 02:18:56 -04:00
|
|
|
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 ;
|
2006-04-03 01:33:52 -04:00
|
|
|
|
2006-04-29 17:13:02 -04:00
|
|
|
! Register allocation
|
2006-04-19 16:19:26 -04:00
|
|
|
|
2006-05-04 18:19:39 -04:00
|
|
|
! Hash mapping reg-classes to mutable vectors
|
2006-05-05 02:00:17 -04:00
|
|
|
: free-vregs ( reg-class -- seq ) \ free-vregs get hash ;
|
2006-04-29 17:13:02 -04:00
|
|
|
|
2006-05-05 02:00:17 -04:00
|
|
|
: alloc-reg ( reg-class -- vreg ) free-vregs pop ;
|
2006-04-29 17:13:02 -04:00
|
|
|
|
2006-05-05 02:00:17 -04:00
|
|
|
: take-reg ( vreg -- ) dup delegate free-vregs delete ;
|
2006-04-29 17:13:02 -04:00
|
|
|
|
2006-05-05 21:41:57 -04:00
|
|
|
: reg-spec>class ( spec -- class )
|
|
|
|
float eq? T{ float-regs f 8 } T{ int-regs } ? ;
|
|
|
|
|
2006-05-09 13:17:03 -04:00
|
|
|
: spec>vreg ( spec -- vreg )
|
|
|
|
dup integer? [
|
|
|
|
<int-vreg> dup take-reg
|
|
|
|
] [
|
|
|
|
reg-spec>class alloc-reg
|
|
|
|
] if ;
|
2006-04-29 17:13:02 -04:00
|
|
|
|
2006-04-09 23:11:19 -04:00
|
|
|
! A data stack location.
|
|
|
|
TUPLE: ds-loc n ;
|
|
|
|
|
|
|
|
! A call stack location.
|
|
|
|
TUPLE: cs-loc n ;
|
|
|
|
|
2006-04-26 03:05:38 -04:00
|
|
|
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 )
|
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
: (loc)
|
|
|
|
#! Utility for methods on <loc>
|
|
|
|
phantom-stack-height - ;
|
2006-04-09 22:23:00 -04:00
|
|
|
|
|
|
|
: (finalize-height) ( stack word -- )
|
2006-04-24 17:52:03 -04:00
|
|
|
#! 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 )
|
2006-04-24 17:52:03 -04:00
|
|
|
#! A sequence of n ds-locs or cs-locs indexing the stack.
|
2006-05-14 23:25:34 -04:00
|
|
|
swap <reversed> [ 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 -- )
|
|
|
|
[ 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
|
|
|
|
2006-04-05 02:43:37 -04:00
|
|
|
SYMBOL: phantom-d
|
|
|
|
SYMBOL: phantom-r
|
|
|
|
|
2006-04-26 03:05:38 -04:00
|
|
|
: 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 ;
|
2006-04-05 02:43:37 -04:00
|
|
|
|
2006-04-19 16:19:26 -04:00
|
|
|
: finalize-heights ( -- )
|
2006-04-26 03:05:38 -04:00
|
|
|
phantoms [ finalize-height ] 2apply ;
|
2006-04-19 16:19:26 -04:00
|
|
|
|
2006-04-22 15:26:32 -04:00
|
|
|
: vreg>stack ( value loc -- )
|
2006-05-09 13:48:55 -04:00
|
|
|
over loc? over not or [ 2drop ] [ %replace ] if ;
|
2006-04-22 15:26:32 -04:00
|
|
|
|
|
|
|
: 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 ;
|
|
|
|
|
2006-05-12 17:07:56 -04:00
|
|
|
: stack>new-vreg ( loc spec -- vreg )
|
|
|
|
spec>vreg [ swap %peek ] keep ;
|
|
|
|
|
2006-04-22 15:26:32 -04:00
|
|
|
: live-locs ( phantom phantom -- hash )
|
|
|
|
[ (live-locs) ] 2apply append prune
|
2006-05-05 21:41:57 -04:00
|
|
|
[ dup f stack>new-vreg ] map>hash ;
|
2006-04-22 15:26:32 -04:00
|
|
|
|
|
|
|
: lazy-store ( value loc -- )
|
|
|
|
over loc? [
|
2006-05-12 17:07:56 -04:00
|
|
|
2dup =
|
|
|
|
[ 2drop ] [ >r \ live-locs get hash r> vreg>stack ] if
|
2006-04-19 16:19:26 -04:00
|
|
|
] [
|
2006-04-22 15:26:32 -04:00
|
|
|
2drop
|
2006-04-19 16:19:26 -04:00
|
|
|
] if ;
|
2006-04-11 02:45:24 -04:00
|
|
|
|
2006-04-22 15:26:32 -04:00
|
|
|
: flush-locs ( phantom phantom -- )
|
2006-04-25 18:25:39 -04:00
|
|
|
2dup live-locs \ live-locs set
|
|
|
|
[ dup phantom-locs* [ lazy-store ] 2each ] 2apply ;
|
2006-04-19 16:19:26 -04:00
|
|
|
|
|
|
|
: 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
|
|
|
|
2006-05-09 13:48:55 -04:00
|
|
|
: end-basic-block ( -- ) finalize-contents finalize-heights ;
|
2006-04-11 02:45:24 -04:00
|
|
|
|
2006-05-09 13:48:55 -04:00
|
|
|
: used-vregs ( -- seq ) phantoms append [ vreg? ] subset ;
|
2006-05-05 02:00:17 -04:00
|
|
|
|
|
|
|
: (compute-free-vregs) ( used class -- vector )
|
|
|
|
dup vregs length reverse [ swap <vreg> ] map-with diff
|
|
|
|
>vector ;
|
2006-04-11 02:45:24 -04:00
|
|
|
|
|
|
|
: compute-free-vregs ( -- )
|
2006-05-05 02:00:17 -04:00
|
|
|
used-vregs
|
|
|
|
{ T{ int-regs } T{ float-regs f 8 } }
|
|
|
|
[ 2dup (compute-free-vregs) ] map>hash \ free-vregs set
|
|
|
|
drop ;
|
2006-04-11 02:45:24 -04:00
|
|
|
|
2006-05-09 13:48:55 -04:00
|
|
|
: additional-vregs ( seq seq -- n )
|
2006-04-23 01:40:49 -04:00
|
|
|
2array phantoms 2array [ [ length ] map ] 2apply v-
|
2006-05-19 21:08:42 -04:00
|
|
|
[ 0 max ] map sum ;
|
2006-04-23 01:40:49 -04:00
|
|
|
|
2006-05-09 13:48:55 -04:00
|
|
|
: free-vregs# ( -- int# float# )
|
2006-05-05 02:00:17 -04:00
|
|
|
T{ int-regs } free-vregs length
|
|
|
|
phantoms [ [ loc? ] subset length ] 2apply + -
|
|
|
|
T{ float-regs f 8 } free-vregs length ;
|
2006-04-23 01:40:49 -04:00
|
|
|
|
2006-05-05 02:00:17 -04:00
|
|
|
: ensure-vregs ( int# float# -- )
|
2006-05-09 13:48:55 -04:00
|
|
|
compute-free-vregs free-vregs# swapd <= >r <= r> and
|
2006-04-23 01:40:49 -04:00
|
|
|
[ finalize-contents compute-free-vregs ] unless ;
|
|
|
|
|
2006-05-09 13:17:03 -04:00
|
|
|
: (lazy-load) ( spec value -- value )
|
|
|
|
{
|
|
|
|
{ [ dup loc? ] [ >r spec>vreg dup r> %peek ] }
|
|
|
|
{ [ dup [ float-regs? ] is? ] [ nip ] }
|
|
|
|
{ [ over float eq? ] [ >r spec>vreg dup r> %move ] }
|
|
|
|
{ [ t ] [ nip ] }
|
|
|
|
} cond ;
|
2006-04-08 03:13:01 -04:00
|
|
|
|
2006-05-09 13:17:03 -04:00
|
|
|
: lazy-load ( values template -- )
|
|
|
|
dup length neg phantom-d get adjust-phantom
|
|
|
|
[ first2 >r swap (lazy-load) r> set ] 2each ;
|
2006-04-08 03:13:01 -04:00
|
|
|
|
2006-05-05 02:00:17 -04:00
|
|
|
: compatible-vreg? ( n vreg -- ? )
|
2006-05-09 11:31:10 -04:00
|
|
|
dup [ int-regs? ] is? [ vreg-n = ] [ 2drop f ] if ;
|
2006-05-05 02:00:17 -04:00
|
|
|
|
2006-04-08 03:13:01 -04:00
|
|
|
: compatible-values? ( value template -- ? )
|
2006-04-19 16:19:26 -04:00
|
|
|
{
|
2006-04-23 15:32:08 -04:00
|
|
|
{ [ over loc? ] [ 2drop t ] }
|
2006-05-09 13:48:55 -04:00
|
|
|
{ [ dup not ] [ drop [ float-regs? ] is? not ] }
|
|
|
|
{ [ dup float eq? ] [ 2drop t ] }
|
2006-05-05 02:00:17 -04:00
|
|
|
{ [ dup integer? ] [ swap compatible-vreg? ] }
|
2006-04-08 03:13:01 -04:00
|
|
|
} cond ;
|
|
|
|
|
2006-04-11 02:45:24 -04:00
|
|
|
: template-match? ( template phantom -- ? )
|
2006-05-14 23:25:34 -04:00
|
|
|
[ <reversed> ] 2apply
|
2006-04-19 16:19:26 -04:00
|
|
|
t [ swap first compatible-values? and ] 2reduce ;
|
2006-04-08 03:13:01 -04:00
|
|
|
|
2006-04-19 16:19:26 -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
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
: match-template ( template -- slow fast )
|
|
|
|
phantom-d get 2dup template-match?
|
|
|
|
[ split-template ] [ drop { } ] if ;
|
2006-04-19 16:19:26 -04:00
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
: fast-input ( template -- )
|
2006-05-09 13:17:03 -04:00
|
|
|
phantom-d get over length swap cut-phantom swap lazy-load ;
|
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 ;
|
|
|
|
|
2006-04-23 15:32:08 -04:00
|
|
|
: phantom-append ( seq stack -- )
|
|
|
|
over length over adjust-phantom swap nappend ;
|
|
|
|
|
|
|
|
: (template-outputs) ( seq stack -- )
|
2006-04-25 18:25:39 -04:00
|
|
|
phantoms swapd phantom-append phantom-append ;
|
2006-04-23 15:32:08 -04:00
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
SYMBOL: +input
|
|
|
|
SYMBOL: +output
|
2006-04-23 15:32:08 -04:00
|
|
|
SYMBOL: +scratch
|
|
|
|
SYMBOL: +clobber
|
|
|
|
|
|
|
|
: fix-spec ( spec -- spec )
|
|
|
|
H{
|
2006-04-24 17:52:03 -04:00
|
|
|
{ +input { } }
|
|
|
|
{ +output { } }
|
2006-04-23 15:32:08 -04:00
|
|
|
{ +scratch { } }
|
|
|
|
{ +clobber { } }
|
|
|
|
} swap hash-union ;
|
2006-04-19 16:19:26 -04:00
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
: output-vregs ( -- seq seq )
|
2006-04-25 18:25:39 -04:00
|
|
|
+output +clobber [ get [ get ] map ] 2apply ;
|
2006-04-23 15:32:08 -04:00
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
: outputs-clash? ( -- ? )
|
|
|
|
output-vregs append phantoms append
|
2006-04-23 15:32:08 -04:00
|
|
|
[ swap member? ] contains-with? ;
|
|
|
|
|
2006-04-24 17:52:03 -04:00
|
|
|
: slow-input ( template -- )
|
2006-05-09 13:17:03 -04:00
|
|
|
#! Are we loading stuff from the stack? Then flush out
|
|
|
|
#! remaining vregs, not slurped in by fast-input.
|
|
|
|
#! Do the outputs clash with vregs on the phantom stacks?
|
|
|
|
#! Then we must flush them first.
|
|
|
|
dup empty? not outputs-clash? or [ finalize-contents ] when
|
|
|
|
[ length phantom-d get phantom-locs ] keep lazy-load ;
|
2006-04-23 15:32:08 -04:00
|
|
|
|
2006-05-05 02:00:17 -04:00
|
|
|
: requested-vregs ( template -- int# float# )
|
|
|
|
dup length swap [ float eq? ] subset length [ - ] keep ;
|
2006-04-25 18:25:39 -04:00
|
|
|
|
2006-05-14 15:44:07 -04:00
|
|
|
: (requests-class?) ( class template -- )
|
|
|
|
[ second reg-spec>class eq? ] contains-with? ;
|
|
|
|
|
|
|
|
: requests-class? ( class -- ? )
|
|
|
|
dup +input get (requests-class?) swap
|
|
|
|
+scratch get (requests-class?) or ;
|
|
|
|
|
|
|
|
: ?fp-scratch ( -- n )
|
2006-05-14 16:44:47 -04:00
|
|
|
T{ float-regs f 8 } requests-class? 1 0 ? ;
|
2006-05-14 15:44:07 -04:00
|
|
|
|
|
|
|
: fp-scratch ( -- vreg )
|
|
|
|
"fp-scratch" get [
|
|
|
|
T{ int-regs } alloc-reg dup "fp-scratch" set
|
|
|
|
] unless* ;
|
|
|
|
|
2006-05-05 02:00:17 -04:00
|
|
|
: guess-vregs ( -- int# float# )
|
2006-05-14 15:44:07 -04:00
|
|
|
+input get { } additional-vregs ?fp-scratch +
|
2006-05-05 20:06:57 -04:00
|
|
|
+scratch get [ first ] map requested-vregs >r + r> ;
|
2006-04-29 17:13:02 -04:00
|
|
|
|
|
|
|
: alloc-scratch ( -- )
|
2006-05-09 13:17:03 -04:00
|
|
|
+scratch get [ first2 >r spec>vreg r> set ] each ;
|
2006-04-29 17:13:02 -04:00
|
|
|
|
2006-04-23 15:32:08 -04:00
|
|
|
: template-inputs ( -- )
|
2006-04-29 17:13:02 -04:00
|
|
|
! 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-05 02:00:17 -04:00
|
|
|
+input get match-template fast-input slow-input
|
|
|
|
! Finally allocate scratch registers
|
|
|
|
alloc-scratch ;
|
2006-04-11 02:45:24 -04:00
|
|
|
|
2006-04-23 15:32:08 -04:00
|
|
|
: template-outputs ( -- )
|
2006-04-24 17:52:03 -04:00
|
|
|
+output get [ get ] map { } (template-outputs) ;
|
2006-04-03 01:33:52 -04:00
|
|
|
|
2006-04-25 18:25:39 -04:00
|
|
|
: with-template ( quot spec -- )
|
|
|
|
fix-spec [ template-inputs call template-outputs ] bind
|
2006-04-24 17:52:03 -04:00
|
|
|
compute-free-vregs ; inline
|
2006-04-28 18:38:48 -04:00
|
|
|
|
|
|
|
: operand ( var -- op ) get v>operand ; inline
|