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