factor/library/compiler/generator/generator.factor

242 lines
6.4 KiB
Factor
Raw Normal View History

2006-04-28 18:38:48 -04:00
! Copyright (C) 2004, 2006 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
IN: compiler
2006-04-28 18:38:48 -04:00
USING: arrays assembler errors generic hashtables inference
kernel kernel-internals lists math namespaces queues sequences
words ;
2005-05-09 02:34:15 -04:00
2006-04-28 18:38:48 -04:00
GENERIC: stack-reserve*
2004-12-25 02:55:03 -05:00
2006-04-28 18:38:48 -04:00
M: object stack-reserve* drop 0 ;
: stack-reserve ( node -- n )
0 swap [ stack-reserve* max ] each-node ;
2006-05-01 23:30:24 -04:00
: intrinsic ( #call -- quot )
node-param "intrinsic" word-prop ;
2006-04-28 19:04:04 -04:00
: if-intrinsic ( #call -- quot )
2006-05-01 23:30:24 -04:00
node-param "if-intrinsic" word-prop ;
2006-04-28 19:04:04 -04:00
2006-04-28 18:38:48 -04:00
DEFER: #terminal?
PREDICATE: #merge #terminal-merge node-successor #terminal? ;
PREDICATE: #call #terminal-call
2006-05-01 23:30:24 -04:00
dup node-successor #if?
over node-successor node-successor #terminal? and
2006-04-28 18:38:48 -04:00
swap if-intrinsic and ;
UNION: #terminal
POSTPONE: f #return #values #terminal-merge ;
: tail-call? ( -- ? )
node-stack get [
dup #terminal-call? swap node-successor #terminal? or
] all? ;
: generate-code ( word node quot -- length | quot: node -- )
2004-12-25 02:55:03 -05:00
compiled-offset >r
compile-aligned
2006-04-28 18:38:48 -04:00
rot save-xt
over stack-reserve %prologue
call
2004-12-25 02:55:03 -05:00
compile-aligned
compiled-offset r> - ;
: generate-reloc ( -- length )
relocation-table get
2005-12-04 02:30:19 -05:00
dup [ assemble-cell ] each
length cells ;
2004-12-25 02:55:03 -05:00
2004-12-25 15:52:08 -05:00
SYMBOL: previous-offset
2006-04-28 18:38:48 -04:00
: begin-generating ( -- code-len-fixup reloc-len-fixup )
compiled-offset previous-offset set
V{ } clone relocation-table set
init-templates begin-assembly swap ;
: generate-1 ( word node quot -- | quot: node -- )
2004-12-25 15:52:08 -05:00
#! If generation fails, reset compiled offset.
[
2006-04-28 18:38:48 -04:00
begin-generating >r >r
generate-code
generate-reloc
r> set-compiled-cell
r> set-compiled-cell
2005-09-21 01:12:16 -04:00
] [
2006-04-28 18:38:48 -04:00
previous-offset get set-compiled-offset rethrow
2005-09-21 01:12:16 -04:00
] recover ;
2004-12-25 15:52:08 -05:00
2006-04-28 18:38:48 -04:00
SYMBOL: generate-queue
: generate-loop ( -- )
generate-queue get dup queue-empty? [
drop
] [
deque first3 generate-1 generate-loop
] if ;
: generate-block ( word node quot -- | quot: node -- )
3array generate-queue get enque ;
2004-12-31 02:17:45 -05:00
2006-04-28 18:38:48 -04:00
GENERIC: generate-node ( node -- )
: generate-nodes ( node -- )
[ node@ generate-node ] iterate-nodes end-basic-block ;
: generate-word ( node -- )
[ [ generate-nodes ] with-node-iterator ]
generate-block ;
: generate ( word node -- )
[
<queue> generate-queue set
generate-word generate-loop
] with-scope ;
! node
M: node generate-node ( node -- next ) drop iterate-next ;
! #label
: generate-call ( label -- next )
end-basic-block
tail-call? [ %jump f ] [ %call iterate-next ] if ;
M: #label generate-node ( node -- next )
#! We remap the IR node's label to a new label object here,
#! to avoid problems with two IR #label nodes having the
#! same label in different lexical scopes.
dup node-param dup generate-call >r
swap node-child generate-word r> ;
! #if
2006-05-01 23:30:24 -04:00
: end-false-branch ( label -- )
tail-call? [ %return drop ] [ %jump-label ] if ;
2006-04-28 18:38:48 -04:00
: generate-if ( node label -- next )
<label> [
>r >r node-children first2 generate-nodes
2006-05-01 23:30:24 -04:00
r> r> end-false-branch save-xt generate-nodes
2006-04-28 18:38:48 -04:00
] keep save-xt iterate-next ;
M: #if generate-node ( node -- next )
[
end-basic-block
<label> dup %jump-t
2006-04-28 18:38:48 -04:00
] H{
{ +input { { 0 "flag" } } }
} with-template generate-if ;
! #call
: [with-template] ( quot template -- quot )
2array >list [ with-template ] append ;
: define-intrinsic ( word quot template -- | quot: -- )
[with-template] "intrinsic" set-word-prop ;
: define-if-intrinsic ( word quot template -- | quot: label -- )
[with-template] "if-intrinsic" set-word-prop ;
2006-05-01 23:30:24 -04:00
: if>boolean-intrinsic ( label -- )
<label> "end" set
2006-05-04 18:08:52 -04:00
f 0 <int-vreg> load-literal
2006-05-01 23:30:24 -04:00
"end" get %jump-label
save-xt
2006-05-04 18:08:52 -04:00
t 0 <int-vreg> load-literal
2006-05-01 23:30:24 -04:00
"end" get save-xt
2006-05-04 18:08:52 -04:00
0 <int-vreg> phantom-d get phantom-push ;
2006-05-01 23:30:24 -04:00
: do-if-intrinsic ( node -- next )
[ <label> dup ] keep if-intrinsic call
>r node-successor dup #if? [
r> generate-if node-successor
2006-04-28 18:38:48 -04:00
] [
2006-05-01 23:30:24 -04:00
drop r> if>boolean-intrinsic iterate-next
] if ;
M: #call generate-node ( node -- next )
{
{ [ dup if-intrinsic ] [ do-if-intrinsic ] }
{ [ dup intrinsic ] [ intrinsic call iterate-next ] }
{ [ t ] [ node-param generate-call ] }
} cond ;
2006-04-28 18:38:48 -04:00
! #call-label
M: #call-label generate-node ( node -- next )
node-param generate-call ;
! #dispatch
: target-label ( label -- ) 0 assemble-cell absolute-cell ;
: dispatch-head ( node -- label/node )
#! Output the jump table insn and return a list of
#! label/branch pairs.
[ end-basic-block %dispatch ] H{
{ +input { { f "n" } } }
{ +scratch { { f "scratch" } } }
} with-template
2006-04-28 18:38:48 -04:00
node-children [ <label> dup target-label 2array ] map ;
: dispatch-body ( label/node -- )
<label> swap [
first2 save-xt generate-nodes end-basic-block
dup %jump-label
] each save-xt ;
M: #dispatch generate-node ( node -- next )
#! The parameter is a list of nodes, each one is a branch to
#! take in case the top of stack has that type.
dispatch-head dispatch-body iterate-next ;
! #push
UNION: immediate fixnum POSTPONE: f ;
: generate-push ( node -- )
2006-05-05 20:06:57 -04:00
>#push< dup literal-template
dup requested-vregs ensure-vregs
alloc-vregs [ [ load-literal ] 2each ] keep
2006-04-28 18:38:48 -04:00
phantom-d get phantom-append ;
M: #push generate-node ( #push -- )
generate-push iterate-next ;
! #shuffle
: phantom-shuffle-input ( n phantom -- seq )
2dup length <= [
cut-phantom
] [
[ phantom-locs ] keep [ length swap head-slice* ] keep
[ append 0 ] keep set-length
] if ;
2005-01-17 15:33:12 -05:00
2006-04-28 18:38:48 -04:00
: phantom-shuffle-inputs ( shuffle -- locs locs )
dup shuffle-in-d length phantom-d get phantom-shuffle-input
swap shuffle-in-r length phantom-r get phantom-shuffle-input ;
2006-04-28 18:38:48 -04:00
: adjust-shuffle ( shuffle -- )
dup shuffle-in-d length neg phantom-d get adjust-phantom
shuffle-in-r length neg phantom-r get adjust-phantom ;
2006-02-13 22:50:26 -05:00
2006-04-28 18:38:48 -04:00
: shuffle-vregs# ( shuffle -- n )
dup shuffle-in-d swap shuffle-in-r additional-vregs# ;
2006-02-13 22:50:26 -05:00
2006-04-28 18:38:48 -04:00
: phantom-shuffle ( shuffle -- )
dup shuffle-vregs# 0 ensure-vregs
2006-04-28 18:38:48 -04:00
[ phantom-shuffle-inputs ] keep
[ shuffle* ] keep adjust-shuffle
(template-outputs) ;
2005-12-24 16:08:15 -05:00
2006-04-28 18:38:48 -04:00
M: #shuffle generate-node ( #shuffle -- )
node-shuffle phantom-shuffle iterate-next ;
2005-12-24 16:08:15 -05:00
2006-04-28 18:38:48 -04:00
! #return
M: #return generate-node drop end-basic-block %return f ;
2005-05-30 00:21:17 -04:00
! These constants must match native/card.h
: card-bits 7 ;
: card-mark HEX: 80 ;
2005-06-07 03:44:34 -04:00
: float-offset 8 float-tag - ;
2006-01-31 21:31:53 -05:00
: string-offset 3 cells object-tag - ;