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(usize),
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}