open_vaf/analysis/data_flow/framework/
mod.rs1pub use engine::Engine;
10pub use graph::Graph as DataFlowGraph;
11
12mod engine;
13mod graph;
14
15use crate::data_structures::{BitSet, WorkQueue};
16use crate::ir::cfg::{BasicBlockId, ControlFlowGraph};
17use index_vec::{Idx, IndexVec};
18
19pub trait GenKillAnalysis<'lt>: Sized {
20 type SetType: Idx + From<usize>;
21 type Direction: Direction<'lt>;
22
23 fn transfer_function(
24 &mut self,
25 gen_kill_set: &mut GenKillSet<Self::SetType>,
26 basic_bock: BasicBlockId,
27 cfg: &ControlFlowGraph,
28 );
29
30 fn max_idx(&self) -> Self::SetType;
31}
32
33pub trait Analysis<'lt>: Sized {
34 type SetType: Idx + From<usize>;
35 type Direction: Direction<'lt>;
36
37 fn transfer_function(
38 &mut self,
39 in_set: &BitSet<Self::SetType>,
40 out_set: &mut BitSet<Self::SetType>,
41 basic_bock: BasicBlockId,
42 cfg: &ControlFlowGraph,
43 );
44
45 fn join(&mut self, inout_set: &mut BitSet<Self::SetType>, in_set: &BitSet<Self::SetType>) {
46 inout_set.union_with(in_set);
47 }
48
49 fn max_idx(&self) -> Self::SetType;
50}
51
52pub trait Direction<'lt> {
53 fn inital_work_queue(cfg: &ControlFlowGraph) -> WorkQueue<BasicBlockId>;
54 fn propagate_result(bb: BasicBlockId, cfg: &ControlFlowGraph, apply: impl FnMut(BasicBlockId));
55}
56
57pub struct Forward;
58
59impl<'lt> Direction<'lt> for Forward {
60 fn inital_work_queue(cfg: &ControlFlowGraph) -> WorkQueue<BasicBlockId> {
61 let mut res = WorkQueue::with_none(cfg.blocks.len_idx());
62 for id in cfg.reverse_postorder() {
63 res.insert(id);
64 }
65 res
66 }
67
68 fn propagate_result(
69 bb: BasicBlockId,
70 cfg: &ControlFlowGraph,
71 mut apply: impl FnMut(BasicBlockId),
72 ) {
73 for bb in cfg.successors(bb) {
74 apply(bb)
75 }
76 }
77}
78
79pub struct Backward;
80
81impl<'lt> Direction<'lt> for Backward {
82 fn inital_work_queue(cfg: &ControlFlowGraph) -> WorkQueue<BasicBlockId> {
83 let mut res = WorkQueue::with_none(cfg.blocks.len_idx());
84 for (id, _) in cfg.postorder_iter() {
85 res.insert(id);
86 }
87 res
88 }
89
90 fn propagate_result(
91 bb: BasicBlockId,
92 cfg: &ControlFlowGraph,
93 mut apply: impl FnMut(BasicBlockId),
94 ) {
95 for &bb in cfg.predecessors(bb) {
96 apply(bb)
97 }
98 }
99}
100
101pub struct GenKillEngine<'lt, A: GenKillAnalysis<'lt>> {
102 analysis: &'lt mut A,
103 pub transfer_functions: IndexVec<BasicBlockId, GenKillSet<A::SetType>>,
104}
105
106impl<'lt, A: GenKillAnalysis<'lt>> GenKillEngine<'lt, A> {
107 pub fn new(cfg: &ControlFlowGraph, analysis: &'lt mut A) -> Self {
108 let gen_kill_set = GenKillSet::new(analysis.max_idx());
109 let transfer_functions = cfg
110 .blocks
111 .indices()
112 .map(|bb| {
113 let mut transfer_function = gen_kill_set.clone();
114 analysis.transfer_function(&mut transfer_function, bb, cfg);
115 transfer_function
116 })
117 .collect();
118
119 Self {
120 analysis,
121 transfer_functions,
122 }
123 }
124}
125
126impl<'lt, A: GenKillAnalysis<'lt>> Analysis<'lt> for GenKillEngine<'lt, A> {
127 type SetType = A::SetType;
128 type Direction = A::Direction;
129
130 fn transfer_function(
131 &mut self,
132 in_set: &BitSet<Self::SetType>,
133 out_set: &mut BitSet<Self::SetType>,
134 basic_bock: BasicBlockId,
135 _: &ControlFlowGraph,
136 ) {
137 out_set.clear();
138 out_set.union_with(in_set);
139 out_set.difference_with(&self.transfer_functions[basic_bock].kill);
140 out_set.union_with(&self.transfer_functions[basic_bock].gen);
141 }
142 fn max_idx(&self) -> Self::SetType {
143 self.analysis.max_idx()
144 }
145}
146
147#[derive(Clone)]
148pub struct GenKillSet<I: Idx + From<usize>> {
149 pub gen: BitSet<I>,
150 pub kill: BitSet<I>,
151}
152
153impl<I: Idx + From<usize>> GenKillSet<I> {
154 #[inline]
155 pub fn new(max_idx: I) -> Self {
156 let gen = BitSet::new_empty(max_idx);
157 Self {
158 kill: gen.clone(),
159 gen,
160 }
161 }
162
163 #[inline]
164 pub fn gen(&mut self, x: I) {
165 self.gen.insert(x);
166 self.kill.set(x, false);
167 }
168
169 #[inline]
170 pub fn kill(&mut self, x: I) {
171 self.kill.insert(x);
172 self.gen.set(x, false);
173 }
174
175 #[inline]
176 pub fn kill_all(&mut self, kill: &BitSet<I>) {
177 self.kill.union_with(kill);
178 self.gen.difference_with(kill);
179 }
180
181 #[inline]
182 pub fn gen_all(&mut self, gen: &BitSet<I>) {
183 self.gen.union_with(gen);
184 self.kill.difference_with(gen);
185 }
186}