diff --git a/rap/src/analysis/core/dataflow/debug.rs b/rap/src/analysis/core/dataflow/debug.rs index df70901..7c413f9 100644 --- a/rap/src/analysis/core/dataflow/debug.rs +++ b/rap/src/analysis/core/dataflow/debug.rs @@ -17,47 +17,13 @@ impl GraphEdge { pub fn to_dot_graph<'tcx>(&self) -> String { let mut attr = String::new(); let mut dot = String::new(); - match self { - //label=xxx - GraphEdge::NodeEdge { - src: _, - dst: _, - op, - seq, - } => { - write!( - attr, - "label=\"{}\" ", - escaped_string(format!("{}_{:?}", seq, op)) - ) - .unwrap(); - } - GraphEdge::ConstEdge { - src: _, - dst: _, - op, - seq, - } => { - write!( - attr, - "label=\"{}\" ", - escaped_string(format!("{}_{:?}", seq, op)) - ) - .unwrap(); - } - } - match self { - GraphEdge::NodeEdge { - src, dst, op: _, .. - } => { - write!(dot, "{:?} -> {:?} [{}]", src, dst, attr).unwrap(); - } - GraphEdge::ConstEdge { - src, dst, op: _, .. - } => { - write!(dot, "{:?} -> {:?} [{}]", src, dst, attr).unwrap(); - } - } + write!( + attr, + "label=\"{}\" ", + escaped_string(format!("{}_{:?}", self.seq, self.op)) + ) + .unwrap(); + write!(dot, "{:?} -> {:?} [{}]", self.src, self.dst, attr).unwrap(); dot } } @@ -81,6 +47,14 @@ impl GraphNode { write!(attr, "label=\" {:?}\" ", local).unwrap(); } } + NodeOp::Const(ref name) => { + write!( + attr, + "label=\" {}\" style=dashed ", + escaped_string(name.clone()) + ) + .unwrap(); + } NodeOp::Call(def_id) => { let func_name = tcx.def_path_str(def_id); if is_marker { diff --git a/rap/src/analysis/core/dataflow/graph.rs b/rap/src/analysis/core/dataflow/graph.rs index 8c03789..8441aee 100644 --- a/rap/src/analysis/core/dataflow/graph.rs +++ b/rap/src/analysis/core/dataflow/graph.rs @@ -15,6 +15,7 @@ pub enum NodeOp { //warning: the fields are related to the version of the backend rustc version Nop, Err, + Const(String), //Rvalue Use, Repeat, @@ -55,19 +56,11 @@ pub enum EdgeOp { } #[derive(Clone)] -pub enum GraphEdge { - NodeEdge { - src: Local, - dst: Local, - op: EdgeOp, - seq: u32, - }, - ConstEdge { - src: String, - dst: Local, - op: EdgeOp, - seq: u32, - }, +pub struct GraphEdge { + pub src: Local, + pub dst: Local, + pub op: EdgeOp, + pub seq: u32, } #[derive(Clone)] @@ -117,7 +110,7 @@ impl Graph { pub fn add_node_edge(&mut self, src: Local, dst: Local, op: EdgeOp) -> EdgeIdx { let seq = self.nodes[dst].seq; - let edge_idx = self.edges.push(GraphEdge::NodeEdge { src, dst, op, seq }); + let edge_idx = self.edges.push(GraphEdge { src, dst, op, seq }); self.nodes[dst].in_edges.push(edge_idx); self.nodes[src].out_edges.push(edge_idx); edge_idx @@ -125,7 +118,10 @@ impl Graph { pub fn add_const_edge(&mut self, src: String, dst: Local, op: EdgeOp) -> EdgeIdx { let seq = self.nodes[dst].seq; - let edge_idx = self.edges.push(GraphEdge::ConstEdge { src, dst, op, seq }); + let mut const_node = GraphNode::new(); + const_node.op = NodeOp::Const(src); + let src = self.nodes.push(const_node); + let edge_idx = self.edges.push(GraphEdge { src, dst, op, seq }); self.nodes[dst].in_edges.push(edge_idx); edge_idx } @@ -307,8 +303,8 @@ impl Graph { pub fn collect_equivalent_locals(&self, local: Local) -> HashSet { let mut set = HashSet::new(); let mut root = local; - let mut find_root_operator = |idx: Local| -> DFSStatus { - let node = &self.nodes[idx]; + let mut find_root_operator = |graph: &Graph, idx: Local| -> DFSStatus { + let node = &graph.nodes[idx]; match node.op { NodeOp::Nop | NodeOp::Use | NodeOp::Ref => { //Nop means an orphan node or a parameter @@ -318,8 +314,8 @@ impl Graph { _ => DFSStatus::Stop, } }; - let mut find_equivalent_operator = |idx: Local| -> DFSStatus { - let node = &self.nodes[idx]; + let mut find_equivalent_operator = |graph: &Graph, idx: Local| -> DFSStatus { + let node = &graph.nodes[idx]; if set.contains(&idx) { return DFSStatus::Stop; } @@ -352,7 +348,7 @@ impl Graph { pub fn is_connected(&self, idx_1: Local, idx_2: Local) -> bool { let target = idx_2; let find = Cell::new(false); - let mut node_operator = |idx: Local| -> DFSStatus { + let mut node_operator = |_: &Graph, idx: Local| -> DFSStatus { find.set(idx == target); if find.get() { DFSStatus::Stop @@ -406,32 +402,30 @@ impl Graph { traverse_all: bool, ) -> DFSStatus where - F: FnMut(Local) -> DFSStatus, - G: FnMut(&EdgeOp) -> DFSStatus, + F: FnMut(&Graph, Local) -> DFSStatus, + G: FnMut(&Graph, EdgeIdx) -> DFSStatus, { macro_rules! traverse { ($edges: ident, $field: ident) => { for edge_idx in self.nodes[now].$edges.iter() { let edge = &self.edges[*edge_idx]; - if let GraphEdge::NodeEdge { $field, op, .. } = edge { - if matches!(edge_validator(op), DFSStatus::Continue) { - let result = self.dfs( - *$field, - direction, - node_operator, - edge_validator, - traverse_all, - ); - if matches!(result, DFSStatus::Stop) && !traverse_all { - return DFSStatus::Stop; - } + if matches!(edge_validator(self, *edge_idx), DFSStatus::Continue) { + let result = self.dfs( + edge.$field, + direction, + node_operator, + edge_validator, + traverse_all, + ); + if matches!(result, DFSStatus::Stop) && !traverse_all { + return DFSStatus::Stop; } } } }; } - if matches!(node_operator(now), DFSStatus::Continue) { + if matches!(node_operator(self, now), DFSStatus::Continue) { match direction { Direction::Upside => { traverse!(in_edges, src); @@ -452,10 +446,7 @@ impl Graph { pub fn get_upside_idx(&self, node_idx: Local, order: usize) -> Option { if let Some(edge_idx) = self.nodes[node_idx].in_edges.get(order) { - match self.edges[*edge_idx] { - GraphEdge::NodeEdge { src, .. } => Some(src), - GraphEdge::ConstEdge { .. } => None, - } + Some(self.edges[*edge_idx].src) } else { None } @@ -463,10 +454,7 @@ impl Graph { pub fn get_downside_idx(&self, node_idx: Local, order: usize) -> Option { if let Some(edge_idx) = self.nodes[node_idx].out_edges.get(order) { - match self.edges[*edge_idx] { - GraphEdge::NodeEdge { dst, .. } => Some(dst), - GraphEdge::ConstEdge { .. } => None, - } + Some(self.edges[*edge_idx].dst) } else { None } @@ -474,8 +462,8 @@ impl Graph { } impl Graph { - pub fn equivalent_edge_validator(op: &EdgeOp) -> DFSStatus { - match op { + pub fn equivalent_edge_validator(graph: &Graph, idx: EdgeIdx) -> DFSStatus { + match graph.edges[idx].op { EdgeOp::Copy | EdgeOp::Move | EdgeOp::Mut | EdgeOp::Immut => DFSStatus::Continue, EdgeOp::Nop | EdgeOp::Const @@ -488,7 +476,7 @@ impl Graph { } } - pub fn always_true_edge_validator(_: &EdgeOp) -> DFSStatus { + pub fn always_true_edge_validator(_: &Graph, _: EdgeIdx) -> DFSStatus { DFSStatus::Continue } } diff --git a/rap/src/analysis/opt/checking/bounds_checking/bounds_len.rs b/rap/src/analysis/opt/checking/bounds_checking/bounds_len.rs index 08ef29e..dd9fbca 100644 --- a/rap/src/analysis/opt/checking/bounds_checking/bounds_len.rs +++ b/rap/src/analysis/opt/checking/bounds_checking/bounds_len.rs @@ -4,10 +4,9 @@ use rustc_middle::mir::Local; use rustc_middle::ty::TyCtxt; use crate::analysis::core::dataflow::graph::{ - AggKind, DFSStatus, Direction, Graph, GraphEdge, GraphNode, NodeOp, + AggKind, DFSStatus, Direction, Graph, GraphNode, NodeOp, }; use crate::analysis::utils::def_path::DefPath; -use crate::rap_debug; use crate::utils::log::{ relative_pos_range, span_to_filename, span_to_line_number, span_to_source_code, }; @@ -61,11 +60,7 @@ fn extract_upperbound_node_if_ops_range(graph: &Graph, node: &GraphNode) -> Opti if let NodeOp::Aggregate(AggKind::Adt(def_id)) = node.op { if def_id == target_def_id { let upperbound_edge = &graph.edges[node.in_edges[1]]; // the second field - if let GraphEdge::NodeEdge { src, .. } = upperbound_edge { - return Some(*src); - } else { - rap_debug!("The upperbound edge of Agg node is not a NodeEdge"); - } + return Some(upperbound_edge.src); } } None @@ -76,7 +71,7 @@ fn find_upside_vec_len_node(graph: &Graph, node_idx: Local) -> Option { let def_paths = &DEFPATHS.get().unwrap(); let target_def_id = def_paths.vec_len.last_def_id(); // Warning: may traverse all upside nodes and the new result will overwrite on the previous result - let mut node_operator = |idx: Local| -> DFSStatus { + let mut node_operator = |graph: &Graph, idx: Local| -> DFSStatus { let node = &graph.nodes[idx]; if let NodeOp::Call(def_id) = node.op { if def_id == target_def_id { @@ -100,7 +95,7 @@ fn find_downside_index_node(graph: &Graph, node_idx: Local) -> Vec { let mut index_node_idxs: Vec = Vec::new(); let def_paths = &DEFPATHS.get().unwrap(); // Warning: traverse all downside nodes - let mut node_operator = |idx: Local| -> DFSStatus { + let mut node_operator = |graph: &Graph, idx: Local| -> DFSStatus { let node = &graph.nodes[idx]; if let NodeOp::Call(def_id) = node.op { if def_id == def_paths.ops_index.last_def_id() diff --git a/rap/src/analysis/opt/memory_cloning/hash_key_cloning.rs b/rap/src/analysis/opt/memory_cloning/hash_key_cloning.rs index 277b8cc..06f1bef 100644 --- a/rap/src/analysis/opt/memory_cloning/hash_key_cloning.rs +++ b/rap/src/analysis/opt/memory_cloning/hash_key_cloning.rs @@ -5,7 +5,6 @@ use once_cell::sync::OnceCell; use crate::analysis::core::dataflow::graph::DFSStatus; use crate::analysis::core::dataflow::graph::Direction; -use crate::analysis::core::dataflow::graph::GraphEdge::NodeEdge; use rustc_hir::{intravisit, Expr, ExprKind}; use rustc_middle::mir::Local; use rustc_middle::ty::{TyCtxt, TyKind, TypeckResults}; @@ -72,26 +71,23 @@ fn find_first_param_upside_clone(graph: &Graph, node: &GraphNode) -> Option DFSStatus { - let node = &graph.nodes[idx]; - if let NodeOp::Call(def_id) = node.op { - if def_id == target_def_id { - clone_node_idx = Some(idx); - return DFSStatus::Stop; - } + let mut node_operator = |graph: &Graph, idx: Local| -> DFSStatus { + let node = &graph.nodes[idx]; + if let NodeOp::Call(def_id) = node.op { + if def_id == target_def_id { + clone_node_idx = Some(idx); + return DFSStatus::Stop; } - DFSStatus::Continue - }; - graph.dfs( - *src, - Direction::Upside, - &mut node_operator, - &mut Graph::equivalent_edge_validator, - false, - ); - } + } + DFSStatus::Continue + }; + graph.dfs( + graph.edges[node.in_edges[1]].src, // the first param is self, so we use 1 + Direction::Upside, + &mut node_operator, + &mut Graph::equivalent_edge_validator, + false, + ); clone_node_idx } @@ -100,26 +96,23 @@ fn find_hashset_new_node(graph: &Graph, node: &GraphNode) -> Option { let mut new_node_idx = None; let def_paths = &DEFPATHS.get().unwrap(); let target_def_id = def_paths.hashset_new.last_def_id(); - if let NodeEdge { src, .. } = &graph.edges[node.in_edges[0]] { - // the first param is self - let mut node_operator = |idx: Local| -> DFSStatus { - let node = &graph.nodes[idx]; - if let NodeOp::Call(def_id) = node.op { - if def_id == target_def_id { - new_node_idx = Some(idx); - return DFSStatus::Stop; - } + let mut node_operator = |graph: &Graph, idx: Local| -> DFSStatus { + let node = &graph.nodes[idx]; + if let NodeOp::Call(def_id) = node.op { + if def_id == target_def_id { + new_node_idx = Some(idx); + return DFSStatus::Stop; } - DFSStatus::Continue - }; - graph.dfs( - *src, - Direction::Upside, - &mut node_operator, - &mut Graph::equivalent_edge_validator, - false, - ); - } + } + DFSStatus::Continue + }; + graph.dfs( + graph.edges[node.in_edges[0]].src, // the first param is self + Direction::Upside, + &mut node_operator, + &mut Graph::equivalent_edge_validator, + false, + ); new_node_idx }