rapx/analysis/rcanary/ranalyzer/
order.rs1use rustc_middle::mir::TerminatorKind;
2
3use std::collections::BinaryHeap;
4use super::super::ranalyzer::{FlowAnalysis, NodeOrder};
7use super::super::RcxMut;
8use super::mir_body;
9
10impl<'tcx, 'a> FlowAnalysis<'tcx, 'a> {
11 pub fn order(&mut self) {
12 let tcx = self.tcx();
18 let mir_keys = tcx.mir_keys(());
19
20 for each_mir in mir_keys {
21 let def_id = each_mir.to_def_id();
23 let body = mir_body(tcx, def_id);
24
25 let mut path = NodeOrder::new(body);
26 let mut lev: Vec<usize> = vec![0; body.basic_blocks.len()];
27
28 path.collect_edges(&mut lev);
29 path.topo_order(&mut lev);
30 self.rcx_mut()
31 .mir_graph_mut()
32 .insert(def_id, path.graph_mut().clone());
33 }
34
35 }
38}
39
40impl<'tcx> NodeOrder<'tcx> {
41 pub(crate) fn collect_edges(&mut self, lev: &mut Vec<usize>) {
43 let bbs = &self.body().basic_blocks;
44 for (block, data) in bbs.iter().enumerate() {
45 let mut result: Vec<usize> = vec![];
46 match &data.terminator().kind {
47 TerminatorKind::Goto { target } => result.push(target.as_usize()),
48 TerminatorKind::SwitchInt { targets, .. } => {
49 for bb in targets.all_targets() {
50 result.push(bb.as_usize());
51 }
52 }
53 TerminatorKind::Return => (),
54 TerminatorKind::Unreachable => (),
55 TerminatorKind::Drop { target, .. } => result.push(target.as_usize()),
56 TerminatorKind::Assert { target, .. } => result.push(target.as_usize()),
57 TerminatorKind::Yield { .. } => (),
58 TerminatorKind::FalseEdge { .. } => (),
59 TerminatorKind::FalseUnwind { .. } => (),
60 TerminatorKind::InlineAsm { .. } => (),
61 TerminatorKind::UnwindResume => (),
62 TerminatorKind::UnwindTerminate(..) => (),
63 TerminatorKind::CoroutineDrop => (),
64 TerminatorKind::Call { target, .. } => {
65 match target {
70 Some(t) => result.push(t.as_usize()),
71 None => (),
72 }
73 }
74 TerminatorKind::TailCall { .. } => todo!(),
75 }
76 for index in result.iter() {
78 lev[*index] = lev[*index] + 1;
79 self.graph_mut().get_pre_mut()[*index].push(block);
80 }
81 self.graph_mut().get_edges_mut()[block] = result;
82 }
83 }
84
85 pub(crate) fn topo_order(&mut self, lev: &mut Vec<usize>) {
86 let mut q: BinaryHeap<usize> = BinaryHeap::new();
87 q.push(0);
88 while !q.is_empty() {
89 let top = q.pop().unwrap();
90 self.graph_mut().get_topo_mut().push(top);
91 for cnt in 0..self.graph().e[top].len() {
92 let next = self.graph().e[top][cnt];
93 lev[next] = lev[next] - 1;
94 if lev[next] == 0 {
95 q.push(next);
96 }
97 }
98 }
99 }
100}