rapx/analysis/core/alias_analysis/default/
mod.rs1pub mod alias;
2pub mod assign;
3pub mod block;
4pub mod graph;
5pub mod mop;
6pub mod types;
7pub mod value;
8
9use super::{AAFact, AAResult, AAResultMap, AliasAnalysis};
10use crate::{
11 analysis::{Analysis, graphs::scc::Scc},
12 def_id::*,
13 utils::source::*,
14};
15use graph::MopGraph;
16use rustc_data_structures::fx::FxHashMap;
17use rustc_hir::def_id::DefId;
18use rustc_middle::ty::TyCtxt;
19use std::{collections::HashSet, convert::From, fmt};
20
21pub const VISIT_LIMIT: usize = 1000;
22
23#[derive(Debug, Clone, Hash, PartialEq, Eq)]
24pub struct MopAAFact {
25 pub fact: AAFact,
26 pub lhs_may_drop: bool,
27 pub lhs_need_drop: bool,
28 pub rhs_may_drop: bool,
29 pub rhs_need_drop: bool,
30}
31
32impl MopAAFact {
33 pub fn new(
34 lhs_no: usize,
35 lhs_may_drop: bool,
36 lhs_need_drop: bool,
37 rhs_no: usize,
38 rhs_may_drop: bool,
39 rhs_need_drop: bool,
40 ) -> MopAAFact {
41 MopAAFact {
42 fact: AAFact::new(lhs_no, rhs_no),
43 lhs_may_drop,
44 lhs_need_drop,
45 rhs_may_drop,
46 rhs_need_drop,
47 }
48 }
49
50 pub fn valuable(&self) -> bool {
51 return self.lhs_may_drop && self.rhs_may_drop;
52 }
53
54 pub fn swap(&mut self) {
55 self.fact.swap();
56 std::mem::swap(&mut self.lhs_may_drop, &mut self.rhs_may_drop);
57 std::mem::swap(&mut self.lhs_need_drop, &mut self.rhs_need_drop);
58 }
59
60 pub fn lhs_no(&self) -> usize {
61 self.fact.lhs_no
62 }
63
64 pub fn rhs_no(&self) -> usize {
65 self.fact.rhs_no
66 }
67
68 pub fn lhs_fields(&self) -> &[usize] {
69 &self.fact.lhs_fields
70 }
71
72 pub fn rhs_fields(&self) -> &[usize] {
73 &self.fact.rhs_fields
74 }
75}
76
77impl From<MopAAFact> for AAFact {
78 fn from(m: MopAAFact) -> Self {
79 m.fact
80 }
81}
82
83impl From<MopAAResult> for AAResult {
84 fn from(m: MopAAResult) -> Self {
85 let alias_set = m.alias_set.into_iter().map(Into::into).collect(); AAResult {
87 arg_size: m.arg_size,
88 alias_set,
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
94pub struct MopAAResult {
95 arg_size: usize,
96 alias_set: HashSet<MopAAFact>,
97}
98
99impl fmt::Display for MopAAResult {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 write!(
102 f,
103 "{{{}}}",
104 self.aliases()
105 .iter()
106 .map(|alias| format!("{}", alias.fact))
107 .collect::<Vec<String>>()
108 .join(",")
109 )
110 }
111}
112
113impl MopAAResult {
114 pub fn new(arg_size: usize) -> MopAAResult {
115 Self {
116 arg_size,
117 alias_set: HashSet::new(),
118 }
119 }
120
121 pub fn arg_size(&self) -> usize {
122 self.arg_size
123 }
124
125 pub fn aliases(&self) -> &HashSet<MopAAFact> {
126 &self.alias_set
127 }
128
129 pub fn add_alias(&mut self, alias: MopAAFact) {
130 self.alias_set.insert(alias);
131 }
132
133 pub fn len(&self) -> usize {
134 self.alias_set.len()
135 }
136
137 pub fn sort_alias_index(&mut self) {
138 let alias_set = std::mem::take(&mut self.alias_set);
139 let mut new_alias_set = HashSet::with_capacity(alias_set.len());
140
141 for mut ra in alias_set.into_iter() {
142 if ra.lhs_no() >= ra.rhs_no() {
143 ra.swap();
144 }
145 new_alias_set.insert(ra);
146 }
147 self.alias_set = new_alias_set;
148 }
149}
150
151pub type MopAAResultMap = FxHashMap<DefId, MopAAResult>;
153
154pub struct AliasAnalyzer<'tcx> {
155 pub tcx: TyCtxt<'tcx>,
156 pub fn_map: FxHashMap<DefId, MopAAResult>,
157}
158
159impl<'tcx> Analysis for AliasAnalyzer<'tcx> {
160 fn name(&self) -> &'static str {
161 "Alias Analysis (MoP)"
162 }
163
164 fn run(&mut self) {
165 rap_debug!("Start alias analysis via MoP.");
166 let mir_keys = self.tcx.mir_keys(());
167 for local_def_id in mir_keys {
168 self.query_mop(local_def_id.to_def_id());
169 }
170 for (fn_id, fn_alias) in &mut self.fn_map {
172 let fn_name = get_fn_name(self.tcx, *fn_id);
173 fn_alias.sort_alias_index();
174 if fn_alias.len() > 0 {
175 rap_debug!("Alias found in {:?}: {}", fn_name, fn_alias);
176 }
177 }
178 self.handle_conor_cases();
179 }
180
181 fn reset(&mut self) {
182 todo!();
183 }
184}
185
186impl<'tcx> AliasAnalysis for AliasAnalyzer<'tcx> {
187 fn get_fn_alias(&self, def_id: DefId) -> Option<AAResult> {
188 self.fn_map.get(&def_id).cloned().map(Into::into)
189 }
190
191 fn get_all_fn_alias(&self) -> AAResultMap {
192 self.fn_map
193 .iter()
194 .map(|(k, v)| (*k, AAResult::from(v.clone())))
195 .collect()
196 }
197}
198
199impl<'tcx> AliasAnalyzer<'tcx> {
200 pub fn new(tcx: TyCtxt<'tcx>) -> Self {
201 Self {
202 tcx,
203 fn_map: FxHashMap::default(),
204 }
205 }
206
207 fn handle_conor_cases(&mut self) {
208 let cases = [
209 copy_from_nonoverlapping(),
210 copy_to_nonoverlapping(),
211 copy_to(),
212 copy_from(),
213 ];
214 let alias = MopAAFact::new(1, true, true, 2, true, true);
215 for (key, value) in self.fn_map.iter_mut() {
216 if cases.iter().any(|lock| lock == key) {
217 value.alias_set.clear();
218 value.alias_set.insert(alias.clone());
219 }
220 }
221 }
222
223 fn query_mop(&mut self, def_id: DefId) {
224 let fn_name = get_fn_name(self.tcx, def_id);
225 rap_trace!("query_mop: {:?}", fn_name);
226 if let Some(_other) = self.tcx.hir_body_const_context(def_id.expect_local()) {
228 return;
229 }
230
231 if self.tcx.is_mir_available(def_id) {
232 let mut mop_graph = MopGraph::new(self.tcx, def_id);
233 mop_graph.find_scc();
234 let mut recursion_set = HashSet::default();
235 mop_graph.check(0, &mut self.fn_map, &mut recursion_set);
236 if mop_graph.visit_times > VISIT_LIMIT {
237 rap_trace!("Over visited: {:?}", def_id);
238 }
239 self.fn_map.insert(def_id, mop_graph.ret_alias);
240 } else {
241 rap_trace!("Mir is not available at {}", self.tcx.def_path_str(def_id));
242 }
243 }
244
245 pub fn get_all_fn_alias_raw(&mut self) -> MopAAResultMap {
246 self.fn_map.clone()
247 }
248}