Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change API definition in dataflow graph #82

Merged
merged 2 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 15 additions & 41 deletions rap/src/analysis/core/dataflow/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand All @@ -81,6 +47,14 @@ impl GraphNode {
write!(attr, "label=\"<f0> {:?}\" ", local).unwrap();
}
}
NodeOp::Const(ref name) => {
write!(
attr,
"label=\"<f0> {}\" style=dashed ",
escaped_string(name.clone())
)
.unwrap();
}
NodeOp::Call(def_id) => {
let func_name = tcx.def_path_str(def_id);
if is_marker {
Expand Down
80 changes: 34 additions & 46 deletions rap/src/analysis/core/dataflow/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -117,15 +110,18 @@ 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
}

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
}
Expand Down Expand Up @@ -307,8 +303,8 @@ impl Graph {
pub fn collect_equivalent_locals(&self, local: Local) -> HashSet<Local> {
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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -452,30 +446,24 @@ impl Graph {

pub fn get_upside_idx(&self, node_idx: Local, order: usize) -> Option<Local> {
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
}
}

pub fn get_downside_idx(&self, node_idx: Local, order: usize) -> Option<Local> {
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
}
}
}

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
Expand All @@ -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
}
}
Expand Down
13 changes: 4 additions & 9 deletions rap/src/analysis/opt/checking/bounds_checking/bounds_len.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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
Expand All @@ -76,7 +71,7 @@ fn find_upside_vec_len_node(graph: &Graph, node_idx: Local) -> Option<Local> {
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 {
Expand All @@ -100,7 +95,7 @@ fn find_downside_index_node(graph: &Graph, node_idx: Local) -> Vec<Local> {
let mut index_node_idxs: Vec<Local> = 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()
Expand Down
71 changes: 32 additions & 39 deletions rap/src/analysis/opt/memory_cloning/hash_key_cloning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -72,26 +71,23 @@ fn find_first_param_upside_clone(graph: &Graph, node: &GraphNode) -> Option<Loca
let mut clone_node_idx = None;
let def_paths = &DEFPATHS.get().unwrap();
let target_def_id = def_paths.clone.last_def_id();
if let NodeEdge { src, .. } = &graph.edges[node.in_edges[1]] {
// the first param is self, so we use 1
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 {
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
}

Expand All @@ -100,26 +96,23 @@ fn find_hashset_new_node(graph: &Graph, node: &GraphNode) -> Option<Local> {
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
}

Expand Down