Skip to main content

rapx/analysis/alias/default/
alias.rs

1use 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    /// Resolve a MIR place to its value index, creating field nodes lazily if needed.
12    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}