rapx/analysis/core/alias_analysis/mop/
alias.rs1use super::graph::*;
2use super::types::*;
3use crate::{
4 analysis::{
5 core::alias_analysis::mop::{FnMap, MopAAFact},
6 utils::intrinsic_id::*,
7 },
8 rap_debug,
9};
10use rustc_hir::def_id::DefId;
11use rustc_middle::{
12 mir::{Operand, Place, ProjectionElem, TerminatorKind},
13 ty,
14};
15use std::collections::HashSet;
16
17impl<'tcx> MopGraph<'tcx> {
18 pub fn alias_bb(&mut self, bb_index: usize) {
20 for stmt in self.blocks[bb_index].const_value.clone() {
21 self.constant.insert(stmt.0, stmt.1);
22 }
23 let cur_block = self.blocks[bb_index].clone();
24 for assign in cur_block.assignments {
25 let mut lv_aliaset_idx = self.projection(false, assign.lv);
26 let rv_aliaset_idx = self.projection(true, assign.rv);
27 rap_debug!("{:?} = {:?}", lv_aliaset_idx, rv_aliaset_idx);
28 match assign.atype {
29 AssignType::Variant => {
30 self.alias_set[lv_aliaset_idx] = rv_aliaset_idx;
31 continue;
32 }
33 AssignType::InitBox => {
34 lv_aliaset_idx = *self.values[lv_aliaset_idx].fields.get(&0).unwrap();
35 }
36 _ => {} }
38 if self.values[lv_aliaset_idx].local != self.values[rv_aliaset_idx].local {
39 self.merge_alias(lv_aliaset_idx, rv_aliaset_idx, 0);
40 }
41 }
42 }
43
44 pub fn alias_bbcall(
46 &mut self,
47 bb_index: usize,
48 fn_map: &mut FnMap,
49 recursion_set: &mut HashSet<DefId>,
50 ) {
51 let cur_block = self.blocks[bb_index].clone();
52 for call in cur_block.calls {
53 if let TerminatorKind::Call {
54 func: Operand::Constant(ref constant),
55 ref args,
56 ref destination,
57 target: _,
58 unwind: _,
59 call_source: _,
60 fn_span: _,
61 } = call.kind
62 {
63 let lv = self.projection(false, *destination);
64 let mut merge_vec = Vec::new();
65 merge_vec.push(lv);
66 let mut may_drop_flag = 0;
67 if self.values[lv].may_drop {
68 may_drop_flag += 1;
69 }
70 for arg in args {
71 match arg.node {
72 Operand::Copy(ref p) => {
73 let rv = self.projection(true, *p);
74 merge_vec.push(rv);
75 if self.values[rv].may_drop {
76 may_drop_flag += 1;
77 }
78 }
79 Operand::Move(ref p) => {
80 let rv = self.projection(true, *p);
81 merge_vec.push(rv);
82 if self.values[rv].may_drop {
83 may_drop_flag += 1;
84 }
85 }
86 Operand::Constant(_) => {
87 merge_vec.push(0);
88 }
89 }
90 }
91 if let ty::FnDef(ref target_id, _) = constant.const_.ty().kind() {
92 if may_drop_flag > 0 {
94 if self.tcx.is_mir_available(*target_id) {
95 rap_debug!("target_id {:?}", target_id);
96 if fn_map.contains_key(target_id) {
97 let assignments = fn_map.get(target_id).unwrap();
98 for assign in assignments.aliases().iter() {
99 if !assign.valuable() {
100 continue;
101 }
102 self.merge(assign, &merge_vec);
103 }
104 } else {
105 if recursion_set.contains(target_id) {
107 continue;
108 }
109 recursion_set.insert(*target_id);
110 let mut mop_graph = MopGraph::new(self.tcx, *target_id);
111 mop_graph.solve_scc();
112 mop_graph.check(0, fn_map, recursion_set);
113 let ret_alias = mop_graph.ret_alias.clone();
114 for assign in ret_alias.aliases().iter() {
115 if !assign.valuable() {
116 continue;
117 }
118 self.merge(assign, &merge_vec);
119 }
120 fn_map.insert(*target_id, ret_alias);
121 recursion_set.remove(target_id);
122 }
123 } else if self.values[lv].may_drop {
124 if target_id.index.as_usize() == CALL_MUT {
125 continue;
126 }
127
128 let mut right_set = Vec::new();
129 for rv in &merge_vec {
130 if self.values[*rv].may_drop
131 && lv != *rv
132 && self.values[lv].is_ptr()
133 {
134 right_set.push(*rv);
135 }
136 }
137 if right_set.len() == 1 {
138 self.merge_alias(lv, right_set[0], 0);
139 }
140 }
141 }
142 }
143 }
144 }
145 }
146
147 pub fn projection(&mut self, is_right: bool, place: Place<'tcx>) -> usize {
154 let mut local = place.local.as_usize();
155 let mut proj_id: usize = local;
156 for proj in place.projection {
157 let new_id = self.values.len();
158 match proj {
159 ProjectionElem::Deref => {
160 proj_id = self.values[proj_id].index;
161 }
162 ProjectionElem::Field(field, ty) => {
166 if is_right && self.values[proj_id].index != proj_id {
167 proj_id = self.values[proj_id].index;
168 local = self.values[proj_id].local;
169 }
170 let field_idx = field.as_usize();
171 if let std::collections::hash_map::Entry::Vacant(e) =
172 self.values[proj_id].fields.entry(field_idx)
173 {
174 let ty_env = ty::TypingEnv::post_analysis(self.tcx, self.def_id);
175 let need_drop = ty.needs_drop(self.tcx, ty_env);
176 let may_drop = !is_not_drop(self.tcx, ty);
177 let mut node =
178 ValueNode::new(new_id, local, need_drop, need_drop || may_drop);
179 node.kind = kind(ty);
180 node.field_id = field_idx;
181 e.insert(node.index);
182 self.alias_set.push(self.values.len());
183 self.values.push(node);
184 }
185 proj_id = *self.values[proj_id].fields.get(&field_idx).unwrap();
186 }
187 _ => {}
188 }
189 }
190 proj_id
191 }
192
193 pub fn merge_alias(&mut self, lv: usize, rv: usize, depth: usize) {
195 rap_debug!("Alias set before merge: {:?}", self.alias_set);
196 self.union_merge(lv, rv);
198 rap_debug!(
200 "update the alias set for lv:{} rv:{} set:{:?}",
201 lv,
202 rv,
203 self.alias_set
204 );
205
206 let max_field_depth = match std::env::var_os("MOP") {
207 Some(val) if val == "0" => 10,
208 Some(val) if val == "1" => 20,
209 Some(val) if val == "2" => 30,
210 Some(val) if val == "3" => 50,
211 _ => 15,
212 };
213
214 if depth > max_field_depth {
215 return;
216 }
217
218 for field in self.values[rv].fields.clone().into_iter() {
219 if !self.values[lv].fields.contains_key(&field.0) {
220 let mut node = ValueNode::new(
221 self.values.len(),
222 self.values[lv].local,
223 self.values[field.1].need_drop,
224 self.values[field.1].may_drop,
225 );
226 node.kind = self.values[field.1].kind;
227 node.field_id = field.0;
228 self.values[lv].fields.insert(field.0, node.index);
229 self.alias_set.push(self.values.len());
230 self.values.push(node);
231 }
232 let lv_field = *(self.values[lv].fields.get(&field.0).unwrap());
233 self.merge_alias(lv_field, field.1, depth + 1);
234 }
235 }
236
237 pub fn merge(&mut self, ret_alias: &MopAAFact, arg_vec: &[usize]) {
239 rap_debug!("{:?}", ret_alias);
240 if ret_alias.lhs_no() >= arg_vec.len() || ret_alias.rhs_no() >= arg_vec.len() {
241 rap_debug!("Vector error!");
242 return;
243 }
244 let left_init = arg_vec[ret_alias.lhs_no()];
245 let mut right_init = arg_vec[ret_alias.rhs_no()];
246 let mut lv = left_init;
247 let mut rv = right_init;
248 for index in ret_alias.lhs_fields().iter() {
249 if !self.values[lv].fields.contains_key(index) {
250 let need_drop = ret_alias.lhs_need_drop;
251 let may_drop = ret_alias.lhs_may_drop;
252 let mut node = ValueNode::new(self.values.len(), left_init, need_drop, may_drop);
253 node.kind = TyKind::RawPtr;
254 node.field_id = *index;
255 self.values[lv].fields.insert(*index, node.index);
256 self.alias_set.push(self.values.len());
257 self.values.push(node);
258 }
259 lv = *self.values[lv].fields.get(index).unwrap();
260 }
261 for index in ret_alias.rhs_fields().iter() {
262 if self.union_is_same(rv, self.alias_set[rv]) {
263 right_init = self.values[rv].local;
264 }
265 if !self.values[rv].fields.contains_key(index) {
266 let need_drop = ret_alias.rhs_need_drop;
267 let may_drop = ret_alias.rhs_may_drop;
268 let mut node = ValueNode::new(self.values.len(), right_init, need_drop, may_drop);
269 node.kind = TyKind::RawPtr;
270 node.field_id = *index;
271 self.values[rv].fields.insert(*index, node.index);
272 self.alias_set.push(self.values.len());
273 self.values.push(node);
274 }
275 rv = *self.values[rv].fields.get(index).unwrap();
276 }
277 self.merge_alias(lv, rv, 0);
278 }
279
280 pub fn merge_results(&mut self, results_nodes: Vec<ValueNode>) {
282 for node in results_nodes.iter() {
283 if node.local <= self.arg_size
284 && (self.union_is_same(node.index, self.alias_set[node.index])
285 || self.alias_set[node.index] != node.index)
286 {
287 if self.values.len() == 1 {
288 return;
289 }
290 let f_node: Vec<usize> = results_nodes.iter().map(|v| v.father).collect();
291
292 for idx in 1..self.values.len() {
293 if !self.union_is_same(idx, node.index) {
294 continue;
295 }
296
297 let mut replace = None;
298 if results_nodes[idx].local > self.arg_size {
299 for (i, &fidx) in f_node.iter().enumerate() {
300 if i != idx && i != node.index && fidx == f_node[idx] {
301 for (j, v) in results_nodes.iter().enumerate() {
302 if j != idx
303 && j != node.index
304 && self.union_is_same(j, fidx)
305 && v.local <= self.arg_size
306 {
307 replace = Some(&results_nodes[j]);
308 }
309 }
310 }
311 }
312 }
313
314 if (results_nodes[idx].local <= self.arg_size || replace.is_some())
315 && idx != node.index
316 && node.local != results_nodes[idx].local
317 {
318 let left_node;
319 let right_node;
320 match results_nodes[idx].local {
321 0 => {
322 left_node = match replace {
323 Some(replace_node) => replace_node,
324 None => &results_nodes[idx],
325 };
326 right_node = node;
327 }
328 _ => {
329 left_node = node;
330 right_node = match replace {
331 Some(replace_node) => replace_node,
332 None => &results_nodes[idx],
333 };
334 }
335 }
336 let mut new_alias = MopAAFact::new(
337 left_node.local,
338 left_node.may_drop,
339 left_node.need_drop,
340 right_node.local,
341 right_node.may_drop,
342 right_node.need_drop,
343 );
344 new_alias.fact.lhs_fields = self.get_field_seq(left_node);
345 new_alias.fact.rhs_fields = self.get_field_seq(right_node);
346 if new_alias.lhs_no() == 0 && new_alias.rhs_no() == 0 {
347 return;
348 }
349 self.ret_alias.add_alias(new_alias);
350 }
351 }
352 }
353 }
354 }
355
356 pub fn get_field_seq(&self, value: &ValueNode) -> Vec<usize> {
357 let mut field_id_seq = vec![];
358 let mut node_ref = value;
359 while node_ref.field_id != usize::MAX {
360 field_id_seq.push(node_ref.field_id);
361 node_ref = &self.values[value.father];
362 }
363 field_id_seq
364 }
365
366 #[inline]
367 pub fn union_find(&mut self, e: usize) -> usize {
368 let mut r = e;
369 while self.alias_set[r] != r {
370 r = self.alias_set[r];
371 }
372 r
373 }
374
375 #[inline]
376 pub fn union_merge(&mut self, e1: usize, e2: usize) {
377 let f1 = self.union_find(e1);
378 let f2 = self.union_find(e2);
379
380 if f1 < f2 {
381 self.alias_set[f2] = f1;
382 }
383 if f1 > f2 {
384 self.alias_set[f1] = f2;
385 }
386
387 for member in 0..self.alias_set.len() {
388 self.alias_set[member] = self.union_find(self.alias_set[member]);
389 }
390 }
391
392 #[inline]
393 pub fn union_is_same(&mut self, e1: usize, e2: usize) -> bool {
394 let f1 = self.union_find(e1);
395 let f2 = self.union_find(e2);
396 f1 == f2
397 }
398}