-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdominator.rs
116 lines (105 loc) · 3.65 KB
/
dominator.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::utils::{BasicBlock, CFGNode};
use petgraph::algo::dominators::Dominators;
use petgraph::{graph::NodeIndex, Direction};
use std::collections::HashSet;
use std::vec;
use crate::cfg::{self, CFG};
/// Build dominance frontier
fn compute_dominance_frontier<T: Clone + std::fmt::Debug + std::fmt::Display + CFGNode>(
dominators: &Dominators<NodeIndex>,
cfg: &CFG<T>,
) -> Vec<HashSet<NodeIndex>> {
//computes all nodes dominated by node
fn dom_by(
node: NodeIndex,
dominators: &Dominators<NodeIndex>,
memo: &mut Vec<Option<HashSet<NodeIndex>>>,
) {
if memo[node.index()].is_some() {
return;
}
let mut dom = HashSet::from([node]);
for idom in dominators.immediately_dominated_by(node) {
if idom.index() == node.index() {
continue;
}
dom_by(idom, dominators, memo);
dom.extend(memo[idom.index()].as_ref().unwrap());
}
memo[node.index()] = Some(dom);
}
//helper function to compute the dominance frontier of each node
fn dom_frontier_recur<T: Clone + std::fmt::Debug + CFGNode>(
node: NodeIndex,
dominators: &Dominators<NodeIndex>,
dom_by: &Vec<HashSet<NodeIndex>>,
cfg: &CFG<T>,
memo: &mut Vec<Option<HashSet<NodeIndex>>>,
) {
if memo[node.index()].is_some() {
return;
}
let mut DF: HashSet<NodeIndex> = cfg
.graph
.neighbors_directed(node, Direction::Outgoing)
.collect::<HashSet<_>>();
for idom in dominators.immediately_dominated_by(node) {
if idom.index() == node.index() {
continue;
}
dom_frontier_recur(idom, dominators, dom_by, cfg, memo);
DF.extend(memo[idom.index()].as_ref().unwrap());
}
memo[node.index()] = Some(
DF.difference(&dom_by[node.index()])
.map(|x| *x)
.collect::<HashSet<_>>(),
);
}
let mut memo = vec![None; cfg.graph.node_count()];
for node in cfg.graph.node_indices() {
dom_by(node, dominators, &mut memo);
}
//dom_by(cfg.start(), dominators, &mut memo);
let dom_by = memo.into_iter().map(|x| x.unwrap()).collect::<Vec<_>>();
let mut memo = vec![None; cfg.graph.node_count()];
for node in cfg.graph.node_indices() {
dom_frontier_recur(node, dominators, &dom_by, cfg, &mut memo);
}
memo.into_iter().map(|x| x.unwrap()).collect::<Vec<_>>()
}
pub fn dominator_analyis<T: Clone + std::fmt::Debug + std::fmt::Display + CFGNode>(
cfg: &CFG<T>,
) -> (Dominators<NodeIndex>, Vec<HashSet<NodeIndex>>) {
let dominators = petgraph::algo::dominators::simple_fast(&cfg.graph, cfg.start());
let dom_frontier = compute_dominance_frontier(&dominators, cfg);
(dominators, dom_frontier)
}
pub fn dom_tree(
dominators: &Dominators<NodeIndex>,
cfg: &CFG<BasicBlock>,
) -> petgraph::Graph<String, ()> {
let mut dom_tree = petgraph::Graph::<String, ()>::new();
for node in cfg.graph.node_indices() {
dom_tree.add_node(
cfg.graph
.node_weight(node)
.unwrap()
.label
.clone()
.unwrap_or("".to_string()),
);
}
for node in cfg.graph.node_indices() {
for idom in dominators.immediately_dominated_by(node) {
if idom != node {
dom_tree.add_edge(
NodeIndex::from(node.index() as u32),
NodeIndex::from(idom.index() as u32),
(),
);
}
}
}
dom_tree
}