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