rapx/analysis/alias/default/
alias.rs1use super::{MopFnAliasMap, graph::*};
2use crate::def_id::*;
3use rustc_hir::def_id::DefId;
4use rustc_middle::{
5 mir::{Operand, ProjectionElem, TerminatorKind},
6 ty::{self, TyCtxt, TypingEnv},
7};
8use std::collections::HashSet;
9
10impl<'tcx> AliasGraph<'tcx> {
11 pub fn projection(&mut self, place: rustc_middle::mir::Place<'tcx>) -> usize {
13 let local = place.local.as_usize();
14 let mut value_idx = local;
15 for proj in place.projection {
16 match proj {
17 ProjectionElem::Deref => {}
18 ProjectionElem::Field(field, ty) => {
19 let field_idx = field.as_usize();
20 if !self.values[value_idx].fields.contains_key(&field_idx) {
21 if self.values.len() < crate::analysis::points_to::graph::MAX_VALUES_PER_PATH {
22 let ty_env = TypingEnv::post_analysis(self.tcx(), self.def_id());
23 let need_drop = ty.needs_drop(self.tcx(), ty_env);
24 let may_drop = !super::types::is_not_drop(self.tcx(), ty);
25 let mut node = super::value::Value::new(
26 self.values.len(), local,
27 );
28 node.father = Some(super::value::FatherInfo::new(value_idx, field_idx));
29 let node_index = node.index;
30 self.values[value_idx].fields.insert(field_idx, node.index);
31 self.values.push(node);
32 let field_slot = crate::analysis::points_to::slot::Slot {
33 local,
34 fields: self.get_field_seq(node_index).into_iter().rev().collect(),
35 };
36 self.values[node_index].slot_idx = Some(self.pts_graph.ensure_slot(field_slot, may_drop, need_drop));
37 self.pts_graph.set_slot_kind(self.values[node_index].slot_idx.unwrap(), super::types::kind(ty));
38 } else { break; }
39 }
40 value_idx = *self.values[value_idx].fields.get(&field_idx).unwrap();
41 }
42 _ => {}
43 }
44 }
45 value_idx
46 }
47
48 pub fn call_target_of(&self, bb_index: usize) -> Option<DefId> {
49 let term = self.terminator(bb_index)?;
50 match &term.kind {
51 TerminatorKind::Call { func: Operand::Constant(c), .. } => match c.ty().kind() {
52 ty::FnDef(id, _) => Some(*id),
53 _ => None,
54 },
55 _ => None,
56 }
57 }
58
59 pub fn get_field_seq(&self, value_idx: usize) -> Vec<usize> {
60 let mut seq = vec![];
61 let mut cur = value_idx;
62 let mut iter = 0usize;
63 while let Some(ref father) = self.values[cur].father {
64 iter += 1;
65 if iter > 1000 { break; }
66 seq.push(father.field_id);
67 cur = father.father_value_id;
68 }
69 seq
70 }
71}
72
73pub fn is_no_alias_intrinsic(def_id: DefId) -> bool {
74 let v = [call_mut_opt(), clone_opt(), take_opt(), replace_opt()];
75 contains(&v, def_id)
76}
77
78pub fn ensure_fn_aliases_cached<'tcx>(
79 tcx: TyCtxt<'tcx>,
80 target_id: DefId,
81 fn_map: &mut MopFnAliasMap,
82 recursion_set: &mut HashSet<DefId>,
83) {
84 if fn_map.contains_key(&target_id) || recursion_set.contains(&target_id) {
85 return;
86 }
87 if !tcx.is_mir_available(target_id) {
88 return;
89 }
90 recursion_set.insert(target_id);
91 let mut alias_graph = AliasGraph::new(tcx, target_id);
92 alias_graph.path_graph.find_scc();
93 alias_graph.process_function_paths(fn_map, recursion_set);
94 let ret_alias = alias_graph.ret_alias.clone();
95 rap_debug!("Find aliases of {:?}: {:?}", target_id, ret_alias);
96 fn_map.insert(target_id, ret_alias);
97 recursion_set.remove(&target_id);
98}