57444e4934e4afe7add6580f3351eb32c1c1f22c
2 import advanced_collections
7 var current_in
: nullable S
writable
8 var current_out
: nullable S
writable
10 fun in_set
(bb
: BasicBlock): nullable S
is abstract
11 fun out_set
(bb
: BasicBlock): nullable S
is abstract
12 fun in_set
=(bb
: BasicBlock, s
: S
) is abstract
13 fun out_set
=(bb
: BasicBlock, s
: S
) is abstract
17 current_in
= default_in_set
18 current_out
= default_in_set
21 redef fun visit
( node
) do node
.visit_all
(self)
23 # If false, it is a backwards analysis
24 fun is_forward
: Bool is abstract
26 # ex: do return in1.union( in2 )
27 # ex: do return in1.intersection( in2 )
28 fun merge
( in1
, in2
: nullable S
): nullable S
is abstract
30 fun default_in_set
: nullable S
do return null
31 fun empty_set
: S
is abstract
36 var current_in
: nullable S
37 var current_out
: nullable S
39 # set current input as default start case
40 var todo
= new List[BasicBlock]
41 todo
.add_all
(cfg
.blocks
)
43 # iterate until fixed point reached
44 while not todo
.is_empty
do
46 var block
= todo
.shift
48 if block
== cfg
.start
then
50 else if block
.predecessors
.is_empty
then
51 # get default in (the most safe one)
52 current_in
= default_in_set
54 current_in
= out_set
(block
.predecessors
.first
)
55 for l
in [1..block
.predecessors
.length
[ do
56 var b
= block
.predecessors
[l
]
57 current_in
= merge
(current_in
, out_set
(b
))
61 if current_in
!= null then
62 in_set
(block
) = current_in
.as(not null)
67 if block
== cfg
.finish
then continue
69 var old_out
= out_set
(block
)
70 for line
in block
.lines
do
71 self.current_in
= current_in
.as(not null)
72 self.current_out
= empty_set
76 current_out
= self.current_out
77 current_in
= self.current_out
.as(not null)
78 #self.current_in = current_in
81 current_out
= self.current_out
82 if old_out
!= current_out
then
83 out_set
(block
) = current_out
.as(not null)
85 for b
in block
.successors
do todo
.add
(b
)
87 for b
in block
.predecessors
do todo
.add
(b
)
93 fun pre_line_visit
(l
: ALine) do end
94 fun post_line_visit
(l
: ALine) do end
97 class FineFlowAnalysis[V
]
102 if bb
.lines
.is_empty
then return backup_in
(bb
)
103 return line_in
( bb
.lines
.first
)
106 redef fun in_set
=(bb
, v
)
108 if bb
.lines
.is_empty
then
110 else line_in
( bb
.lines
.first
) = v
113 redef fun out_set
(bb
)
115 if bb
.lines
.is_empty
then return backup_out
(bb
)
116 return line_out
( bb
.lines
.last
)
119 redef fun out_set
=(bb
, v
)
121 if bb
.lines
.is_empty
then
123 else line_out
( bb
.lines
.last
) = v
126 fun backup_in
(l
: BasicBlock): nullable V
is abstract
127 fun backup_out
(l
: BasicBlock): nullable V
is abstract
128 fun backup_in
=(l
: BasicBlock, v
: nullable V
) is abstract
129 fun backup_out
=(l
: BasicBlock, v
: nullable V
) is abstract
131 fun line_in
(l
: ALine): nullable V
is abstract
132 fun line_out
(l
: ALine): nullable V
is abstract
133 fun line_in
=(l
: ALine, v
: nullable V
) is abstract
134 fun line_out
=(l
: ALine, v
: nullable V
) is abstract
136 redef fun pre_line_visit
(line
) do line_in
(line
) = current_in
137 redef fun post_line_visit
(line
) do line_out
(line
) = current_out
140 class StaticAnalysis[S
]
144 init (set
: S
) do self.set
= set
146 redef fun visit
( node
) do node
.visit_all
(self)
147 fun analyze
(ast
: AListing): S