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
							parent
							
								
									07adc2ecae
								
							
						
					
					
						commit
						f9c6d7cc43
					
				| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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?>>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 ;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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@ + ;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue