rapx/analysis/core/
range_analysis.rs1#![allow(non_snake_case)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4
5use crate::analysis::core::range_analysis::domain::domain::ConstConvert;
6use crate::analysis::core::range_analysis::domain::domain::IntervalArithmetic;
7use crate::analysis::core::range_analysis::domain::range::Range;
8use crate::rap_info;
9
10pub mod PassRunner;
11pub mod SSA;
12pub mod domain;
13use crate::analysis::Analysis;
14use domain::ConstraintGraph::ConstraintGraph;
15use rustc_data_structures::fx::FxHashMap;
16use rustc_hir::def::DefKind;
17use rustc_hir::def_id::DefId;
18use rustc_hir::def_id::LocalDefId;
19use rustc_middle::mir::Body;
20use rustc_middle::mir::Local;
21use rustc_middle::ty::TyCtxt;
22use std::{
23 collections::{HashMap, HashSet},
24 fmt::Debug,
25};
26use PassRunner::*;
27pub struct SSATrans<'tcx> {
28 pub tcx: TyCtxt<'tcx>,
29 pub debug: bool,
30}
31
32impl<'tcx> SSATrans<'tcx> {
33 pub fn new(tcx: TyCtxt<'tcx>, debug: bool) -> Self {
34 Self { tcx: tcx, debug }
35 }
36
37 pub fn start(&mut self) {
38 for local_def_id in self.tcx.iter_local_def_id() {
39 if matches!(self.tcx.def_kind(local_def_id), DefKind::Fn) {
40 if self.tcx.hir_maybe_body_owned_by(local_def_id).is_some() {
41 if let Some(def_id) = self
42 .tcx
43 .hir_body_owners()
44 .find(|id| self.tcx.def_path_str(*id) == "main")
45 {
46 if let Some(ssa_def_id) =
47 self.tcx.hir_crate_items(()).free_items().find(|id| {
48 let hir_id = id.hir_id();
49 if let Some(ident_name) = self.tcx.hir_opt_name(hir_id) {
50 ident_name.to_string() == "SSAstmt"
51 } else {
52 false
53 }
54 })
55 {
56 let ssa_def_id = ssa_def_id.owner_id.to_def_id();
57 if let Some(essa_def_id) =
58 self.tcx.hir_crate_items(()).free_items().find(|id| {
59 let hir_id = id.hir_id();
60 if let Some(ident_name) = self.tcx.hir_opt_name(hir_id) {
61 ident_name.to_string() == "ESSAstmt"
62 } else {
63 false
64 }
65 })
66 {
67 let essa_def_id = essa_def_id.owner_id.to_def_id();
68 self.analyze_mir(self.tcx, def_id, ssa_def_id, essa_def_id);
69 }
70 }
71 }
72 }
73 }
74 }
75 }
76 fn analyze_mir(
77 &mut self,
78 tcx: TyCtxt<'tcx>,
79 def_id: LocalDefId,
80 ssa_def_id: DefId,
81 essa_def_id: DefId,
82 ) {
83 let mut body = tcx.optimized_mir(def_id).clone();
84 {
85 let body_mut_ref: &mut Body<'tcx> = unsafe { &mut *(&mut body as *mut Body<'tcx>) };
86 let mut passrunner = PassRunner::PassRunner::new(tcx);
87 passrunner.run_pass(body_mut_ref, ssa_def_id, essa_def_id);
88 let essa_mir_string = passrunner.get_final_ssa_as_string(body_mut_ref);
90 rap_info!("ssa lvalue check {:?}", lvalue_check(&essa_mir_string));
92 }
93 }
94}
95
96pub trait RangeAnalysis<'tcx, T: IntervalArithmetic + ConstConvert + Debug>: Analysis {
97 fn get_fn_range(&self, def_id: DefId) -> Option<HashMap<Local, Range<T>>>;
98 fn get_all_fn_ranges(&self) -> FxHashMap<DefId, HashMap<Local, Range<T>>>;
99 fn get_fn_local_range(&self, def_id: DefId, local: Local) -> Option<Range<T>>;
100}
101
102pub struct DefaultRange<'tcx, T: IntervalArithmetic + ConstConvert + Debug> {
103 pub tcx: TyCtxt<'tcx>,
104 pub debug: bool,
105 pub ssa_def_id: Option<DefId>,
106 pub essa_def_id: Option<DefId>,
107 pub final_vars: FxHashMap<DefId, HashMap<Local, Range<T>>>,
108 pub ssa_locals_mapping: FxHashMap<DefId, HashMap<Local, HashSet<Local>>>,
109}
110impl<'tcx, T: IntervalArithmetic + ConstConvert + Debug> Analysis for DefaultRange<'tcx, T>
111where
112 T: IntervalArithmetic + ConstConvert + Debug,
113{
114 fn name(&self) -> &'static str {
115 "Range Analysis"
116 }
117
118 fn run(&mut self) {
119 for local_def_id in self.tcx.iter_local_def_id() {
120 if matches!(self.tcx.def_kind(local_def_id), DefKind::Fn) {
121 if self.tcx.hir_maybe_body_owned_by(local_def_id).is_some() {
122 rap_info!(
123 "Analyzing function: {}",
124 self.tcx.def_path_str(local_def_id)
125 );
126 self.analyze_mir(local_def_id);
127 }
128 }
129 }
130 }
131
132 fn reset(&mut self) {
133 self.final_vars.clear();
134 self.ssa_locals_mapping.clear();
135 }
136}
137
138impl<'tcx, T: IntervalArithmetic + ConstConvert + Debug> RangeAnalysis<'tcx, T>
139 for DefaultRange<'tcx, T>
140where
141 T: IntervalArithmetic + ConstConvert + Debug,
142{
143 fn get_fn_range(&self, def_id: DefId) -> Option<HashMap<Local, Range<T>>> {
144 self.final_vars.get(&def_id).cloned()
145 }
146
147 fn get_all_fn_ranges(&self) -> FxHashMap<DefId, HashMap<Local, Range<T>>> {
148 self.final_vars.clone()
150 }
151
152 fn get_fn_local_range(&self, def_id: DefId, local: Local) -> Option<Range<T>> {
154 self.final_vars
155 .get(&def_id)
156 .and_then(|vars| vars.get(&local).cloned())
157 }
158}
159
160impl<'tcx, T> DefaultRange<'tcx, T>
161where
162 T: IntervalArithmetic + ConstConvert + Debug,
163{
164 pub fn new(tcx: TyCtxt<'tcx>, debug: bool) -> Self {
165 let mut ssa_id = None;
166 let mut essa_id = None;
167
168 if let Some(ssa_def_id) = tcx.hir_crate_items(()).free_items().find(|id| {
169 let hir_id = id.hir_id();
170 if let Some(ident_name) = tcx.hir_opt_name(hir_id) {
171 ident_name.to_string() == "SSAstmt"
172 } else {
173 false
174 }
175 }) {
176 ssa_id = Some(ssa_def_id.owner_id.to_def_id());
177 if let Some(essa_def_id) = tcx.hir_crate_items(()).free_items().find(|id| {
178 let hir_id = id.hir_id();
179 if let Some(ident_name) = tcx.hir_opt_name(hir_id) {
180 ident_name.to_string() == "ESSAstmt"
181 } else {
182 false
183 }
184 }) {
185 essa_id = Some(essa_def_id.owner_id.to_def_id());
186 }
187 }
188 Self {
189 tcx: tcx,
190 debug,
191 ssa_def_id: ssa_id,
192 essa_def_id: essa_id,
193 final_vars: HashMap::default(),
194 ssa_locals_mapping: HashMap::default(),
195 }
196 }
197
198 fn analyze_mir(&mut self, def_id: LocalDefId) {
199 let mut body = self.tcx.optimized_mir(def_id).clone();
200 {
201 let ssa_def_id = self.ssa_def_id.expect("SSA definition ID is not set");
202 let essa_def_id = self.essa_def_id.expect("ESSA definition ID is not set");
203
204 let body_mut_ref: &mut Body<'tcx> = unsafe { &mut *(&mut body as *mut Body<'tcx>) };
205 let mut passrunner = PassRunner::PassRunner::new(self.tcx);
206 passrunner.run_pass(body_mut_ref, ssa_def_id, essa_def_id);
207 let mut cg: ConstraintGraph<'tcx, T> = ConstraintGraph::new(essa_def_id, ssa_def_id);
209 cg.build_graph(body_mut_ref);
210 cg.build_nuutila(false);
211 cg.find_intervals();
212 cg.rap_print_vars();
213 let (r#final, not_found) = cg.build_final_vars(&passrunner.locals_map);
214 cg.rap_print_final_vars();
215
216 self.ssa_locals_mapping
217 .insert(def_id.into(), passrunner.locals_map.clone());
218
219 let mut r_final = HashMap::default();
220
221 for (&place, varnode) in r#final.iter() {
222 r_final.insert(place.local, varnode.get_range().clone());
223 }
224 self.final_vars.insert(def_id.into(), r_final);
225 }
226 }
227}