Skip to main content

rapx/analysis/alias/default/
alias.rs

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