rapx/analysis/alias/default/
graph.rs1use super::MopFnAliasPairs;
2use crate::{
3 analysis::path::{
4 PathTree,
5 graph::{PathEnumerator, PathGraph},
6 },
7 analysis::points_to::graph::PtsGraph,
8 compat::FxHashMap,
9 graphs::cfg::CfgBlock,
10 utils::source::get_fn_name,
11};
12use rustc_middle::mir::Terminator;
13use rustc_middle::ty::TyCtxt;
14use rustc_span::{Span, def_id::DefId};
15use std::fmt;
16
17use super::value::Value;
18
19pub struct AliasGraph<'tcx> {
20 pub path_graph: PathGraph<'tcx>,
21 pub visit_times: usize,
22
23 pub values: Vec<Value>,
26
27 pub pts_graph: PtsGraph,
29
30 pub move_sources: FxHashMap<usize, usize>,
33
34 pub ret_alias: MopFnAliasPairs,
35 pub arg_size: usize,
36 pub span: Span,
37}
38
39impl<'tcx> AliasGraph<'tcx> {
40 pub fn new(tcx: TyCtxt<'tcx>, def_id: DefId) -> AliasGraph<'tcx> {
41 let fn_name = get_fn_name(tcx, def_id);
42 rap_debug!("New an AliasGraph for: {:?}", fn_name);
43 let path_graph = PathGraph::new(tcx, def_id);
44 Self::from_path_graph(tcx, def_id, path_graph)
45 }
46
47 pub fn from_path_graph(
48 tcx: TyCtxt<'tcx>,
49 def_id: DefId,
50 path_graph: PathGraph<'tcx>,
51 ) -> AliasGraph<'tcx> {
52 let body = tcx.optimized_mir(def_id);
53 let locals = &body.local_decls;
54 let arg_size = body.arg_count;
55 let mut values = Vec::<Value>::new();
56 for local in locals.indices() {
57 let node = Value::new(local.as_usize(), local.as_usize());
58 values.push(node);
59 }
60 AliasGraph {
61 path_graph,
62 visit_times: 0,
63 values,
64 pts_graph: PtsGraph::new(),
65 move_sources: FxHashMap::default(),
66 ret_alias: MopFnAliasPairs::new(arg_size),
67 arg_size,
68 span: body.span,
69 }
70 }
71
72 pub fn def_id(&self) -> DefId {
73 self.path_graph.def_id()
74 }
75
76 pub fn tcx(&self) -> TyCtxt<'tcx> {
77 self.path_graph.tcx()
78 }
79
80 pub fn arg_size(&self) -> usize {
81 self.arg_size
82 }
83
84 pub fn span(&self) -> Span {
85 self.span
86 }
87
88 pub fn cfg_block(&self, index: usize) -> &CfgBlock {
89 self.path_graph.cfg_block(index)
90 }
91
92 pub fn terminator(&self, index: usize) -> Option<&Terminator<'tcx>> {
93 self.path_graph.terminator(index)
94 }
95
96 pub fn enumerate_paths(&self) -> PathTree {
97 let mut enumerator = PathEnumerator::new(&self.path_graph);
98 enumerator.enumerate_paths()
99 }
100
101 pub fn visit_times(&self) -> usize {
102 self.visit_times
103 }
104
105 pub fn increment_visit_times(&mut self) -> usize {
106 self.visit_times += 1;
107 self.visit_times
108 }
109
110 pub fn value_to_slot_idx(&self, value_idx: usize) -> Option<usize> {
113 self.values.get(value_idx).and_then(|v| v.slot_idx)
114 }
115
116 pub fn get_alias_set(&self, e: usize) -> Option<Vec<usize>> {
117 let e_slot = self.value_to_slot_idx(e)?;
118 let mut result = vec![e];
119 for i in 0..self.values.len() {
120 if i == e {
121 continue;
122 }
123 if let Some(i_slot) = self.value_to_slot_idx(i) {
124 if self.pts_graph.may_alias(e_slot, i_slot) {
125 result.push(i);
126 }
127 }
128 }
129 if result.len() > 1 {
130 Some(result)
131 } else {
132 None
133 }
134 }
135
136 pub fn value_may_drop(&self, value_idx: usize) -> bool {
139 self.value_to_slot_idx(value_idx)
140 .map(|s| self.pts_graph.may_drop(s))
141 .unwrap_or(false)
142 }
143
144 pub fn value_is_ptr(&self, value_idx: usize) -> bool {
145 self.value_to_slot_idx(value_idx)
146 .map(|si| self.pts_graph.slot_is_ptr(si))
147 .unwrap_or(false)
148 }
149
150}
151
152impl<'tcx> std::fmt::Display for AliasGraph<'tcx> {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 writeln!(f, "AliasGraph {{")?;
155 writeln!(f, " def_id: {:?}", self.def_id())?;
156 writeln!(f, " values: {:?}", self.values)?;
157 writeln!(f, " cfg_blocks: {:?}", self.path_graph.cfg.blocks)?;
158 writeln!(f, " disc_info: {:?}", self.path_graph.disc_info)?;
159 write!(f, "}}")
160 }
161}