rapx/analysis/core/
alias_analysis.rs

1pub mod default;
2pub mod mop;
3use super::super::Analysis;
4use rustc_data_structures::fx::FxHashMap;
5use rustc_hir::def_id::DefId;
6use std::{collections::HashSet, fmt};
7
8pub trait AliasAnalysis<T>: Analysis {
9    fn get_fn_alias(&mut self, def_id: DefId) -> T;
10    fn get_all_fn_alias(&mut self) -> FxHashMap<DefId, T>;
11}
12
13/// To store the alias relationships among arguments and return values.
14///
15/// Each function may have multiple return instructions, leading to different RetAlias.
16#[derive(Debug, Clone)]
17pub struct AAResult {
18    arg_size: usize,
19    alias_set: HashSet<AAFact>,
20}
21
22impl AAResult {
23    pub fn new(arg_size: usize) -> AAResult {
24        Self {
25            arg_size,
26            alias_set: HashSet::new(),
27        }
28    }
29
30    pub fn arg_size(&self) -> usize {
31        self.arg_size
32    }
33
34    pub fn aliases(&self) -> &HashSet<AAFact> {
35        &self.alias_set
36    }
37
38    pub fn add_alias(&mut self, alias: AAFact) {
39        self.alias_set.insert(alias);
40    }
41
42    pub fn len(&self) -> usize {
43        self.alias_set.len()
44    }
45
46    pub fn sort_alias_index(&mut self) {
47        let alias_set = std::mem::take(&mut self.alias_set);
48        let mut new_alias_set = HashSet::with_capacity(alias_set.len());
49
50        for mut ra in alias_set.into_iter() {
51            if ra.lhs_no() >= ra.rhs_no() {
52                ra.swap();
53            }
54            new_alias_set.insert(ra);
55        }
56        self.alias_set = new_alias_set;
57    }
58}
59
60impl fmt::Display for AAResult {
61    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
62        write!(
63            f,
64            "{{{}}}",
65            self.aliases()
66                .iter()
67                .map(|alias| format!("{}", alias))
68                .collect::<Vec<String>>()
69                .join(",")
70        )
71    }
72}
73
74/// AAFact is used to store the alias relationships between two places.
75/// The result is field-sensitive.
76#[derive(Debug, Clone, Hash, PartialEq, Eq)]
77pub struct AAFact {
78    pub lhs_no: usize,
79    pub lhs_fields: Vec<usize>,
80    pub rhs_no: usize,
81    pub rhs_fields: Vec<usize>,
82}
83
84impl AAFact {
85    pub fn new(lhs_no: usize, rhs_no: usize) -> AAFact {
86        AAFact {
87            lhs_no,
88            lhs_fields: Vec::<usize>::new(),
89            rhs_no,
90            rhs_fields: Vec::<usize>::new(),
91        }
92    }
93
94    pub fn swap(&mut self) {
95        std::mem::swap(&mut self.lhs_no, &mut self.rhs_no);
96        std::mem::swap(&mut self.lhs_fields, &mut self.rhs_fields);
97    }
98
99    pub fn lhs_no(&self) -> usize {
100        self.lhs_no
101    }
102
103    pub fn rhs_no(&self) -> usize {
104        self.rhs_no
105    }
106
107    pub fn lhs_fields(&self) -> &[usize] {
108        &self.lhs_fields
109    }
110
111    pub fn rhs_fields(&self) -> &[usize] {
112        &self.rhs_fields
113    }
114}
115
116fn aa_place_desc_str(no: usize, fields: &[usize], field_sensitive: bool) -> String {
117    let mut result = String::new();
118    result.push_str(&no.to_string());
119    if !field_sensitive {
120        return result;
121    }
122    for num in fields.iter() {
123        result.push('.');
124        result.push_str(&num.to_string());
125    }
126    result
127}
128
129impl fmt::Display for AAFact {
130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131        write!(
132            f,
133            "({},{})",
134            aa_place_desc_str(self.lhs_no, &self.lhs_fields, true),
135            aa_place_desc_str(self.rhs_no, &self.rhs_fields, true)
136        )
137    }
138}