rapx/analysis/core/dataflow/
mod.rs1pub mod debug;
2pub mod default;
3pub mod graph;
4
5use std::{
6 collections::{HashMap, HashSet},
7 fmt::{self, Debug, Display},
8 fs::File,
9 io::Write,
10 process::Command,
11};
12
13use crate::{analysis::Analysis, utils::source::get_fn_name_byid};
14
15use rustc_hir::{def::DefKind, def_id::DefId};
16use rustc_index::IndexVec;
17use rustc_middle::{
18 mir::{Body, Local},
19 ty::TyCtxt,
20};
21use rustc_span::Span;
22
23pub type Arg2Ret = IndexVec<Local, bool>;
24pub type Arg2RetMap = HashMap<DefId, IndexVec<Local, bool>>;
25#[derive(Clone)]
26pub struct DataFlowGraph {
27 pub nodes: GraphNodes,
28 pub edges: GraphEdges,
29 pub param_ret_deps: Arg2Ret,
30}
31pub type DataFlowGraphMap = HashMap<DefId, DataFlowGraph>;
32
33pub struct Arg2RetWrapper(pub Arg2Ret);
34pub struct Arg2RetMapWrapper(pub Arg2RetMap);
35pub struct DataFlowGraphWrapper(pub DataFlowGraph);
36pub struct DataFlowGraphMapWrapper(pub HashMap<DefId, DataFlowGraph>);
37
38pub type EdgeIdx = usize;
39pub type GraphNodes = IndexVec<Local, GraphNode>;
40pub type GraphEdges = IndexVec<EdgeIdx, GraphEdge>;
41
42#[derive(Clone, Debug)]
43pub struct GraphEdge {
44 pub src: Local,
45 pub dst: Local,
46 pub op: EdgeOp,
47 pub seq: usize,
48}
49
50#[derive(Clone, Debug)]
51pub struct GraphNode {
52 pub ops: Vec<NodeOp>,
53 pub span: Span, pub seq: usize, pub out_edges: Vec<EdgeIdx>,
56 pub in_edges: Vec<EdgeIdx>,
57}
58
59pub trait DataFlowAnalysis: Analysis {
61 fn get_fn_dataflow(&self, def_id: DefId) -> Option<DataFlowGraph>;
63
64 fn get_all_dataflow(&self) -> DataFlowGraphMap;
66
67 fn has_flow_between(&self, def_id: DefId, local1: Local, local2: Local) -> bool;
70
71 fn collect_equivalent_locals(&self, def_id: DefId, local: Local) -> HashSet<Local>;
73
74 fn get_fn_arg2ret(&self, def_id: DefId) -> Arg2Ret;
76
77 fn get_all_arg2ret(&self) -> Arg2RetMap;
79}
80
81impl fmt::Display for Arg2RetWrapper {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 let arg2ret: &Arg2Ret = &self.0;
84 for (local, depends) in arg2ret.iter_enumerated() {
85 if local.as_u32() > 0 {
86 if *depends {
87 writeln!(f, "Argument {:?} ---> Return value _0", local)?;
88 }
89 }
90 }
91 Ok(())
92 }
93}
94
95impl fmt::Display for Arg2RetMapWrapper {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 writeln!(f, "=== Print dataflow analysis results ===")?;
98 for (def_id, arg2ret) in &self.0 {
99 let fn_name = get_fn_name_byid(def_id);
100 writeln!(
101 f,
102 "Function: {:?}\n{}",
103 fn_name,
104 Arg2RetWrapper(arg2ret.clone())
105 )?;
106 }
107 Ok(())
108 }
109}
110
111impl Display for DataFlowGraphWrapper {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 let graph = &self.0;
114 write!(
115 f,
116 "Graph statistics: {} nodes, {} edges.\n",
117 graph.nodes.len(),
118 graph.edges.len()
119 )?;
120 if graph.param_ret_deps.len() > 1 {
121 write!(f, "Return value dependencies: \n")?;
122 }
123 for (node_idx, deps) in graph.param_ret_deps.iter_enumerated() {
124 if node_idx.as_u32() > 0 {
125 if *deps {
126 write!(f, "Argument {:?} ---> Return value _0.\n", node_idx)?;
127 }
128 }
129 }
130
131 for (node_idx, node) in graph.nodes.iter_enumerated() {
132 let node_adj: Vec<Local> = node
133 .out_edges
134 .iter()
135 .map(|edge_idx| graph.edges[*edge_idx].dst)
136 .collect();
137 if !node_adj.is_empty() {
138 write!(f, "Node {:?} -> Node {:?}\n", node_idx, node_adj)?;
139 }
140 }
141 Ok(())
142 }
143}
144
145impl Debug for DataFlowGraphWrapper {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 writeln!(f, "Nodes:")?;
148 for node in &self.0.nodes {
149 writeln!(f, " {:?}", node)?;
150 }
151 writeln!(f, "Edges:")?;
152 for edge in &self.0.edges {
153 writeln!(f, " {:?}", edge)?;
154 }
155 Ok(())
156 }
157}
158
159impl Display for DataFlowGraphMapWrapper {
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 writeln!(f, "===Print dataflow analysis resuts===")?;
162 for (def_id, dfg) in &self.0 {
163 let fn_name = get_fn_name_byid(def_id);
164 writeln!(
165 f,
166 "Function: {:?}\n{}",
167 fn_name,
168 DataFlowGraphWrapper(dfg.clone())
169 )?;
170 }
171 Ok(())
172 }
173}
174
175impl Debug for DataFlowGraphMapWrapper {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 for (def_id, dfg) in &self.0 {
178 writeln!(
179 f,
180 "DefId: {:?}\n{:?}",
181 def_id,
182 DataFlowGraphWrapper(dfg.clone())
183 )?;
184 }
185 Ok(())
186 }
187}
188
189#[derive(Clone, Debug)]
190pub enum NodeOp {
191 Nop,
193 Err,
194 Const(String, String),
195 Use,
197 Repeat,
198 Ref,
199 ThreadLocalRef,
200 AddressOf,
201 Len,
202 Cast,
203 BinaryOp,
204 CheckedBinaryOp,
205 NullaryOp,
206 UnaryOp,
207 Discriminant,
208 Aggregate(AggKind),
209 ShallowInitBox,
210 CopyForDeref,
211 RawPtr,
212 Call(DefId),
214 CallOperand, }
216
217#[derive(Clone, Debug)]
218pub enum EdgeOp {
219 Nop,
220 Move,
222 Copy,
223 Const,
224 Immut,
226 Mut,
227 Deref,
229 Field(String),
230 Downcast(String),
231 Index,
232 ConstIndex,
233 SubSlice,
234 SubType,
235}
236
237#[derive(Clone, Copy, Debug)]
238pub enum AggKind {
239 Array,
240 Tuple,
241 Adt(DefId),
242 Closure(DefId),
243 Coroutine(DefId),
244 RawPtr,
245}