2006-04-28 18:38:48 -04:00
|
|
|
! Copyright (C) 2004, 2006 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2006-04-03 02:18:56 -04:00
|
|
|
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-04-28 19:04:04 -04:00
|
|
|
: if-intrinsic ( #call -- quot )
|
|
|
|
dup node-successor #if?
|
|
|
|
[ node-param "if-intrinsic" word-prop ] [ drop f ] if ;
|
|
|
|
|
2006-04-28 18:38:48 -04:00
|
|
|
DEFER: #terminal?
|
|
|
|
|
|
|
|
PREDICATE: #merge #terminal-merge node-successor #terminal? ;
|
|
|
|
|
|
|
|
PREDICATE: #call #terminal-call
|
|
|
|
dup node-successor node-successor #terminal?
|
|
|
|
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
|
2005-12-13 17:33:58 -05:00
|
|
|
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
|
|
|
|
: generate-if ( node label -- next )
|
|
|
|
<label> [
|
|
|
|
>r >r node-children first2 generate-nodes
|
|
|
|
r> r> %jump-label save-xt generate-nodes
|
|
|
|
] keep save-xt iterate-next ;
|
|
|
|
|
|
|
|
M: #if generate-node ( node -- next )
|
|
|
|
[
|
|
|
|
end-basic-block
|
2006-04-29 17:13:02 -04:00
|
|
|
<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 ;
|
|
|
|
|
|
|
|
: intrinsic ( #call -- quot ) node-param "intrinsic" word-prop ;
|
|
|
|
|
|
|
|
: define-if-intrinsic ( word quot template -- | quot: label -- )
|
|
|
|
[with-template] "if-intrinsic" set-word-prop ;
|
|
|
|
|
|
|
|
M: #call generate-node ( node -- next )
|
|
|
|
dup if-intrinsic [
|
|
|
|
>r <label> dup r> call
|
|
|
|
>r node-successor r> generate-if node-successor
|
|
|
|
] [
|
|
|
|
dup intrinsic
|
|
|
|
[ call iterate-next ] [ node-param generate-call ] ?if
|
|
|
|
] if* ;
|
|
|
|
|
|
|
|
! #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.
|
2006-04-29 17:13:02 -04:00
|
|
|
[ 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 -- )
|
|
|
|
>#push< dup length dup ensure-vregs
|
|
|
|
alloc-reg# [ <vreg> ] map
|
|
|
|
[ [ load-literal ] 2each ] keep
|
|
|
|
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 ;
|
2005-05-28 20:52:23 -04:00
|
|
|
|
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# ensure-vregs
|
|
|
|
[ 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
|
|
|
|
2006-01-31 21:31:53 -05:00
|
|
|
: string-offset 3 cells object-tag - ;
|