rapx/analysis/dataflow/
mod.rs

1pub mod debug;
2pub mod default;
3pub mod graph;
4
5use std::{
6    collections::{HashMap, HashSet},
7    fmt::{self, Debug, Display},
8};
9
10pub mod types;
11use crate::{analysis::Analysis, utils::source::get_fn_name_byid};
12pub use types::*;
13
14impl From<DataflowGraph> for DataFlowGraph {
15    fn from(graph: DataflowGraph) -> Self {
16        let param_ret_deps = graph.param_return_deps();
17        DataFlowGraph {
18            nodes: graph.nodes,
19            edges: graph.edges,
20            param_ret_deps,
21        }
22    }
23}
24
25// Backward-compatible aliases for code migrating from old `Graph`/`GraphNode`/`GraphEdge` names.
26pub type Graph = DataflowGraph;
27pub type GraphNode = DataflowNode;
28pub type GraphEdge = DataflowEdge;
29
30use rustc_hir::def_id::DefId;
31use rustc_index::IndexVec;
32use rustc_middle::mir::Local;
33
34pub type Arg2Ret = IndexVec<Local, bool>;
35pub type Arg2RetMap = HashMap<DefId, IndexVec<Local, bool>>;
36#[derive(Clone)]
37pub struct DataFlowGraph {
38    pub nodes: GraphNodes,
39    pub edges: GraphEdges,
40    pub param_ret_deps: Arg2Ret,
41}
42pub type DataFlowGraphMap = HashMap<DefId, DataFlowGraph>;
43
44pub struct Arg2RetWrapper(pub Arg2Ret);
45pub struct Arg2RetMapWrapper(pub Arg2RetMap);
46pub struct DataFlowGraphWrapper(pub DataFlowGraph);
47pub struct DataFlowGraphMapWrapper(pub HashMap<DefId, DataFlowGraph>);
48
49/// This trait provides features related to dataflow analysis.
50pub trait DataflowAnalysis: Analysis {
51    fn get_fn_dataflow(&self, def_id: DefId) -> Option<DataFlowGraph>;
52    fn get_all_dataflow(&self) -> DataFlowGraphMap;
53    fn has_flow_between(&self, def_id: DefId, local1: Local, local2: Local) -> bool;
54    fn collect_equivalent_locals(&self, def_id: DefId, local: Local) -> HashSet<Local>;
55    fn get_fn_arg2ret(&self, def_id: DefId) -> Arg2Ret;
56    fn get_all_arg2ret(&self) -> Arg2RetMap;
57}
58
59impl fmt::Display for Arg2RetWrapper {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        let arg2ret: &Arg2Ret = &self.0;
62        for (local, depends) in arg2ret.iter_enumerated() {
63            if local.as_u32() > 0 {
64                if *depends {
65                    writeln!(f, "Argument {:?} ---> Return value _0", local)?;
66                }
67            }
68        }
69        Ok(())
70    }
71}
72
73impl fmt::Display for Arg2RetMapWrapper {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        writeln!(f, "=== Print dataflow analysis results ===")?;
76        for (def_id, arg2ret) in &self.0 {
77            let fn_name = get_fn_name_byid(def_id);
78            writeln!(
79                f,
80                "Function: {:?}\n{}",
81                fn_name,
82                Arg2RetWrapper(arg2ret.clone())
83            )?;
84        }
85        Ok(())
86    }
87}
88
89impl Display for DataFlowGraphWrapper {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        let graph = &self.0;
92        write!(
93            f,
94            "Graph statistics: {} nodes, {} edges.\n",
95            graph.nodes.len(),
96            graph.edges.len()
97        )?;
98        if graph.param_ret_deps.len() > 1 {
99            write!(f, "Return value dependencies: \n")?;
100        }
101        for (node_idx, deps) in graph.param_ret_deps.iter_enumerated() {
102            if node_idx.as_u32() > 0 {
103                if *deps {
104                    write!(f, "Argument {:?} ---> Return value _0.\n", node_idx)?;
105                }
106            }
107        }
108
109        for (node_idx, node) in graph.nodes.iter_enumerated() {
110            let node_adj: Vec<Local> = node
111                .out_edges
112                .iter()
113                .map(|edge_idx| graph.edges[*edge_idx].dst)
114                .collect();
115            if !node_adj.is_empty() {
116                write!(f, "Node {:?} -> Node {:?}\n", node_idx, node_adj)?;
117            }
118        }
119        Ok(())
120    }
121}
122
123impl Debug for DataFlowGraphWrapper {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        writeln!(f, "Nodes:")?;
126        for node in &self.0.nodes {
127            writeln!(f, "  {:?}", node)?;
128        }
129        writeln!(f, "Edges:")?;
130        for edge in &self.0.edges {
131            writeln!(f, "  {:?}", edge)?;
132        }
133        Ok(())
134    }
135}
136
137impl Display for DataFlowGraphMapWrapper {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        writeln!(f, "===Print dataflow analysis resuts===")?;
140        for (def_id, dfg) in &self.0 {
141            let fn_name = get_fn_name_byid(def_id);
142            writeln!(
143                f,
144                "Function: {:?}\n{}",
145                fn_name,
146                DataFlowGraphWrapper(dfg.clone())
147            )?;
148        }
149        Ok(())
150    }
151}
152
153impl Debug for DataFlowGraphMapWrapper {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        for (def_id, dfg) in &self.0 {
156            writeln!(
157                f,
158                "DefId: {:?}\n{:?}",
159                def_id,
160                DataFlowGraphWrapper(dfg.clone())
161            )?;
162        }
163        Ok(())
164    }
165}