rapx/analysis/core/alias_analysis/default/
alias.rs1use super::{MopAliasPair, MopFnAliasMap, block::Term, graph::*, types::*, value::*};
2use crate::{analysis::graphs::scc::Scc, def_id::*};
3use rustc_data_structures::fx::FxHashSet;
4use rustc_hir::def_id::DefId;
5use rustc_middle::{
6 mir::{Local, Operand, Place, ProjectionElem, TerminatorKind},
7 ty,
8};
9use std::collections::HashSet;
10
11impl<'tcx> MopGraph<'tcx> {
12 pub fn alias_bb(&mut self, bb_index: usize) {
14 for constant in self.blocks[bb_index].const_value.clone() {
15 self.constants.insert(constant.local, constant.value);
16 }
17 let cur_block = self.blocks[bb_index].clone();
18 for assign in cur_block.assignments {
19 rap_debug!("assign: {:?}", assign);
20 let lv_idx = self.projection(assign.lv);
21 let rv_idx = self.projection(assign.rv);
22
23 self.assign_alias(lv_idx, rv_idx);
24 rap_debug!("Alias sets: {:?}", self.alias_sets)
25 }
26 }
27
28 pub fn alias_bbcall(
30 &mut self,
31 bb_index: usize,
32 fn_map: &mut MopFnAliasMap,
33 recursion_set: &mut HashSet<DefId>,
34 ) {
35 let cur_block = self.blocks[bb_index].clone();
36 if let Term::Call(call) | Term::Drop(call) = cur_block.terminator {
37 if let TerminatorKind::Call {
38 func: Operand::Constant(ref constant),
39 ref args,
40 ref destination,
41 target: _,
42 unwind: _,
43 call_source: _,
44 fn_span: _,
45 } = call.kind
46 {
47 let lv = self.projection(*destination);
48 let mut may_drop = false;
49 if self.values[lv].may_drop {
50 may_drop = true;
51 }
52
53 let mut merge_vec = Vec::new();
54 merge_vec.push(lv);
55
56 for arg in args {
57 match arg.node {
58 Operand::Copy(ref p) | Operand::Move(ref p) => {
59 let rv = self.projection(*p);
60 merge_vec.push(rv);
61 if self.values[rv].may_drop {
62 may_drop = true;
63 }
64 }
65 Operand::Constant(_) => {
67 merge_vec.push(0);
68 }
69 }
70 }
71 if let &ty::FnDef(target_id, _) = constant.const_.ty().kind() {
72 if may_drop == false {
73 return;
74 }
75 if is_no_alias_intrinsic(target_id) {
77 return;
78 }
79 if !self.tcx.is_mir_available(target_id) {
80 return;
81 }
82 rap_debug!("Sync aliases for function call: {:?}", target_id);
83 let fn_aliases = if fn_map.contains_key(&target_id) {
84 rap_debug!("Aliases existed");
85 fn_map.get(&target_id).unwrap()
86 } else {
87 if recursion_set.contains(&target_id) {
89 return;
90 }
91 recursion_set.insert(target_id);
92 let mut mop_graph = MopGraph::new(self.tcx, target_id);
93 mop_graph.find_scc();
94 mop_graph.check(0, fn_map, recursion_set);
95 let ret_alias = mop_graph.ret_alias.clone();
96 rap_debug!("Find aliases of {:?}: {:?}", target_id, ret_alias);
97 fn_map.insert(target_id, ret_alias);
98 recursion_set.remove(&target_id);
99 fn_map.get(&target_id).unwrap()
100 };
101 if fn_aliases.aliases().is_empty() {
102 if let Some(l_set_idx) = self.find_alias_set(lv) {
103 self.alias_sets[l_set_idx].remove(&lv);
104 }
105 }
106 for alias in fn_aliases.aliases().iter() {
107 if !alias.valuable() {
108 continue;
109 }
110 self.handle_fn_alias(alias, &merge_vec);
111 rap_debug!("{:?}", self.alias_sets);
112 }
113 } else if self.values[lv].may_drop {
114 for rv in &merge_vec {
115 if self.values[*rv].may_drop && lv != *rv && self.values[lv].is_ptr() {
116 self.merge_alias(lv, *rv);
120 }
121 }
122 }
123 }
124 }
125 }
126
127 pub fn projection(&mut self, place: Place<'tcx>) -> usize {
133 let local = place.local.as_usize();
134 rap_debug!("projection: place = {:?}, local = {:?}", place, local);
135 let mut value_idx = local;
136 for proj in place.projection {
141 rap_debug!("proj: {:?}", proj);
142 let new_value_idx = self.values.len();
143 match proj {
144 ProjectionElem::Deref => {}
145 ProjectionElem::Field(field, ty) => {
146 let field_idx = field.as_usize();
147 if !self.values[value_idx].fields.contains_key(&field_idx) {
149 let ty_env = ty::TypingEnv::post_analysis(self.tcx, self.def_id);
150 let need_drop = ty.needs_drop(self.tcx, ty_env);
151 let may_drop = !is_not_drop(self.tcx, ty);
152 let mut node =
153 Value::new(new_value_idx, local, need_drop, need_drop || may_drop);
154 node.kind = kind(ty);
155 node.father = Some(FatherInfo::new(value_idx, field_idx));
156 self.values[value_idx].fields.insert(field_idx, node.index);
157 self.values.push(node);
158 }
159 value_idx = *self.values[value_idx].fields.get(&field_idx).unwrap();
160 }
161 _ => {}
162 }
163 }
164 value_idx
165 }
166
167 pub fn assign_alias(&mut self, lv_idx: usize, rv_idx: usize) {
171 rap_debug!("assign_alias: lv = {:?}. rv = {:?}", lv_idx, rv_idx);
172
173 let r_set_idx = if let Some(idx) = self.find_alias_set(rv_idx) {
174 idx
175 } else {
176 self.alias_sets
177 .push([rv_idx].into_iter().collect::<FxHashSet<usize>>());
178 self.alias_sets.len() - 1
179 };
180
181 if let Some(l_set_idx) = self.find_alias_set(lv_idx) {
182 if l_set_idx == r_set_idx {
183 return;
184 }
185 self.alias_sets[l_set_idx].remove(&lv_idx);
186 }
187 let new_l_set_idx = r_set_idx;
188 self.alias_sets[new_l_set_idx].insert(lv_idx);
189
190 if self.values[lv_idx].fields.len() > 0 || self.values[rv_idx].fields.len() > 0 {
191 self.sync_field_alias(lv_idx, rv_idx, 0, true);
192 }
193 if self.values[rv_idx].father != None {
194 self.sync_father_alias(lv_idx, rv_idx, new_l_set_idx);
195 }
196 }
197
198 pub fn sync_field_alias(&mut self, lv: usize, rv: usize, depth: usize, clear_left: bool) {
204 rap_debug!("sync field aliases for lv:{} rv:{}", lv, rv);
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 if clear_left {
220 for lv_field in self.values[lv].fields.clone().into_iter() {
221 if let Some(alias_set_idx) = self.find_alias_set(lv_field.1) {
222 self.alias_sets[alias_set_idx].remove(&lv_field.1);
223 }
224 }
225 }
226 for rv_field in self.values[rv].fields.clone().into_iter() {
227 rap_debug!("rv_field: {:?}", rv_field);
228 if !self.values[lv].fields.contains_key(&rv_field.0) {
229 let mut node = Value::new(
230 self.values.len(),
231 self.values[lv].local,
232 self.values[rv_field.1].need_drop,
233 self.values[rv_field.1].may_drop,
234 );
235 node.kind = self.values[rv_field.1].kind;
236 node.father = Some(FatherInfo::new(lv, rv_field.0));
237 self.values[lv].fields.insert(rv_field.0, node.index);
238 self.values.push(node);
239 }
240 let lv_field_value_idx = *(self.values[lv].fields.get(&rv_field.0).unwrap());
241
242 rap_debug!(
243 "alias_set_id of rv_field {:?}",
244 self.find_alias_set(rv_field.1)
245 );
246 if let Some(alias_set_idx) = self.find_alias_set(rv_field.1) {
247 self.alias_sets[alias_set_idx].insert(lv_field_value_idx);
248 }
249 rap_debug!("alias sets: {:?}", self.alias_sets);
250 self.sync_field_alias(lv_field_value_idx, rv_field.1, depth + 1, true);
251 }
252 }
253
254 pub fn sync_father_alias(&mut self, lv: usize, rv: usize, lv_alias_set_idx: usize) {
260 rap_debug!("sync father aliases for lv:{} rv:{}", lv, rv);
261 let mut father_id = rv;
262 let mut father = self.values[father_id].father.clone();
263 while let Some(father_info) = father {
264 father_id = father_info.father_value_id;
265 let field_id = father_info.field_id;
266 let father_value = self.values[father_id].clone();
267 if let Some(alias_set_idx) = self.find_alias_set(father_id) {
268 for value_idx in self.alias_sets[alias_set_idx].clone() {
269 let field_value_idx = if self.values[value_idx].fields.contains_key(&field_id) {
271 *self.values[value_idx].fields.get(&field_id).unwrap()
272 } else {
273 let mut node = Value::new(
274 self.values.len(),
275 self.values[value_idx].local,
276 self.values[value_idx].need_drop,
277 self.values[value_idx].may_drop,
278 );
279 node.kind = self.values[value_idx].kind;
280 node.father = Some(FatherInfo::new(value_idx, field_id));
281 self.values.push(node.clone());
282 self.values[value_idx].fields.insert(field_id, node.index);
283 node.index
284 };
285 self.alias_sets[lv_alias_set_idx].insert(field_value_idx);
287 }
288 }
289 father = father_value.father;
290 }
291 }
292
293 pub fn handle_fn_alias(&mut self, fn_alias: &MopAliasPair, arg_vec: &[usize]) {
295 rap_debug!(
296 "merge aliases returned by function calls, args: {:?}",
297 arg_vec
298 );
299 rap_debug!("fn alias: {}", fn_alias);
300 if fn_alias.left_local() >= arg_vec.len() || fn_alias.right_local() >= arg_vec.len() {
301 return;
302 }
303
304 let mut lv = arg_vec[fn_alias.left_local()];
305 let mut rv = arg_vec[fn_alias.right_local()];
306 let left_local = self.values[lv].local;
307 let right_local = self.values[rv].local;
308
309 for index in fn_alias.lhs_fields().iter() {
310 if !self.values[lv].fields.contains_key(index) {
311 let need_drop = fn_alias.lhs_need_drop;
312 let may_drop = fn_alias.lhs_may_drop;
313 let mut node = Value::new(self.values.len(), left_local, need_drop, may_drop);
314 node.kind = ValueKind::RawPtr;
315 node.father = Some(FatherInfo::new(lv, *index));
316 self.values[lv].fields.insert(*index, node.index);
317 self.values.push(node);
318 }
319 lv = *self.values[lv].fields.get(index).unwrap();
320 }
321 for index in fn_alias.rhs_fields().iter() {
322 if !self.values[rv].fields.contains_key(index) {
323 let need_drop = fn_alias.rhs_need_drop;
324 let may_drop = fn_alias.rhs_may_drop;
325 let mut node = Value::new(self.values.len(), right_local, need_drop, may_drop);
326 node.kind = ValueKind::RawPtr;
327 node.father = Some(FatherInfo::new(rv, *index));
328 self.values[rv].fields.insert(*index, node.index);
329 self.values.push(node);
330 }
331 rv = *self.values[rv].fields.get(index).unwrap();
332 }
333 self.merge_alias(lv, rv);
336 }
337
338 pub fn get_field_seq(&self, value: &Value) -> Vec<usize> {
339 let mut field_id_seq = vec![];
340 let mut node_ref = value;
341 while let Some(father) = &node_ref.father {
342 field_id_seq.push(father.field_id);
343 node_ref = &self.values[father.father_value_id];
344 }
345 field_id_seq
346 }
347
348 fn is_valid_field(&self, local: usize, field_seq: &[usize]) -> bool {
351 let body = self.tcx.optimized_mir(self.def_id);
352 let mut ty = body.local_decls[Local::from_usize(local)].ty;
353 for &fidx in field_seq {
354 while let ty::TyKind::Ref(_, inner, _) | ty::TyKind::RawPtr(inner, _) = ty.kind() {
355 ty = *inner;
356 }
357 if let ty::Adt(def, _) = ty.kind() {
358 let field_count = def.all_fields().count();
359 if fidx >= field_count {
360 return false;
361 }
362 } else {
363 return false;
365 }
366 }
367 true
368 }
369
370 pub fn merge_results(&mut self) {
372 rap_debug!("merge results");
373 let f_node: Vec<Option<FatherInfo>> =
374 self.values.iter().map(|v| v.father.clone()).collect();
375 for node in self.values.iter() {
376 if node.local > self.arg_size {
377 continue;
378 }
379 for idx in 1..self.values.len() {
380 if !self.is_aliasing(idx, node.index) {
381 continue;
382 }
383
384 let mut replace = None;
385 if self.values[idx].local > self.arg_size {
386 for (i, fidx) in f_node.iter().enumerate() {
387 if let Some(father_info) = fidx {
388 if i != idx && i != node.index {
389 for (j, v) in self.values.iter().enumerate() {
391 if j != idx
392 && j != node.index
393 && self.is_aliasing(j, father_info.father_value_id)
394 && v.local <= self.arg_size
395 {
396 replace = Some(&self.values[j]);
397 }
398 }
399 }
400 }
401 }
402 }
403
404 if (self.values[idx].local <= self.arg_size || replace.is_some())
405 && idx != node.index
406 && node.local != self.values[idx].local
407 {
408 let left_node;
409 let right_node;
410 match self.values[idx].local {
411 0 => {
412 left_node = match replace {
413 Some(replace_node) => replace_node,
414 None => &self.values[idx],
415 };
416 right_node = node;
417 }
418 _ => {
419 left_node = node;
420 right_node = match replace {
421 Some(replace_node) => replace_node,
422 None => &self.values[idx],
423 };
424 }
425 }
426 let mut new_alias = MopAliasPair::new(
427 left_node.local,
428 left_node.may_drop,
429 left_node.need_drop,
430 right_node.local,
431 right_node.may_drop,
432 right_node.need_drop,
433 );
434 new_alias.fact.lhs_fields = self.get_field_seq(left_node);
435 new_alias.fact.rhs_fields = self.get_field_seq(right_node);
436 if new_alias.left_local() == new_alias.right_local() {
437 continue;
438 }
439 if !self.is_valid_field(left_node.local, &new_alias.fact.lhs_fields)
440 || !self.is_valid_field(right_node.local, &new_alias.fact.rhs_fields)
441 {
442 rap_debug!("new_alias with invalid field: {:?}", new_alias);
443 continue;
444 }
445 rap_debug!("new_alias: {:?}", new_alias);
446 self.ret_alias.add_alias(new_alias);
447 }
448 }
449 }
450 self.compress_aliases();
451 }
452
453 pub fn compress_aliases(&mut self) {
469 let mut truncated_facts = Vec::new();
471 for fact in self.ret_alias.alias_set.iter() {
472 let mut new_fact = fact.clone();
473 if !new_fact.fact.lhs_fields.is_empty() {
474 new_fact.fact.lhs_fields = vec![new_fact.fact.lhs_fields[0]];
475 }
476 if !new_fact.fact.rhs_fields.is_empty() {
477 new_fact.fact.rhs_fields = vec![new_fact.fact.rhs_fields[0]];
478 }
479 truncated_facts.push(new_fact);
480 }
481 self.ret_alias.alias_set.clear();
483 for fact in truncated_facts {
484 self.ret_alias.alias_set.insert(fact);
485 }
486
487 let aliases: Vec<MopAliasPair> = self.ret_alias.alias_set.iter().cloned().collect();
490 let n = aliases.len();
491 let mut to_remove: HashSet<MopAliasPair> = HashSet::new();
492
493 for i in 0..n {
494 for j in 0..n {
495 if i == j || to_remove.contains(&aliases[j]) {
496 continue;
497 }
498 let a = &aliases[i].fact;
499 let b = &aliases[j].fact;
500 if a.left_local() == b.left_local() && a.right_local() == b.right_local() {
502 if a.lhs_fields.len() <= b.lhs_fields.len()
503 && a.lhs_fields == b.lhs_fields[..a.lhs_fields.len()]
504 && a.rhs_fields.len() <= b.rhs_fields.len()
505 && a.rhs_fields == b.rhs_fields[..a.rhs_fields.len()]
506 && (a.lhs_fields.len() < b.lhs_fields.len() || a.rhs_fields.len() < b.rhs_fields.len())
508 {
509 to_remove.insert(aliases[j].clone());
510 }
511 }
512 }
513 }
514 for alias in to_remove {
515 self.ret_alias.alias_set.remove(&alias);
516 }
517 }
518
519 #[inline(always)]
520 pub fn find_alias_set(&self, e: usize) -> Option<usize> {
521 self.alias_sets.iter().position(|set| set.contains(&e))
522 }
523
524 #[inline(always)]
525 pub fn is_aliasing(&self, e1: usize, e2: usize) -> bool {
526 let s1 = self.find_alias_set(e1);
527 let s2 = self.find_alias_set(e2);
528 s1.is_some() && s1 == s2
529 }
530
531 pub fn merge_alias(&mut self, e1: usize, e2: usize) {
532 let mut s1 = self.find_alias_set(e1);
533 let mut s2 = self.find_alias_set(e2);
534
535 if s1.is_none() {
537 self.alias_sets
538 .push([e1].into_iter().collect::<FxHashSet<usize>>());
539 s1 = Some(self.alias_sets.len() - 1);
540 }
541
542 if s2.is_none() {
544 self.alias_sets
545 .push([e2].into_iter().collect::<FxHashSet<usize>>());
546 s2 = Some(self.alias_sets.len() - 1);
547 }
548
549 let idx1 = s1.unwrap();
551 let idx2 = s2.unwrap();
552
553 if idx1 == idx2 {
554 return;
555 }
556
557 let set2 = self.alias_sets.remove(idx2);
558 let idx1 = if idx2 < idx1 { idx1 - 1 } else { idx1 };
560 self.alias_sets[idx1].extend(set2);
561
562 if self.values[e1].fields.len() > 0 {
563 self.sync_field_alias(e2, e1, 0, false);
564 }
565 if self.values[e2].fields.len() > 0 {
566 self.sync_field_alias(e1, e2, 0, false);
567 }
568 if self.values[e1].father != None {
569 self.sync_father_alias(e2, e1, idx1);
570 }
571 if self.values[e2].father != None {
572 self.sync_father_alias(e1, e2, idx1);
573 }
574 }
575
576 #[inline(always)]
577 pub fn get_alias_set(&mut self, e: usize) -> Option<FxHashSet<usize>> {
578 if let Some(idx) = self.find_alias_set(e) {
579 Some(self.alias_sets[idx].clone())
580 } else {
581 None
582 }
583 }
584}
585
586pub fn is_no_alias_intrinsic(def_id: DefId) -> bool {
587 let v = [call_mut_opt(), clone_opt(), take_opt()];
588 contains(&v, def_id)
589}