6 var current_in
: nullable S
writable
7 var current_out
: nullable S
writable
9 fun in_set
(bb
: BasicBlock): nullable S
is abstract
10 fun out_set
(bb
: BasicBlock): nullable S
is abstract
11 fun in_set
=(bb
: BasicBlock, s
: S
) is abstract
12 fun out_set
=(bb
: BasicBlock, s
: S
) is abstract
16 current_in
= default_in_set
17 current_out
= default_in_set
20 redef fun visit
( node
) do node
.visit_all
(self)
22 # If false, it is a backwards analysis
23 fun is_forward
: Bool is abstract
25 # ex: do return in1.union( in2 )
26 # ex: do return in1.intersection( in2 )
27 fun merge
( in1
, in2
: nullable S
): nullable S
is abstract
29 fun default_in_set
: nullable S
do return null
30 fun empty_set
: S
is abstract
35 var current_in
: nullable S
36 var current_out
: nullable S
38 # set current input as default start case
39 var todo
= new List[BasicBlock]
40 todo
.add_all
(cfg
.blocks
)
42 # iterate until fixed point reached
43 while not todo
.is_empty
do
45 var block
= todo
.shift
47 if block
== cfg
.start
then
49 else if block
.predecessors
.is_empty
then
50 # get default in (the most safe one)
51 current_in
= default_in_set
53 current_in
= out_set
(block
.predecessors
.first
)
54 for l
in [1..block
.predecessors
.length
[ do
55 var b
= block
.predecessors
[l
]
56 current_in
= merge
(current_in
, out_set
(b
))
60 if current_in
!= null then
61 in_set
(block
) = current_in
.as(not null)
66 if block
== cfg
.finish
then continue
68 var old_out
= out_set
(block
)
69 for line
in block
.lines
do
70 self.current_in
= current_in
.as(not null)
71 self.current_out
= empty_set
75 current_out
= self.current_out
76 current_in
= self.current_out
.as(not null)
77 #self.current_in = current_in
80 current_out
= self.current_out
81 if old_out
!= current_out
then
82 out_set
(block
) = current_out
.as(not null)
84 for b
in block
.successors
do todo
.add
(b
)
86 for b
in block
.predecessors
do todo
.add
(b
)
92 fun pre_line_visit
(l
: ALine) do end
93 fun post_line_visit
(l
: ALine) do end
96 class FineFlowAnalysis[V
]
101 if bb
.lines
.is_empty
then return backup_in
(bb
)
102 return line_in
( bb
.lines
.first
)
105 redef fun in_set
=(bb
, v
)
107 if bb
.lines
.is_empty
then
109 else line_in
( bb
.lines
.first
) = v
112 redef fun out_set
(bb
)
114 if bb
.lines
.is_empty
then return backup_out
(bb
)
115 return line_out
( bb
.lines
.last
)
118 redef fun out_set
=(bb
, v
)
120 if bb
.lines
.is_empty
then
122 else line_out
( bb
.lines
.last
) = v
125 fun backup_in
(l
: BasicBlock): nullable V
is abstract
126 fun backup_out
(l
: BasicBlock): nullable V
is abstract
127 fun backup_in
=(l
: BasicBlock, v
: nullable V
) is abstract
128 fun backup_out
=(l
: BasicBlock, v
: nullable V
) is abstract
130 fun line_in
(l
: ALine): nullable V
is abstract
131 fun line_out
(l
: ALine): nullable V
is abstract
132 fun line_in
=(l
: ALine, v
: nullable V
) is abstract
133 fun line_out
=(l
: ALine, v
: nullable V
) is abstract
135 redef fun pre_line_visit
(line
) do line_in
(line
) = current_in
136 redef fun post_line_visit
(line
) do line_out
(line
) = current_out
139 class StaticAnalysis[S
]
143 init (set
: S
) do self.set
= set
145 redef fun visit
( node
) do node
.visit_all
(self)
146 fun analyze
(ast
: AListing): S