rapx/analysis/core/range_analysis/
mod.rs1#![allow(non_snake_case)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4pub mod default;
5pub mod domain;
6use crate::{
7 analysis::{
8 Analysis,
9 core::range_analysis::domain::domain::{ConstConvert, IntervalArithmetic},
10 },
11 utils::source::get_fn_name_byid,
12};
13use once_cell::sync::Lazy;
14use rust_intervals::Interval;
16use rustc_data_structures::fx::FxHashMap;
17use rustc_hir::def_id::DefId;
18use rustc_middle::mir::{BinOp, Place};
19
20use std;
21use std::{
22 collections::HashMap,
23 fmt::{self, Debug, Display},
24};
25pub type RAResult<'tcx, T> = HashMap<Place<'tcx>, Range<T>>;
26pub type RAResultMap<'tcx, T> = FxHashMap<DefId, HashMap<Place<'tcx>, Range<T>>>;
27pub type RAVecResultMap<'tcx, T> = FxHashMap<DefId, Vec<HashMap<Place<'tcx>, Range<T>>>>;
28
29pub type PathConstraint<'tcx> = HashMap<Vec<usize>, Vec<(Place<'tcx>, Place<'tcx>, BinOp)>>;
30pub type PathConstraintMap<'tcx> =
31 FxHashMap<DefId, HashMap<Vec<usize>, Vec<(Place<'tcx>, Place<'tcx>, BinOp)>>>;
32pub struct RAResultWrapper<'tcx, T: IntervalArithmetic>(pub RAResult<'tcx, T>);
33pub struct RAResultMapWrapper<'tcx, T: IntervalArithmetic>(pub RAResultMap<'tcx, T>);
34pub struct RAVecResultMapWrapper<'tcx, T: IntervalArithmetic>(pub RAVecResultMap<'tcx, T>);
35pub struct PathConstraintWrapper<'tcx>(pub PathConstraint<'tcx>);
36pub struct PathConstraintMapWrapper<'tcx>(pub PathConstraintMap<'tcx>);
37
38pub trait RangeAnalysis<'tcx, T: IntervalArithmetic + ConstConvert + Debug>: Analysis {
43 fn get_fn_range(&self, def_id: DefId) -> Option<RAResult<'tcx, T>>;
46
47 fn get_fn_ranges_percall(&self, def_id: DefId) -> Option<Vec<RAResult<'tcx, T>>>;
51
52 fn get_all_fn_ranges(&self) -> RAResultMap<'tcx, T>;
54
55 fn get_all_fn_ranges_percall(&self) -> RAVecResultMap<'tcx, T>;
57
58 fn get_fn_local_range(&self, def_id: DefId, local: Place<'tcx>) -> Option<Range<T>>;
60
61 fn get_fn_path_constraints(&self, def_id: DefId) -> Option<PathConstraint<'tcx>>;
65
66 fn get_all_path_constraints(&self) -> PathConstraintMap<'tcx>;
68}
69
70impl<'tcx, T> Display for RAResultWrapper<'tcx, T>
71where
72 Place<'tcx>: Debug,
73 T: IntervalArithmetic + Clone + PartialOrd + Display,
74{
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 for (place, range) in &self.0 {
77 writeln!(f, "{:?} => {}", place, range)?;
78 }
79 Ok(())
80 }
81}
82impl<'tcx, T> Display for RAResultMapWrapper<'tcx, T>
83where
84 DefId: Debug,
85 Place<'tcx>: Debug,
86 T: IntervalArithmetic + Clone + PartialOrd + Display,
87{
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 writeln!(f, "=== Print range analysis resuts ===")?;
90 for (def_id, ra_result) in &self.0 {
91 let fn_name = get_fn_name_byid(def_id);
92 writeln!(f, "Function: {:?} =>", fn_name)?;
93
94 let mut sorted: Vec<_> = ra_result.iter().collect();
95 sorted.sort_by_key(|(place, _)| place.local.as_usize());
96
97 for (place, range) in sorted {
98 writeln!(f, " {:?} => {}", place, range)?;
99 }
100 }
101 Ok(())
102 }
103}
104impl<'tcx, T> Display for RAVecResultMapWrapper<'tcx, T>
105where
106 DefId: Debug,
107 Place<'tcx>: Debug,
108 T: IntervalArithmetic + Clone + PartialOrd + Display,
109{
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 writeln!(f, "=== Print range analysis resuts ===")?;
112 for (def_id, vec_of_maps) in &self.0 {
113 let fn_name = get_fn_name_byid(def_id);
114 writeln!(f, "Function: {:?} =>", fn_name)?;
115
116 for (i, map) in vec_of_maps.iter().enumerate() {
117 writeln!(f, " Result Set #{}:", i)?;
118
119 let mut sorted: Vec<_> = map.iter().collect();
120 sorted.sort_by_key(|(place, _)| place.local.as_usize());
121
122 for (place, range) in sorted {
123 writeln!(f, " {:?} => {}", place, range)?;
124 }
125 }
126 }
127 Ok(())
128 }
129}
130
131impl<'tcx> Display for PathConstraintWrapper<'tcx>
132where
133 Place<'tcx>: Debug,
134 BinOp: Debug,
135{
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 for (path, constraints) in &self.0 {
138 writeln!(f, "Path {:?}:", path)?;
139 for (p1, p2, op) in constraints {
140 writeln!(f, " Constraint:{:?} {:?} {:?}", p1, op, p2)?;
141 }
142 }
143 Ok(())
144 }
145}
146
147impl<'tcx> Display for PathConstraintMapWrapper<'tcx>
148where
149 DefId: Debug,
150 Place<'tcx>: Debug,
151 BinOp: Debug,
152{
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 writeln!(f, "=== Print paths and constraints ===")?;
155 for (def_id, pc) in &self.0 {
156 let fn_name = get_fn_name_byid(def_id);
157 writeln!(f, "Function: {:?}:", fn_name)?;
158 for (path, constraints) in pc {
159 writeln!(f, " Path {:?}:", path)?;
160 for (p1, p2, op) in constraints {
161 writeln!(f, " Constraint:{:?} {:?} {:?}", p1, op, p2)?;
162 }
163 }
164 }
165 Ok(())
166 }
167}
168#[derive(Debug, PartialEq, Eq, Hash, Clone)]
169pub enum RangeType {
170 Unknown,
171 Regular,
172 Empty,
173}
174impl fmt::Display for RangeType {
175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176 let s = match self {
177 RangeType::Unknown => "Unknown",
178 RangeType::Regular => "Regular",
179 RangeType::Empty => "Empty",
180 };
181 write!(f, "{}", s)
182 }
183}
184#[derive(Debug, Hash, Clone, PartialEq, Eq)]
185
186pub struct Range<T>
187where
188 T: IntervalArithmetic,
189{
190 pub rtype: RangeType,
191 pub range: Interval<T>,
192}
193static STR_MIN: Lazy<String> = Lazy::new(|| "Min".to_string());
194static STR_MAX: Lazy<String> = Lazy::new(|| "Max".to_string());
195impl<T> Display for Range<T>
196where
197 T: IntervalArithmetic + std::fmt::Display,
198{
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 let lower: String = if *self.range.lower().unwrap() == T::min_value() {
201 STR_MIN.clone()
202 } else if *self.range.lower().unwrap() == T::max_value() {
203 STR_MAX.clone()
204 } else {
205 self.range.lower().unwrap().to_string()
206 };
207
208 let upper: String = if *self.range.upper().unwrap() == T::min_value() {
209 STR_MIN.clone()
210 } else if *self.range.upper().unwrap() == T::max_value() {
211 STR_MAX.clone()
212 } else {
213 self.range.upper().unwrap().to_string()
214 };
215
216 write!(f, "{:?} [{}, {}]", self.rtype, lower, upper)
217 }
218}