factor/library/compiler/generator/generator.factor

236 lines
6.2 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
2006-08-10 01:05:12 -04:00
kernel kernel-internals math namespaces sequences words ;
2005-05-09 02:34:15 -04:00
2006-08-15 04:57:12 -04:00
GENERIC: stack-reserve* ( node -- n )
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? ;
2006-08-06 20:31:15 -04:00
PREDICATE: #values #terminal-values node-successor #terminal? ;
2006-04-28 18:38:48 -04:00
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
2006-08-06 20:31:15 -04:00
POSTPONE: f #return #terminal-values #terminal-merge ;
2006-04-28 18:38:48 -04:00
: tail-call? ( -- ? )
node-stack get [
dup #terminal-call? swap node-successor #terminal? or
] all? ;
2006-08-15 16:29:35 -04:00
: generate-code ( node quot -- )
over stack-reserve %prologue call ; inline
: init-generator ( -- )
2006-04-28 18:38:48 -04:00
V{ } clone relocation-table set
V{ } clone literal-table set
2006-09-02 01:58:23 -04:00
V{ } clone label-table set
V{ } clone word-table set ;
2006-04-28 18:38:48 -04:00
2006-08-15 16:29:35 -04:00
: generate-1 ( word node quot -- )
2006-08-10 00:14:43 -04:00
#! Generate the code, then dump three vectors to pass to
#! add-compiled-block.
pick f save-xt [
init-generator
init-templates
generate-code
2006-08-10 00:14:43 -04:00
generate-labels
relocation-table get
literal-table get
2006-09-02 01:58:23 -04:00
word-table get
2006-11-08 21:04:46 -05:00
] V{ } make code-format add-compiled-block save-xt ;
2006-04-28 18:38:48 -04:00
GENERIC: generate-node ( node -- )
: generate-nodes ( node -- )
[ node@ generate-node ] iterate-nodes end-basic-block ;
2006-11-08 21:04:46 -05:00
: generate-branch ( node -- )
[ generate-nodes ] keep-templates ;
2006-04-28 18:38:48 -04:00
: generate ( word node -- )
2006-08-10 01:05:12 -04:00
[ [ generate-nodes ] with-node-iterator ] generate-1 ;
2006-04-28 18:38:48 -04:00
! node
M: node generate-node drop iterate-next ;
2006-04-28 18:38:48 -04:00
! #label
: generate-call ( label -- next )
end-basic-block
tail-call? [ %jump f ] [ %call iterate-next ] if ;
M: #label generate-node
2006-04-28 18:38:48 -04:00
dup node-param dup generate-call >r
2006-08-10 01:05:12 -04:00
swap node-child generate r> ;
2006-04-28 18:38:48 -04:00
! #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> [
2006-11-08 21:04:46 -05:00
>r >r node-children first2 generate-branch
r> r> end-false-branch resolve-label
generate-branch
init-templates
] keep resolve-label iterate-next ;
2006-04-28 18:38:48 -04:00
M: #if generate-node
2006-11-08 21:04:46 -05:00
[ <label> dup %jump-t ]
H{ { +input+ { { f "flag" } } } }
with-template
generate-if ;
2006-04-28 18:38:48 -04:00
! #call
: [with-template] ( quot template -- quot )
2006-11-08 21:04:46 -05:00
\ with-template 3array >quotation ;
2006-04-28 18:38:48 -04:00
2006-08-15 16:29:35 -04:00
: define-intrinsic ( word quot template -- )
2006-04-28 18:38:48 -04:00
[with-template] "intrinsic" set-word-prop ;
2006-11-08 21:04:46 -05:00
: define-if>branch-intrinsic ( word quot inputs -- )
+input+ associate
2006-04-28 18:38:48 -04:00
[with-template] "if-intrinsic" set-word-prop ;
2006-11-08 21:04:46 -05:00
: if>boolean-intrinsic ( quot -- )
"true" define-label
"end" define-label
2006-11-08 21:04:46 -05:00
"true" get swap call
f "if-scratch" get load-literal
2006-05-01 23:30:24 -04:00
"end" get %jump-label
2006-11-08 21:04:46 -05:00
"true" resolve-label
t "if-scratch" get load-literal
2006-11-07 00:22:34 -05:00
"end" resolve-label
2006-11-08 21:04:46 -05:00
"if-scratch" get phantom-d get phantom-push
compute-free-vregs ; inline
: define-if>boolean-intrinsic ( word quot inputs -- )
+input+ associate
{ { f "if-scratch" } } +scratch+ associate
hash-union
>r [ if>boolean-intrinsic ] curry r>
[with-template] "intrinsic" set-word-prop ;
: define-if-intrinsic ( word quot inputs -- )
3dup define-if>branch-intrinsic define-if>boolean-intrinsic ;
2006-05-01 23:30:24 -04:00
: do-if-intrinsic ( node -- next )
2006-11-08 21:04:46 -05:00
dup node-successor dup #if? [
<label> [ rot if-intrinsic call ] keep
generate-if node-successor
2006-04-28 18:38:48 -04:00
] [
2006-11-08 21:04:46 -05:00
drop intrinsic call iterate-next
2006-05-01 23:30:24 -04:00
] if ;
M: #call generate-node
2006-05-01 23:30:24 -04:00
{
{ [ 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
2006-04-28 18:38:48 -04:00
node-param generate-call ;
! #dispatch
: dispatch-head ( node -- label/node )
#! Output the jump table insn and return a list of
#! label/branch pairs.
[ end-basic-block %dispatch ] H{
2006-10-28 02:43:33 -04:00
{ +input+ { { f "n" } } }
{ +scratch+ { { f "scratch" } } }
} with-template
node-children [ <label> dup %target 2array ] map ;
2006-04-28 18:38:48 -04:00
: dispatch-body ( label/node -- )
<label> swap [
2006-11-08 21:04:46 -05:00
first2 resolve-label generate-nodes
2006-04-28 18:38:48 -04:00
dup %jump-label
] each resolve-label ;
2006-04-28 18:38:48 -04:00
M: #dispatch generate-node
2006-04-28 18:38:48 -04:00
#! 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-14 16:44:47 -04:00
>#push<
dup length ?fp-scratch + 0 ensure-vregs
[ f spec>vreg [ load-literal ] keep ] map
2006-05-09 21:37:07 -04:00
phantom-d get phantom-append ;
2006-04-28 18:38:48 -04:00
M: #push generate-node
2006-04-28 18:38:48 -04:00
generate-push iterate-next ;
! #shuffle
: phantom-shuffle-input ( n phantom -- seq )
2dup length <= [
cut-phantom
] [
[ phantom-locs ] keep [ length head-slice* ] keep
2006-08-09 16:14:54 -04:00
[ append ] keep delete-all
2006-04-28 18:38:48 -04:00
] if ;
2005-01-17 15:33:12 -05:00
2006-04-28 18:38:48 -04:00
: adjust-shuffle ( shuffle -- )
2006-09-15 20:59:47 -04:00
effect-in length neg phantom-d get adjust-phantom ;
2006-02-13 22:50:26 -05:00
2006-04-28 18:38:48 -04:00
: phantom-shuffle ( shuffle -- )
2006-09-15 20:59:47 -04:00
dup effect-in 0 additional-vregs 0 ensure-vregs
2006-09-15 20:52:13 -04:00
[
2006-09-15 20:59:47 -04:00
effect-in length phantom-d get phantom-shuffle-input
2006-09-15 20:52:13 -04:00
] keep
2006-04-28 18:38:48 -04:00
[ shuffle* ] keep adjust-shuffle
2006-09-15 20:52:13 -04:00
phantom-d get phantom-append ;
2005-12-24 16:08:15 -05:00
M: #shuffle generate-node
2006-04-28 18:38:48 -04:00
node-shuffle phantom-shuffle iterate-next ;
2005-12-24 16:08:15 -05:00
2006-09-15 20:52:13 -04:00
M: #>r generate-node
drop
1 0 additional-vregs 0 ensure-vregs
1 phantom-d get phantom-shuffle-input
-1 phantom-d get adjust-phantom
phantom-r get phantom-append
iterate-next ;
M: #r> generate-node
drop
0 1 additional-vregs 0 ensure-vregs
1 phantom-r get phantom-shuffle-input
-1 phantom-r get adjust-phantom
phantom-d get phantom-append
iterate-next ;
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 vm/memory.h
2005-05-30 00:21:17 -04:00
: card-bits 7 ;
: card-mark HEX: 80 ;
2005-06-07 03:44:34 -04:00
! These constants must match vm/layouts.h
: float-offset 8 float-tag - ;
2006-01-31 21:31:53 -05:00
: string-offset 3 cells object-tag - ;