compiler.cfg.*: changes to remove basic-block variable

The emit-node generics signature is changed to ( block node -- block' )
so that it always returns the next block to operate on. Signature for a
lot of related words are changed similarily. Now there is only a few
basic-block usages left.
db4
Björn Lindqvist 2016-03-07 04:42:28 +01:00
parent 07adc2ecae
commit f9c6d7cc43
10 changed files with 372 additions and 189 deletions

View File

@ -1,6 +1,6 @@
USING: alien alien.libraries compiler.cfg.builder help.markup
help.syntax literals make multiline sequences stack-checker.alien
strings ;
USING: alien alien.libraries compiler.cfg compiler.cfg.builder
compiler.cfg.instructions compiler.tree help.markup help.syntax
literals make multiline sequences stack-checker.alien strings ;
IN: compiler.cfg.builder.alien
<<
@ -34,12 +34,26 @@ HELP: check-dlsym
{ $values { "symbol" string } { "library" library } }
{ $description "Checks that a symbol with the given name exists in the given library. Throws an error if not." } ;
HELP: emit-callback-body
{ $values { "params" alien-node-params } }
{ $description "Emits the nodes that forms the body of the alien callback." } ;
HELP: emit-callback-return
{ $values { "params" alien-node-params } { "block" basic-block } }
{ $description "Emits a " { $link ##callback-outputs } " instruction for the " { $link #alien-callback } " if needed." } ;
HELP: unbox-parameters
{ $values { "parameters" sequence } { "vregs" sequence } { "reps" sequence } }
{ $description "Unboxes a sequence of parameters to send to an ffi function." } ;
ARTICLE: "compiler.cfg.builder.alien"
"CFG node emitter for alien nodes"
"The " { $vocab-link "compiler.cfg.builder.alien" } " vocab implements " { $link emit-node } " methods for alien nodes." ;
"The " { $vocab-link "compiler.cfg.builder.alien" } " vocab implements " { $link emit-node } " methods for alien nodes."
$nl
"Words for alien callbacks:"
{ $subsections
emit-callback-body
emit-callback-return
} ;
ABOUT: "compiler.cfg.builder.alien"

View File

@ -1,6 +1,9 @@
USING: alien.c-types compiler.cfg.builder.alien compiler.cfg.instructions
compiler.cfg.registers compiler.cfg.stacks.local compiler.test
cpu.architecture kernel make namespaces system tools.test ;
USING: accessors alien alien.c-types compiler.cfg compiler.cfg.builder
compiler.cfg.builder.alien compiler.cfg.instructions
compiler.cfg.registers compiler.test compiler.tree.builder
compiler.tree.optimizer cpu.architecture cpu.x86.assembler
cpu.x86.assembler.operands kernel make namespaces sequences system
tools.test words ;
IN: compiler.cfg.builder.alien.tests
! unboxing ints is only needed on 32bit archs
@ -25,3 +28,37 @@ cpu x86.32?
} ? [
[ { c-string int } unbox-parameters ] V{ } make
] cfg-unit-test
: dummy-assembly ( -- ass )
int { } cdecl [
EAX 33 MOV
] alien-assembly ;
{ t } [
<basic-block> dup basic-block set dup
\ dummy-assembly build-tree optimize-tree first
[ emit-node ] V{ } make drop eq?
] unit-test
: dummy-callback ( -- cb )
void { } cdecl [ ] alien-callback ;
{ 2 t } [
\ dummy-callback build-tree optimize-tree gensym build-cfg
[ length ] [ second frame-pointer?>> ] bi
] unit-test
{
V{
T{ ##load-reference { dst 1 } { obj t } }
T{ ##load-integer { dst 2 } { val 3 } }
T{ ##copy { dst 4 } { src 1 } { rep any-rep } }
T{ ##copy { dst 3 } { src 2 } { rep any-rep } }
T{ ##inc { loc D: 2 } }
T{ ##branch }
}
} [
basic-block get
\ dummy-callback build-tree optimize-tree 3 swap nth child>>
[ emit-callback-body drop ] V{ } make
] cfg-unit-test

View File

@ -1,15 +1,12 @@
! Copyright (C) 2008, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types alien.libraries
alien.strings arrays assocs classes.struct combinators
compiler.cfg compiler.cfg.builder
compiler.cfg.builder.alien.boxing
compiler.cfg.builder.alien.params compiler.cfg.hats
compiler.cfg.instructions compiler.cfg.registers
USING: accessors alien.c-types alien.libraries alien.strings arrays
assocs classes.struct combinators compiler.cfg compiler.cfg.builder
compiler.cfg.builder.alien.boxing compiler.cfg.builder.alien.params
compiler.cfg.hats compiler.cfg.instructions compiler.cfg.registers
compiler.cfg.stacks compiler.cfg.stacks.local compiler.errors
compiler.tree cpu.architecture fry kernel layouts make math
math.parser namespaces sequences sequences.generalizations
strings words ;
compiler.tree cpu.architecture fry kernel layouts make math namespaces
sequences sequences.generalizations words ;
IN: compiler.cfg.builder.alien
: with-param-regs* ( quot -- reg-values stack-values )
@ -84,8 +81,8 @@ IN: compiler.cfg.builder.alien
base-type box-return ds-push
] if-void ;
M: #alien-invoke emit-node ( block node -- )
nip params>>
M: #alien-invoke emit-node ( block node -- block' )
params>>
[
{
[ caller-parameters ]
@ -95,11 +92,10 @@ M: #alien-invoke emit-node ( block node -- )
} cleave
<gc-map> ##alien-invoke,
]
[ caller-return ]
bi ;
[ caller-return ] bi ;
M: #alien-indirect emit-node ( block node -- )
nip params>>
M: #alien-indirect emit-node ( block node -- block' )
params>>
[
[ ds-pop ^^unbox-any-c-ptr ] dip
[ caller-parameters ]
@ -107,11 +103,10 @@ M: #alien-indirect emit-node ( block node -- )
[ caller-stack-frame ] tri
<gc-map> ##alien-indirect,
]
[ caller-return ]
bi ;
[ caller-return ] bi ;
M: #alien-assembly emit-node ( block node -- )
nip params>>
M: #alien-assembly emit-node ( block node -- block' )
params>>
[
{
[ caller-parameters ]
@ -120,8 +115,7 @@ M: #alien-assembly emit-node ( block node -- )
[ quot>> ]
} cleave ##alien-assembly,
]
[ caller-return ]
bi ;
[ caller-return ] bi ;
: callee-parameter ( rep on-stack? odd-register? -- dst )
[ next-vreg dup ] 3dip next-parameter ;
@ -133,8 +127,7 @@ M: #alien-assembly emit-node ( block node -- )
: (callee-parameters) ( params -- vregs reps )
[ flatten-parameter-type ] map
[ [ [ first3 callee-parameter ] map ] map ]
[ [ keys ] map ]
bi ;
[ [ keys ] map ] bi ;
: box-parameters ( vregs reps params -- )
parameters>> [ base-type box-parameter ds-push ] 3each ;
@ -152,30 +145,30 @@ M: #alien-assembly emit-node ( block node -- )
base-type unbox-return store-return
] if-void ;
: emit-callback-body ( block nodes -- block' )
dup last #return? t assert= but-last emit-nodes ;
: emit-callback-inputs ( params -- )
[ callee-parameters ##callback-inputs, ] keep box-parameters ;
: callback-stack-cleanup ( params -- )
[ xt>> ]
[ [ stack-params get ] dip [ return>> ] [ abi>> ] bi stack-cleanup ] bi
"stack-cleanup" set-word-prop ;
: needs-frame-pointer ( -- )
cfg get t >>frame-pointer? drop ;
: emit-callback-return ( block params -- )
swap [ callee-return ##callback-outputs, ] [ drop ] if ;
: emit-callback-body ( nodes -- )
[ last #return? t assert= ] [ but-last emit-nodes ] bi ;
: emit-callback-outputs ( block params -- )
[ emit-callback-return ] keep callback-stack-cleanup ;
: emit-callback-return ( params -- )
basic-block get [ callee-return ##callback-outputs, ] [ drop ] if ;
M: #alien-callback emit-node ( block node -- )
nip dup params>> xt>> dup
M: #alien-callback emit-node ( block node -- block' )
dup params>> xt>> dup
[
needs-frame-pointer begin-word
{
[ params>> callee-parameters ##callback-inputs, ]
[ params>> box-parameters ]
[ child>> emit-callback-body ]
[ params>> emit-callback-return ]
[ params>> callback-stack-cleanup ]
} cleave
basic-block get [ end-word ] when*
t cfg get frame-pointer?<<
begin-word
over params>> emit-callback-inputs
over child>> emit-callback-body
[ swap params>> emit-callback-outputs ] keep
[ end-word drop ] when*
] with-cfg-builder ;

View File

@ -29,9 +29,16 @@ T{ basic-block
>>
HELP: begin-basic-block
{ $values { "block" basic-block } }
{ $values { "block" basic-block } { "block'" basic-block } }
{ $description "Terminates the given block and initializes a new " { $link basic-block } " to begin outputting instructions to. The new block is included in the old blocks " { $slot "successors" } "." } ;
HELP: begin-branch
{ $values
{ "block" "current " { $link basic-block } }
{ "block" basic-block }
}
{ $description "Used to begin emitting a branch." } ;
HELP: call-height
{ $values { "#call" #call } { "n" number } }
{ $description "Calculates how many items a " { $link #call } " will add or remove from the data stack." }
@ -43,6 +50,14 @@ HELP: call-height
}
} ;
HELP: emit-conditional
{ $values
{ "block" basic-block }
{ "branches" "sequence of pairs" }
{ "block'" basic-block }
}
{ $description "Emits a sequence of conditional branches to the current " { $link cfg } ". Each branch is a pair where the first item is the entry basic block and the second the branches " { $link height-state } ". 'block' is the block in which the control flow is branched and \"block'\" the block in which it converges again." } ;
HELP: emit-trivial-block
{ $values { "quot" quotation } }
{ $description "Combinator that emits a new trivial block, constructed by calling the supplied quotation. The quotation should not end the current block -- only add instructions to it." }
@ -63,3 +78,22 @@ HELP: set-basic-block
HELP: with-branch
{ $values { "quot" quotation } { "pair/f" { $maybe "pair" } } }
{ $description "The pair is either " { $link f } " or a two-tuple containing a " { $link basic-block } " and a " { $link height-state } " two-tuple." } ;
ARTICLE: "compiler.cfg.builder.blocks"
"CFG construction utilities"
$nl
"This vocab contains utilities for that helps " { $vocab-link "compiler.cfg.builder" } " to construct CFG:s."
$nl
"Combinators:"
{ $subsections
with-branch
}
"Creating blocks:"
{ $subsections
begin-basic-block
begin-branch
emit-call-block
emit-conditional
} ;
ABOUT: "compiler.cfg.builder.blocks"

View File

@ -7,12 +7,16 @@ IN: compiler.cfg.builder.blocks.tests
! (begin-basic-block)
{ 20 } [
{ } 20 insns>block (begin-basic-block)
basic-block get predecessors>> first number>>
predecessors>> first number>>
] cfg-unit-test
! begin-branch
{ f } [
height-state get <basic-block> begin-branch height-state get eq?
height-state get <basic-block> begin-branch drop height-state get eq?
] cfg-unit-test
{ f } [
<basic-block> dup begin-branch eq?
] cfg-unit-test
! emit-trivial-block
@ -23,6 +27,11 @@ IN: compiler.cfg.builder.blocks.tests
basic-block get successors>> first instructions>>
] cfg-unit-test
! end-basic-block
{ f } [
f end-basic-block basic-block get
] unit-test
! make-kill-block
{ t } [
<basic-block> [ make-kill-block ] keep kill-block?>>

View File

@ -15,16 +15,16 @@ IN: compiler.cfg.builder.blocks
: end-basic-block ( block -- )
[ end-local-analysis ] when* building off basic-block off ;
: (begin-basic-block) ( block -- )
<basic-block> swap [ over connect-bbs ] when* set-basic-block ;
: (begin-basic-block) ( block -- block' )
<basic-block> swap [ over connect-bbs ] when* dup set-basic-block ;
: begin-basic-block ( block -- )
: begin-basic-block ( block -- block' )
dup [ end-local-analysis ] when* (begin-basic-block) ;
: emit-trivial-block ( quot: ( ..a block -- ..b ) -- )
##branch, basic-block get begin-basic-block
basic-block get [ swap call ] keep
##branch, begin-basic-block ; inline
[ swap call ] keep
##branch, begin-basic-block drop ; inline
: make-kill-block ( block -- )
t swap kill-block?<< ;
@ -39,7 +39,7 @@ IN: compiler.cfg.builder.blocks
[ word>> ] [ call-height ] bi
[ emit-call-block ] emit-trivial-block ;
: begin-branch ( block -- )
: begin-branch ( block -- block' )
height-state [ clone-height-state ] change (begin-basic-block) ;
: end-branch ( block -- pair/f )
@ -51,16 +51,16 @@ IN: compiler.cfg.builder.blocks
: with-branch ( quot -- pair/f )
[
basic-block get begin-branch
basic-block get begin-branch drop
call
basic-block get end-branch
] with-scope ; inline
: emit-conditional ( branches block -- )
! branches is a sequence of pairs as above
end-basic-block
sift [
: emit-conditional ( block branches -- block' )
swap end-basic-block
sift [ f ] [
dup first second height-state set
basic-block get begin-basic-block
[ first ] map basic-block get connect-Nto1-bbs
] unless-empty ;
[ first ] map
f begin-basic-block
[ connect-Nto1-bbs ] keep
] if-empty ;

View File

@ -1,6 +1,7 @@
USING: assocs compiler.cfg compiler.cfg.builder.blocks
compiler.cfg.stacks.local compiler.tree help.markup help.syntax kernel
literals math multiline quotations sequences vectors words ;
compiler.cfg.instructions compiler.cfg.stacks.local compiler.tree
help.markup help.syntax kernel literals math multiline quotations
sequences vectors words ;
IN: compiler.cfg.builder
<<
@ -49,7 +50,8 @@ HELP: build-cfg
{ $description "Builds one or more cfgs from the given word." } ;
HELP: procedures
{ $var-description "A " { $link vector } " used as temporary storage during cfg construction for all procedures being built." } ;
{ $var-description "A " { $link vector } " used as temporary storage during cfg construction for all procedures being built." }
{ $see-also build-cfg } ;
HELP: make-input-map
{ $values { "#shuffle" #shuffle } { "assoc" assoc } }
@ -57,8 +59,17 @@ HELP: make-input-map
{ $examples { $unchecked-example $[ ex-make-input-map ] } } ;
HELP: emit-call
{ $values { "block" basic-block } { "word" word } { "height" number } }
{ $description "Emits a call to the given word to the " { $link cfg } " being constructed. \"height\" is the number of items being added to or removed from the data stack. Side effects of the word is that it modifies the \"basic-block\" and " { $link height-state } " variables." }
{ $values
{ "block" basic-block }
{ "word" word }
{ "height" number }
{ "block'" basic-block }
}
{ $description
"Emits a call to the given word to the " { $link cfg } " being constructed. \"height\" is the number of items being added to or removed from the data stack."
$nl
"Side effects of the word is that it modifies the \"basic-block\" and " { $link height-state } " variables."
}
{ $examples
"In this example, a call to a dummy word is emitted which pushes three items onto the stack."
{ $unchecked-example $[ ex-emit-call ] }
@ -70,8 +81,31 @@ HELP: emit-loop-call
{ $description "Sets the given block as the successor of the current block. Then ends the block." } ;
HELP: emit-node
{ $values { "block" basic-block } { "node" node } }
{ $description "Emits CFG instructions for the given SSA node." } ;
{ $values { "block" basic-block } { "node" node } { "block'" basic-block } }
{ $description "Emits CFG instructions for the given SSA node. The word can add one or more basic blocks to the " { $link cfg } ". The next block to operate on is pushed onto the stack. "
$nl
"The following classes emit-node methods does not change the current block:"
{ $list
{ $link #alien-assembly }
{ $link #alien-callback }
{ $link #alien-indirect }
}
} ;
HELP: emit-nodes
{ $values
{ "block" "current " { $link basic-block } }
{ "nodes" sequence }
{ "block'" basic-block }
}
{ $description "Emits all tree nodes to the cfg. The next block to operate on is pushed onto the stack." } ;
HELP: end-word
{ $values
{ "block" "current " { $link basic-block } }
{ "block'" basic-block }
}
{ $description "Ends the word by adding a basic block containing a " { $link ##return } " instructions to the " { $link cfg } "." } ;
HELP: trivial-branch?
{ $values
@ -94,6 +128,41 @@ HELP: with-cfg-builder
ARTICLE: "compiler.cfg.builder"
"Final stage of compilation generates machine code from dataflow IR"
"Convert tree SSA IR to CFG IR. The result is not in SSA form; this is constructed later by calling compiler.cfg.ssa.construction:construct-ssa." ;
$nl
"The compiler first builds an SSA IR tree of the word to be compiled (see " { $vocab-link "compiler.tree.builder" } ") then this vocab converts it to a CFG IR tree. The result is not in SSA form; this is constructed later by calling compiler.cfg.ssa.construction:construct-ssa."
$nl
"Main word:"
{ $subsections
build-cfg
}
"Block adders:"
{ $subsections
begin-word
end-word
}
"Combinators:"
{ $subsections
with-cfg-builder
}
"Emitters for " { $link #call } ":"
{ $subsections
emit-call
emit-loop-call
emit-trivial-call
}
"Emitters for " { $link #dispatch } " and " { $link #if } ":"
{ $subsections
emit-actual-if
emit-branch
emit-if
emit-trivial-if
}
"Emitters for " { $link #recursive } ":"
{
$subsections
emit-loop
emit-recursive
end-branch
} ;
ABOUT: "compiler.cfg.builder"

View File

@ -1,10 +1,11 @@
USING: accessors alien alien.accessors arrays assocs byte-arrays
combinators.short-circuit compiler.cfg compiler.cfg.builder
compiler.cfg.checker compiler.cfg.debugger compiler.cfg.instructions
compiler.cfg.optimizer compiler.cfg.registers
compiler.cfg.stacks.local compiler.cfg.utilities compiler.test
compiler.tree compiler.tree.propagation.info cpu.architecture fry
hashtables io kernel kernel.private locals make math math.intervals
compiler.cfg.builder.blocks compiler.cfg.checker compiler.cfg.debugger
compiler.cfg.instructions compiler.cfg.optimizer
compiler.cfg.registers compiler.cfg.stacks.local
compiler.cfg.utilities compiler.test compiler.tree
compiler.tree.propagation.info cpu.architecture fry hashtables io
kernel kernel.private locals make math math.intervals
math.partial-dispatch math.private namespaces prettyprint sbufs
sequences sequences.private slots.private strings strings.private
tools.test vectors words ;
@ -236,6 +237,13 @@ IN: compiler.cfg.builder.tests
[ ##compare-integer-imm-branch? ] contains-insn?
] unit-test
! begin-cfg
SYMBOL: foo
{ foo } [
\ foo f begin-cfg word>>
] cfg-unit-test
! make-input-map
{
{ { 37 D: 2 } { 81 D: 1 } { 92 D: 0 } }
@ -243,36 +251,42 @@ IN: compiler.cfg.builder.tests
T{ #shuffle { in-d { 37 81 92 } } } make-input-map
] unit-test
! emit-branch
{ 77 } [
{ T{ #call { word + } } }
V{ } 77 insns>block dup basic-block set
emit-branch
first predecessors>>
first predecessors>>
first predecessors>>
first number>>
] cfg-unit-test
! emit-call
{
V{ T{ ##call { word print } } T{ ##branch } }
} [
[ f \ print 4 emit-call ] V{ } make drop
basic-block get successors>> first instructions>>
<basic-block> dup set-basic-block \ print 4 emit-call
predecessors>> first instructions>>
] cfg-unit-test
! emit-loop-call
{ 1 } [
V{ } 0 insns>block basic-block set init-cfg-test
V{ } 1 insns>block [ basic-block get emit-loop-call ] V{ } make drop
basic-block get successors>> length
] unit-test
{ "bar" } [
V{ } "foo" insns>block basic-block set
init-cfg-test
[ V{ } "bar" insns>block basic-block get emit-loop-call ] V{ } make drop
basic-block get successors>> first number>>
] unit-test
! emit-node
{
{ T{ ##load-integer { dst 78 } { val 0 } } }
} [
77 vreg-counter set-global
[ f T{ #push { literal 0 } { out-d { 8537399 } } } emit-node ] { } make
] cfg-unit-test
{
{ { 1 1 } { 0 0 } }
H{ { D: -1 4 } { D: 0 4 } }
} [
4 D: 0 replace-loc
f T{ #shuffle
{ mapping { { 2 4 } { 3 4 } } }
{ in-d V{ 4 } }
{ out-d V{ 2 3 } }
} emit-node
height-state get
replaces get
] cfg-unit-test
! ! #call
{
V{
T{ ##load-integer { dst 3 } { val 0 } }
@ -290,15 +304,9 @@ IN: compiler.cfg.builder.tests
{ word alien-cell }
{ in-d V{ 10 20 } }
{ out-d { 30 } }
} [ emit-node ] V{ } make
} [ emit-node drop ] V{ } make
] cfg-unit-test
{ 1 } [
V{ } 0 insns>block basic-block set init-cfg-test
V{ } 1 insns>block [ basic-block get emit-loop-call ] V{ } make drop
basic-block get successors>> length
] unit-test
: call-node-1 ( -- node )
T{ #call
{ word set-slot }
@ -334,38 +342,60 @@ IN: compiler.cfg.builder.tests
{
V{ T{ ##call { word set-slot } } T{ ##branch } }
} [
[ f call-node-1 emit-node ] V{ } make drop
[ f call-node-1 emit-node drop ] V{ } make drop
basic-block get successors>> first instructions>>
] cfg-unit-test
! emit-loop-call
{ "bar" } [
V{ } "foo" insns>block basic-block set
init-cfg-test
[ V{ } "bar" insns>block basic-block get emit-loop-call ] V{ } make drop
basic-block get successors>> first number>>
! ! #push
{
{ T{ ##load-integer { dst 78 } { val 0 } } }
} [
77 vreg-counter set-global
[ f T{ #push { literal 0 } { out-d { 8537399 } } } emit-node drop ] { } make
] cfg-unit-test
! ! #shuffle
{
{ { 1 1 } { 0 0 } }
H{ { D: -1 4 } { D: 0 4 } }
} [
4 D: 0 replace-loc
f T{ #shuffle
{ mapping { { 2 4 } { 3 4 } } }
{ in-d V{ 4 } }
{ out-d V{ 2 3 } }
} emit-node drop
height-state get
replaces get
] cfg-unit-test
! ! #terminate
{ f } [
basic-block get dup set-basic-block
T{ #terminate { in-d { } } { in-r { } } } emit-node
] cfg-unit-test
! end-word
{
V{
T{ ##safepoint }
T{ ##epilogue }
T{ ##return }
}
} [
[
<basic-block> dup set-basic-block end-word
] V{ } make drop instructions>>
] unit-test
! begin-cfg
SYMBOL: foo
{ foo } [
\ foo f begin-cfg word>>
] cfg-unit-test
! remember-loop
{ 20 } [
H{ } clone loops set
"hello" { } 20 insns>block remember-loop
loops get "hello" of number>>
] cfg-unit-test
! store-shuffle
{
H{ { D: 2 1 } }
} [
f T{ #shuffle { in-d { 7 3 0 } } { out-d { 55 } } { mapping { { 55 3 } } } }
emit-node replaces get
emit-node drop replaces get
] cfg-unit-test
{
@ -375,5 +405,5 @@ SYMBOL: foo
{ in-d { 7 } }
{ out-d { 55 77 } }
{ mapping { { 55 7 } { 77 7 } } }
} emit-node replaces get
} emit-node drop replaces get
] cfg-unit-test

View File

@ -5,8 +5,8 @@ compiler.cfg.builder.blocks compiler.cfg.comparisons
compiler.cfg.hats compiler.cfg.instructions
compiler.cfg.intrinsics compiler.cfg.registers
compiler.cfg.stacks compiler.cfg.stacks.local compiler.tree
compiler.cfg.utilities cpu.architecture fry kernel make math namespaces
sequences words ;
compiler.cfg.utilities cpu.architecture fry kernel locals make math
namespaces sequences words ;
IN: compiler.cfg.builder
SYMBOL: procedures
@ -16,14 +16,11 @@ SYMBOL: loops
H{ } clone loops set
<basic-block> dup set-basic-block <cfg> dup cfg set ;
: begin-procedure ( word label -- )
begin-cfg procedures get push ;
: with-cfg-builder ( nodes word label quot: ( ..a block -- ..b ) -- )
'[
begin-stack-analysis
begin-procedure
basic-block get @
begin-cfg dup procedures get push
entry>> @
end-stack-analysis
] with-scope ; inline
@ -33,18 +30,18 @@ SYMBOL: loops
'[ _ t t [ drop _ call( node -- ) ] with-cfg-builder ] with-variable
] { } make drop ;
GENERIC: emit-node ( block node -- )
GENERIC: emit-node ( block node -- block' )
: emit-nodes ( nodes -- )
[ basic-block get [ swap emit-node ] [ drop ] if* ] each ;
: emit-nodes ( block nodes -- block' )
[ over [ emit-node ] [ drop ] if ] each ;
: begin-word ( block -- )
: begin-word ( block -- block' )
dup make-kill-block
##safepoint, ##prologue, ##branch,
begin-basic-block ;
: (build-cfg) ( nodes word label -- )
[ begin-word emit-nodes ] with-cfg-builder ;
[ begin-word swap emit-nodes drop ] with-cfg-builder ;
: build-cfg ( nodes word -- procedures )
V{ } clone [
@ -54,41 +51,40 @@ GENERIC: emit-node ( block node -- )
] keep ;
: emit-loop-call ( successor-block current-block -- )
##safepoint,
##branch,
##safepoint, ##branch,
[ swap connect-bbs ] [ end-basic-block ] bi ;
: emit-call ( block word height -- )
over loops get at [ 2nip swap emit-loop-call ]
[
[ emit-call-block ] emit-trivial-block drop
] if* ;
: emit-trivial-call ( block word height -- block' )
##branch, rot begin-basic-block
[ emit-call-block ] keep
##branch, begin-basic-block ;
: emit-call ( block word height -- block' )
over loops get at [
2nip swap emit-loop-call f
] [ emit-trivial-call ] if* ;
! #recursive
: recursive-height ( #recursive -- n )
[ label>> return>> in-d>> length ] [ in-d>> length ] bi - ;
: emit-recursive ( block #recursive -- )
: emit-recursive ( block #recursive -- block' )
[ [ label>> id>> ] [ recursive-height ] bi emit-call ] keep
[ child>> ] [ label>> word>> ] [ label>> id>> ] tri (build-cfg) ;
: remember-loop ( label block -- )
swap loops get set-at ;
: emit-loop ( block #recursive -- block' )
##branch, [ begin-basic-block ] dip
[ label>> id>> loops get set-at ] [ child>> emit-nodes ] 2bi ;
: emit-loop ( node block -- )
##branch, begin-basic-block
[ label>> id>> basic-block get remember-loop ]
[ child>> emit-nodes ] bi ;
M: #recursive emit-node ( block node -- )
dup label>> loop?>> [ swap emit-loop ] [ emit-recursive ] if ;
M: #recursive emit-node ( block node -- block' )
dup label>> loop?>> [ emit-loop ] [ emit-recursive ] if ;
! #if
: emit-branch ( obj -- pair/f )
[ emit-nodes ] with-branch ;
: emit-branch ( nodes block -- pair/f )
[ begin-branch swap emit-nodes end-branch ] with-scope ;
: emit-if ( block node -- )
children>> [ emit-branch ] map swap emit-conditional ;
: emit-if ( block node -- block' )
children>> over '[ _ emit-branch ] map emit-conditional ;
: trivial-branch? ( nodes -- value ? )
dup length 1 = [
@ -113,33 +109,34 @@ M: #recursive emit-node ( block node -- )
: emit-trivial-not-if ( -- )
[ f cc= ^^compare-imm ] unary-op ;
: emit-actual-if ( block #if -- )
: emit-actual-if ( block #if -- block' )
! Inputs to the final instruction need to be copied because of
! loc>vreg sync
ds-pop any-rep ^^copy f cc/= ##compare-imm-branch, emit-if ;
M: #if emit-node ( block node -- )
M: #if emit-node ( block node -- block' )
{
{ [ dup trivial-if? ] [ 2drop emit-trivial-if ] }
{ [ dup trivial-not-if? ] [ 2drop emit-trivial-not-if ] }
{ [ dup trivial-if? ] [ drop emit-trivial-if ] }
{ [ dup trivial-not-if? ] [ drop emit-trivial-not-if ] }
[ emit-actual-if ]
} cond ;
M: #dispatch emit-node ( block node -- )
M: #dispatch emit-node ( block node -- block' )
! Inputs to the final instruction need to be copied because of
! loc>vreg sync. ^^offset>slot always returns a fresh vreg,
! though.
ds-pop ^^offset>slot next-vreg ##dispatch, emit-if ;
M: #call emit-node ( block node -- )
dup word>> dup "intrinsic" word-prop
[ nip call( node -- ) drop ] [ swap call-height emit-call ] if* ;
M: #call emit-node ( block node -- block' )
dup word>> dup "intrinsic" word-prop [
nip call( node -- ) drop basic-block get
] [ swap call-height emit-call ] if* ;
M: #call-recursive emit-node ( block node -- )
M: #call-recursive emit-node ( block node -- block' )
[ label>> id>> ] [ call-height ] bi emit-call ;
M: #push emit-node ( block node -- )
nip literal>> ^^load-literal ds-push ;
M: #push emit-node ( block node -- block' )
literal>> ^^load-literal ds-push ;
! #shuffle
@ -165,35 +162,35 @@ M: #push emit-node ( block node -- )
[ make-input-map ] [ mapping>> ] [ extract-outputs ] tri
[ first2 [ [ of of peek-loc ] 2with map ] dip 2array ] 2with map ;
M: #shuffle emit-node ( block node -- )
nip [ out-vregs/stack ] keep store-height-changes
M: #shuffle emit-node ( block node -- block' )
[ out-vregs/stack ] keep store-height-changes
[ first2 store-vregs ] each ;
! #return
: end-word ( block -- )
: end-word ( block -- block' )
##branch, begin-basic-block
basic-block get make-kill-block
dup make-kill-block
##safepoint,
##epilogue,
##return, ;
M: #return emit-node ( block node -- )
M: #return emit-node ( block node -- block' )
drop end-word ;
M: #return-recursive emit-node ( block node -- )
label>> id>> loops get key? [ drop ] [ end-word ] if ;
M: #return-recursive emit-node ( block node -- block' )
label>> id>> loops get key? [ ] [ end-word ] if ;
! #terminate
M: #terminate emit-node ( block node -- )
drop ##no-tco, end-basic-block ;
M: #terminate emit-node ( block node -- block' )
drop ##no-tco, end-basic-block f ;
! No-op nodes
M: #introduce emit-node 2drop ;
M: #introduce emit-node drop ;
M: #copy emit-node 2drop ;
M: #copy emit-node drop ;
M: #enter-recursive emit-node 2drop ;
M: #enter-recursive emit-node drop ;
M: #phi emit-node 2drop ;
M: #phi emit-node drop ;
M: #declare emit-node 2drop ;
M: #declare emit-node drop ;

View File

@ -29,7 +29,7 @@ IN: compiler.cfg.intrinsics.fixnum
ds-peek 0 cc> ##compare-integer-imm-branch,
[ emit-fixnum-left-shift ] with-branch
[ emit-fixnum-right-shift ] with-branch
2array basic-block get emit-conditional ;
2array basic-block get swap emit-conditional drop ;
: emit-fixnum-shift-fast ( node -- )
node-input-infos second interval>> {
@ -54,7 +54,7 @@ IN: compiler.cfg.intrinsics.fixnum
! of loc>vreg sync
[ [ (2inputs) [ any-rep ^^copy ] bi@ cc/o ] dip call ] dip
[ emit-no-overflow-case ] [ emit-overflow-case ] bi* 2array
basic-block get emit-conditional ; inline
basic-block get swap emit-conditional drop ; inline
: fixnum+overflow ( x y -- z ) [ >bignum ] bi@ + ;