rapx/analysis/core/alias_analysis/default/
alias.rs1use super::{MopAAFact, MopAAResultMap, assign::*, block::Term, graph::*, types::*, value::*};
2use crate::analysis::graphs::scc::Scc;
3use crate::def_id::*;
4use rustc_hir::def_id::DefId;
5use rustc_middle::{
6 mir::{Operand, Place, ProjectionElem, TerminatorKind},
7 ty,
8};
9use std::collections::HashSet;
10
11impl<'tcx> MopGraph<'tcx> {
12 pub fn alias_bb(&mut self, bb_index: usize) {
14 for stmt in self.blocks[bb_index].const_value.clone() {
15 self.constants.insert(stmt.def_id, stmt.value);
16 }
17 let cur_block = self.blocks[bb_index].clone();
18 for assign in cur_block.assignments {
19 let mut lv_aliaset_idx = self.projection(false, assign.lv);
20 let rv_aliaset_idx = self.projection(true, assign.rv);
21 rap_debug!("{:?} = {:?}", lv_aliaset_idx, rv_aliaset_idx);
22 match assign.atype {
23 AssignType::Variant => {
24 self.alias_set[lv_aliaset_idx] = rv_aliaset_idx;
25 continue;
26 }
27 AssignType::InitBox => {
28 lv_aliaset_idx = *self.values[lv_aliaset_idx].fields.get(&0).unwrap();
29 }
30 _ => {} }
32 if self.values[lv_aliaset_idx].local != self.values[rv_aliaset_idx].local {
33 self.merge_alias(lv_aliaset_idx, rv_aliaset_idx, 0);
34 }
35 }
36 }
37
38 pub fn alias_bbcall(
40 &mut self,
41 bb_index: usize,
42 fn_map: &mut MopAAResultMap,
43 recursion_set: &mut HashSet<DefId>,
44 ) {
45 let cur_block = self.blocks[bb_index].clone();
46 if let Term::Call(call) | Term::Drop(call) = cur_block.terminator {
47 if let TerminatorKind::Call {
48 func: Operand::Constant(ref constant),
49 ref args,
50 ref destination,
51 target: _,
52 unwind: _,
53 call_source: _,
54 fn_span: _,
55 } = call.kind
56 {
57 let lv = self.projection(false, *destination);
58 let mut merge_vec = Vec::new();
59 merge_vec.push(lv);
60 let mut may_drop_flag = 0;
61 if self.values[lv].may_drop {
62 may_drop_flag += 1;
63 }
64 for arg in args {
65 match arg.node {
66 Operand::Copy(ref p) => {
67 let rv = self.projection(true, *p);
68 merge_vec.push(rv);
69 if self.values[rv].may_drop {
70 may_drop_flag += 1;
71 }
72 }
73 Operand::Move(ref p) => {
74 let rv = self.projection(true, *p);
75 merge_vec.push(rv);
76 if self.values[rv].may_drop {
77 may_drop_flag += 1;
78 }
79 }
80 Operand::Constant(_) => {
81 merge_vec.push(0);
82 }
83 }
84 }
85 if let &ty::FnDef(target_id, _) = constant.const_.ty().kind() {
86 if may_drop_flag > 0 {
87 if self.tcx.is_mir_available(target_id) {
88 rap_debug!("target_id {:?}", target_id);
89 if fn_map.contains_key(&target_id) {
90 let assignments = fn_map.get(&target_id).unwrap();
91 for assign in assignments.aliases().iter() {
92 if !assign.valuable() {
93 continue;
94 }
95 self.merge(assign, &merge_vec);
96 }
97 } else {
98 if recursion_set.contains(&target_id) {
100 return;
101 }
102 recursion_set.insert(target_id);
103 let mut mop_graph = MopGraph::new(self.tcx, target_id);
104 mop_graph.find_scc();
105 mop_graph.check(0, fn_map, recursion_set);
106 let ret_alias = mop_graph.ret_alias.clone();
107 for assign in ret_alias.aliases().iter() {
108 if !assign.valuable() {
109 continue;
110 }
111 self.merge(assign, &merge_vec);
112 }
113 fn_map.insert(target_id, ret_alias);
114 recursion_set.remove(&target_id);
115 }
116 } else if self.values[lv].may_drop {
117 if target_id == call_mut() {
118 return;
119 }
120
121 let mut right_set = Vec::new();
122 for rv in &merge_vec {
123 if self.values[*rv].may_drop
124 && lv != *rv
125 && self.values[lv].is_ptr()
126 {
127 right_set.push(*rv);
128 }
129 }
130 if right_set.len() == 1 {
131 self.merge_alias(lv, right_set[0], 0);
132 }
133 }
134 }
135 }
136 }
137 }
138 }
139
140 pub fn projection(&mut self, is_right: bool, place: Place<'tcx>) -> usize {
147 let mut local = place.local.as_usize();
148 let mut proj_id: usize = local;
149 for proj in place.projection {
150 let new_id = self.values.len();
151 match proj {
152 ProjectionElem::Deref => {
153 proj_id = self.values[proj_id].index;
154 }
155 ProjectionElem::Field(field, ty) => {
159 if is_right && self.values[proj_id].index != proj_id {
160 proj_id = self.values[proj_id].index;
161 local = self.values[proj_id].local;
162 }
163 let field_idx = field.as_usize();
164 if let std::collections::hash_map::Entry::Vacant(e) =
165 self.values[proj_id].fields.entry(field_idx)
166 {
167 let ty_env = ty::TypingEnv::post_analysis(self.tcx, self.def_id);
168 let need_drop = ty.needs_drop(self.tcx, ty_env);
169 let may_drop = !is_not_drop(self.tcx, ty);
170 let mut node = Value::new(new_id, local, need_drop, need_drop || may_drop);
171 node.kind = kind(ty);
172 node.field_id = field_idx;
173 e.insert(node.index);
174 self.alias_set.push(self.values.len());
175 self.values.push(node);
176 }
177 proj_id = *self.values[proj_id].fields.get(&field_idx).unwrap();
178 }
179 _ => {}
180 }
181 }
182 proj_id
183 }
184
185 pub fn merge_alias(&mut self, lv: usize, rv: usize, depth: usize) {
187 rap_debug!("Alias set before merge: {:?}", self.alias_set);
188 self.union_merge(lv, rv);
190 rap_debug!(
192 "update the alias set for lv:{} rv:{} set:{:?}",
193 lv,
194 rv,
195 self.alias_set
196 );
197
198 let max_field_depth = match std::env::var_os("MOP") {
199 Some(val) if val == "0" => 10,
200 Some(val) if val == "1" => 20,
201 Some(val) if val == "2" => 30,
202 Some(val) if val == "3" => 50,
203 _ => 15,
204 };
205
206 if depth > max_field_depth {
207 return;
208 }
209
210 for field in self.values[rv].fields.clone().into_iter() {
211 if !self.values[lv].fields.contains_key(&field.0) {
212 let mut node = Value::new(
213 self.values.len(),
214 self.values[lv].local,
215 self.values[field.1].need_drop,
216 self.values[field.1].may_drop,
217 );
218 node.kind = self.values[field.1].kind;
219 node.field_id = field.0;
220 self.values[lv].fields.insert(field.0, node.index);
221 self.alias_set.push(self.values.len());
222 self.values.push(node);
223 }
224 let lv_field = *(self.values[lv].fields.get(&field.0).unwrap());
225 self.merge_alias(lv_field, field.1, depth + 1);
226 }
227 }
228
229 pub fn merge(&mut self, ret_alias: &MopAAFact, arg_vec: &[usize]) {
231 rap_debug!("{:?}", ret_alias);
232 if ret_alias.lhs_no() >= arg_vec.len() || ret_alias.rhs_no() >= arg_vec.len() {
233 rap_debug!("Vector error!");
234 return;
235 }
236 let left_init = arg_vec[ret_alias.lhs_no()];
237 let mut right_init = arg_vec[ret_alias.rhs_no()];
238 let mut lv = left_init;
239 let mut rv = right_init;
240 for index in ret_alias.lhs_fields().iter() {
241 if !self.values[lv].fields.contains_key(index) {
242 let need_drop = ret_alias.lhs_need_drop;
243 let may_drop = ret_alias.lhs_may_drop;
244 let mut node = Value::new(self.values.len(), left_init, need_drop, may_drop);
245 node.kind = TyKind::RawPtr;
246 node.field_id = *index;
247 self.values[lv].fields.insert(*index, node.index);
248 self.alias_set.push(self.values.len());
249 self.values.push(node);
250 }
251 lv = *self.values[lv].fields.get(index).unwrap();
252 }
253 for index in ret_alias.rhs_fields().iter() {
254 if self.union_is_same(rv, self.alias_set[rv]) {
255 right_init = self.values[rv].local;
256 }
257 if !self.values[rv].fields.contains_key(index) {
258 let need_drop = ret_alias.rhs_need_drop;
259 let may_drop = ret_alias.rhs_may_drop;
260 let mut node = Value::new(self.values.len(), right_init, need_drop, may_drop);
261 node.kind = TyKind::RawPtr;
262 node.field_id = *index;
263 self.values[rv].fields.insert(*index, node.index);
264 self.alias_set.push(self.values.len());
265 self.values.push(node);
266 }
267 rv = *self.values[rv].fields.get(index).unwrap();
268 }
269 self.merge_alias(lv, rv, 0);
270 }
271
272 pub fn merge_results(&mut self, results_nodes: Vec<Value>) {
274 for node in results_nodes.iter() {
275 if node.local <= self.arg_size
276 && (self.union_is_same(node.index, self.alias_set[node.index])
277 || self.alias_set[node.index] != node.index)
278 {
279 if self.values.len() == 1 {
280 return;
281 }
282 let f_node: Vec<usize> = results_nodes.iter().map(|v| v.father).collect();
283
284 for idx in 1..self.values.len() {
285 if !self.union_is_same(idx, node.index) {
286 continue;
287 }
288
289 let mut replace = None;
290 if results_nodes[idx].local > self.arg_size {
291 for (i, &fidx) in f_node.iter().enumerate() {
292 if i != idx && i != node.index && fidx == f_node[idx] {
293 for (j, v) in results_nodes.iter().enumerate() {
294 if j != idx
295 && j != node.index
296 && self.union_is_same(j, fidx)
297 && v.local <= self.arg_size
298 {
299 replace = Some(&results_nodes[j]);
300 }
301 }
302 }
303 }
304 }
305
306 if (results_nodes[idx].local <= self.arg_size || replace.is_some())
307 && idx != node.index
308 && node.local != results_nodes[idx].local
309 {
310 let left_node;
311 let right_node;
312 match results_nodes[idx].local {
313 0 => {
314 left_node = match replace {
315 Some(replace_node) => replace_node,
316 None => &results_nodes[idx],
317 };
318 right_node = node;
319 }
320 _ => {
321 left_node = node;
322 right_node = match replace {
323 Some(replace_node) => replace_node,
324 None => &results_nodes[idx],
325 };
326 }
327 }
328 let mut new_alias = MopAAFact::new(
329 left_node.local,
330 left_node.may_drop,
331 left_node.need_drop,
332 right_node.local,
333 right_node.may_drop,
334 right_node.need_drop,
335 );
336 new_alias.fact.lhs_fields = self.get_field_seq(left_node);
337 new_alias.fact.rhs_fields = self.get_field_seq(right_node);
338 if new_alias.lhs_no() == 0 && new_alias.rhs_no() == 0 {
339 return;
340 }
341 self.ret_alias.add_alias(new_alias);
342 }
343 }
344 }
345 }
346 }
347
348 pub fn get_field_seq(&self, value: &Value) -> Vec<usize> {
349 let mut field_id_seq = vec![];
350 let mut node_ref = value;
351 while node_ref.field_id != usize::MAX {
352 field_id_seq.push(node_ref.field_id);
353 node_ref = &self.values[value.father];
354 }
355 field_id_seq
356 }
357
358 #[inline(always)]
359 pub fn union_find(&mut self, e: usize) -> usize {
360 let mut r = e;
361 while self.alias_set[r] != r {
362 r = self.alias_set[r];
363 }
364 r
365 }
366
367 #[inline(always)]
368 pub fn union_merge(&mut self, e1: usize, e2: usize) {
369 let f1 = self.union_find(e1);
370 let f2 = self.union_find(e2);
371
372 if f1 < f2 {
373 self.alias_set[f2] = f1;
374 }
375 if f1 > f2 {
376 self.alias_set[f1] = f2;
377 }
378
379 for member in 0..self.alias_set.len() {
380 self.alias_set[member] = self.union_find(self.alias_set[member]);
381 }
382 }
383
384 #[inline(always)]
385 pub fn union_is_same(&mut self, e1: usize, e2: usize) -> bool {
386 let f1 = self.union_find(e1);
387 let f2 = self.union_find(e2);
388 f1 == f2
389 }
390
391 #[inline(always)]
392 pub fn get_alias_set(&mut self, e: usize) -> HashSet<usize> {
393 let mut alias_set = HashSet::new();
394 for i in 0..self.alias_set.len() {
395 if i == e {
396 continue;
397 }
398 if self.union_is_same(e, i) {
399 alias_set.insert(i);
400 }
401 }
402 alias_set
403 }
404
405 #[inline(always)]
406 pub fn union_has_alias(&mut self, e: usize) -> bool {
407 for i in 0..self.alias_set.len() {
408 if i == e {
409 continue;
410 }
411 if self.union_is_same(e, i) {
412 return true;
413 }
414 }
415 false
416 }
417}