78 lines
2.4 KiB
Factor
78 lines
2.4 KiB
Factor
USING: accessors arrays assocs combinators compiler.cfg.dataflow-analysis
|
|
compiler.cfg.instructions compiler.cfg.linearization compiler.cfg.stacks.local
|
|
compiler.cfg.registers fry kernel math math.order namespaces sequences ;
|
|
QUALIFIED: sets
|
|
IN: compiler.cfg.stacks.map
|
|
|
|
! Operations on the stack info
|
|
: register-write ( n stack -- stack' )
|
|
first2 rot suffix sets:members 2array ;
|
|
|
|
: adjust-stack ( n stack -- stack' )
|
|
first2 pick '[ _ + ] map [ + ] dip 2array ;
|
|
|
|
: stack>vacant ( stack -- seq )
|
|
first2 [ 0 max iota ] dip sets:diff ;
|
|
|
|
: classify-read ( stack n -- val )
|
|
swap 2dup second member? [ 2drop 0 ] [ first >= [ 1 ] [ 2 ] if ] if ;
|
|
|
|
CONSTANT: initial-state { { 0 { } } { 0 { } } }
|
|
|
|
: mark-location ( state insn -- state' )
|
|
[ first2 ] dip loc>> >loc<
|
|
[ rot register-write swap ] [ swap register-write ] if 2array ;
|
|
|
|
: fill-vacancies ( state -- state' )
|
|
[ [ first2 ] [ stack>vacant ] bi append 2array ] map ;
|
|
|
|
GENERIC: visit-insn ( state insn -- state' )
|
|
|
|
M: ##inc visit-insn ( state insn -- state' )
|
|
[ first2 ] dip loc>> >loc<
|
|
[ rot adjust-stack swap ] [ swap adjust-stack ] if 2array
|
|
! Negative out-of stack locations immediately becomes garbage.
|
|
[ first2 [ 0 >= ] filter 2array ] map ;
|
|
|
|
M: ##replace-imm visit-insn mark-location ;
|
|
M: ##replace visit-insn mark-location ;
|
|
|
|
ERROR: vacant-peek insn ;
|
|
|
|
: underflowable-peek? ( state peek -- ? )
|
|
2dup loc>> >loc< swap [ 0 1 ? swap nth ] dip classify-read
|
|
dup 2 = [ drop vacant-peek ] [ 2nip 1 = ] if ;
|
|
|
|
M: ##peek visit-insn ( state insn -- state' )
|
|
2dup underflowable-peek? [ [ fill-vacancies ] dip ] when mark-location ;
|
|
|
|
M: insn visit-insn ( state insn -- state' )
|
|
drop ;
|
|
|
|
FORWARD-ANALYSIS: map
|
|
|
|
SYMBOL: stack-record
|
|
|
|
: register-stack-state ( state insn -- )
|
|
insn#>> stack-record get 2dup at f assert= set-at ;
|
|
|
|
M: map-analysis transfer-set ( in-set bb dfa -- out-set )
|
|
drop instructions>> swap [
|
|
[ register-stack-state ] [ visit-insn ] 2bi
|
|
] reduce ;
|
|
|
|
M: map-analysis ignore-block? ( bb dfa -- ? )
|
|
2drop f ;
|
|
|
|
! Picking the first means that a block will only be analyzed once.
|
|
M: map-analysis join-sets ( sets bb dfa -- set )
|
|
2drop [ initial-state ] [ first ] if-empty ;
|
|
|
|
: uniquely-number-instructions ( cfg -- )
|
|
cfg>insns [ swap insn#<< ] each-index ;
|
|
|
|
: trace-stack-state ( cfg -- assoc )
|
|
H{ } clone stack-record set
|
|
[ uniquely-number-instructions ] [ compute-map-sets ] bi
|
|
stack-record get ;
|