rapx/analysis/core/alias_analysis/
default.rs

1pub mod alias;
2pub mod graph;
3pub mod mop;
4
5use super::{AAFact, AAResult, AliasAnalysis};
6use crate::{
7    analysis::{
8        utils::intrinsic_id::{
9            COPY_FROM, COPY_FROM_NONOVERLAPPING, COPY_TO, COPY_TO_NONOVERLAPPING,
10        },
11        Analysis,
12    },
13    rap_debug, rap_info, rap_trace,
14    utils::source::*,
15};
16use graph::MopGraph;
17use rustc_data_structures::fx::FxHashMap;
18use rustc_hir::def_id::DefId;
19use rustc_middle::ty::TyCtxt;
20use std::{collections::HashSet, convert::From};
21
22pub const VISIT_LIMIT: usize = 1000;
23
24pub struct DefaultAlias<'tcx> {
25    pub tcx: TyCtxt<'tcx>,
26    pub fn_map: FxHashMap<DefId, AAResult>,
27}
28
29impl<'tcx> Analysis for DefaultAlias<'tcx> {
30    fn name(&self) -> &'static str {
31        "Default alias analysis algorithm."
32    }
33
34    fn run(&mut self) {
35        rap_debug!("Start alias analysis.");
36        let mir_keys = self.tcx.mir_keys(());
37        for local_def_id in mir_keys {
38            self.query_mop(local_def_id.to_def_id());
39        }
40        // Meaning of output: 0 for ret value; 1,2,3,... for corresponding args.
41        for (fn_id, fn_alias) in &mut self.fn_map {
42            let fn_name = get_fn_name(self.tcx, *fn_id);
43            fn_alias.sort_alias_index();
44            if fn_alias.len() > 0 {
45                rap_info!("Alias found in {:?}: {}", fn_name, fn_alias);
46            }
47        }
48        self.handle_conor_cases();
49    }
50
51    fn reset(&mut self) {
52        todo!();
53    }
54}
55
56impl<'tcx, T> AliasAnalysis<T> for DefaultAlias<'tcx>
57where
58    T: From<AAResult> + Clone,
59{
60    fn get_fn_alias(&mut self, def_id: DefId) -> T {
61        self.fn_map
62            .get(&def_id)
63            .expect(&format!("Cannot find alias analysis result for {def_id:?}"))
64            .clone()
65            .into()
66    }
67
68    fn get_all_fn_alias(&mut self) -> FxHashMap<DefId, T> {
69        self.fn_map
70            .iter()
71            .map(|(k, v)| (*k, T::from(v.clone())))
72            .collect::<FxHashMap<DefId, T>>()
73    }
74}
75
76impl<'tcx> DefaultAlias<'tcx> {
77    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
78        Self {
79            tcx,
80            fn_map: FxHashMap::default(),
81        }
82    }
83
84    fn handle_conor_cases(&mut self) {
85        let cases = [
86            COPY_FROM_NONOVERLAPPING,
87            COPY_TO_NONOVERLAPPING,
88            COPY_TO,
89            COPY_FROM,
90        ];
91        let alias = AAFact::new(1, 2);
92        for (key, value) in self.fn_map.iter_mut() {
93            if cases.contains(&key.index.as_usize()) {
94                value.alias_set.clear();
95                value.alias_set.insert(alias.clone());
96            }
97        }
98    }
99
100    fn query_mop(&mut self, def_id: DefId) {
101        let fn_name = get_fn_name(self.tcx, def_id);
102        rap_trace!("query_mop: {:?}", fn_name);
103        /* filter const mir */
104        if let Some(_other) = self.tcx.hir_body_const_context(def_id.expect_local()) {
105            return;
106        }
107
108        if self.tcx.is_mir_available(def_id) {
109            let mut mop_graph = MopGraph::new(self.tcx, def_id);
110            mop_graph.solve_scc();
111            let mut recursion_set = HashSet::default();
112            mop_graph.check(0, &mut self.fn_map, &mut recursion_set);
113            if mop_graph.visit_times > VISIT_LIMIT {
114                rap_trace!("Over visited: {:?}", def_id);
115            }
116            self.fn_map.insert(def_id, mop_graph.ret_alias);
117        } else {
118            rap_trace!("mir is not available at {}", self.tcx.def_path_str(def_id));
119        }
120    }
121}