rapx/analysis/alias_analysis/default/
mop.rs1use rustc_hir::def_id::DefId;
2
3use std::collections::HashSet;
4
5use crate::analysis::path_analysis::{PathNode, PathTree};
6use crate::compat::{FxHashMap, FxHashSet};
7
8use super::value::Value;
9use super::{graph::*, *};
10
11#[derive(Clone)]
12struct MopStateSnapshot {
13 values: Vec<Value>,
14 constants: FxHashMap<usize, usize>,
15 alias_sets: Vec<FxHashSet<usize>>,
16}
17
18impl<'tcx> AliasGraph<'tcx> {
19 fn snapshot_state(&self) -> MopStateSnapshot {
20 MopStateSnapshot {
21 values: self.values.clone(),
22 constants: self.constants.clone(),
23 alias_sets: self.alias_sets.clone(),
24 }
25 }
26
27 fn restore_state(&mut self, snapshot: &MopStateSnapshot) {
28 self.values = snapshot.values.clone();
29 self.constants = snapshot.constants.clone();
30 self.alias_sets = snapshot.alias_sets.clone();
31 }
32
33 pub fn process_function_paths(
44 &mut self,
45 fn_map: &mut MopFnAliasMap,
46 recursion_set: &mut HashSet<DefId>,
47 ) {
48 self.process_function_paths_opt(None, fn_map, recursion_set)
49 }
50
51 pub fn process_function_paths_opt(
53 &mut self,
54 precomputed_paths: Option<PathTree>,
55 fn_map: &mut MopFnAliasMap,
56 recursion_set: &mut HashSet<DefId>,
57 ) {
58 rap_debug!(
59 "process_function_paths: def_id={:?} blocks={}",
60 self.def_id(),
61 self.path_graph.cfg.blocks.len()
62 );
63 let paths = precomputed_paths.unwrap_or_else(|| self.enumerate_paths());
64 rap_debug!(
65 "process_function_paths: def_id={:?} paths_enumerated={}",
66 self.def_id(),
67 paths.len()
68 );
69
70 let Some(root) = paths.root() else {
71 return;
72 };
73 let mut path = Vec::new();
74 let _ = self.dfs_mop(root, &mut path, fn_map, recursion_set);
75 }
76
77 fn dfs_mop(
78 &mut self,
79 node: &PathNode,
80 path: &mut Vec<usize>,
81 fn_map: &mut MopFnAliasMap,
82 recursion_set: &mut HashSet<DefId>,
83 ) -> Result<(), ()> {
84 path.push(node.block);
85 self.alias_bb(node.block);
86 self.alias_bbcall(node.block, fn_map, recursion_set);
87
88 let saved_state = self.snapshot_state();
89 let saved_recursion = recursion_set.clone();
90
91 if node.is_path_end {
92 self.increment_visit_times();
93 if self.visit_times() > VISIT_LIMIT {
94 path.pop();
95 return Err(());
96 }
97 self.merge_results();
98 }
99
100 for child in &node.children {
101 self.restore_state(&saved_state);
102 *recursion_set = saved_recursion.clone();
103 self.dfs_mop(child, path, fn_map, recursion_set)?;
104 }
105
106 path.pop();
107 Ok(())
108 }
109}