rapx/analysis/core/range_analysis/domain/
range.rs1#![allow(unused_imports)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4#![allow(unused_assignments)]
5#![allow(irrefutable_let_patterns)]
6use std::{default, fmt};
7
8use num_traits::{Bounded, Num, Zero};
9use rust_intervals::Interval;
10use rustc_middle::mir::{BinOp, UnOp};
11use std::ops::{Add, Mul, Sub};
13
14use crate::{
15 analysis::core::range_analysis::{Range, RangeType, domain::SymbolicExpr::IntervalTypeTrait},
16 rap_trace,
17};
18
19use super::domain::*;
20
21impl<T> Range<T>
60where
61 T: IntervalArithmetic,
62{
63 pub fn new(lb: T, ub: T, rtype: RangeType) -> Self {
65 Self {
66 rtype,
67 range: Interval::new_closed_closed(lb, ub),
68 }
69 }
70 pub fn default(default: T) -> Self {
71 Self {
72 rtype: RangeType::Unknown,
73
74 range: Interval::new_closed_closed(default, default),
75 }
76 }
77 pub fn init(r: Interval<T>) -> Self {
79 Self {
80 rtype: RangeType::Regular,
81 range: r,
82 }
83 }
84 pub fn get_lower(&self) -> T {
85 self.range.lower().unwrap().clone()
86 }
87
88 pub fn get_upper(&self) -> T {
90 self.range.upper().unwrap().clone()
91 }
92
93 pub fn is_unknown(&self) -> bool {
103 self.rtype == RangeType::Unknown
104 }
105
106 pub fn set_unknown(&mut self) {
108 self.rtype = RangeType::Unknown;
109 }
110
111 pub fn is_regular(&self) -> bool {
113 self.rtype == RangeType::Regular
114 }
115
116 pub fn set_regular(&mut self) {
118 self.rtype = RangeType::Regular;
119 }
120
121 pub fn is_empty(&self) -> bool {
123 self.rtype == RangeType::Empty
124 }
125
126 pub fn set_empty(&mut self) {
128 self.rtype = RangeType::Empty;
129 }
130 pub fn set_default(&mut self) {
131 self.rtype = RangeType::Regular;
132 self.range = Interval::new_closed_closed(T::min_value(), T::max_value());
133 }
134 pub fn add(&self, other: &Range<T>) -> Range<T> {
135 let a = self
136 .get_lower()
137 .clone()
138 .checked_add(&other.get_lower().clone())
139 .unwrap_or(T::max_value());
140
141 let b = self
142 .get_upper()
143 .clone()
144 .checked_add(&other.get_upper().clone())
145 .unwrap_or(T::max_value());
146
147 Range::new(a, b, RangeType::Regular)
148 }
149
150 pub fn sub(&self, other: &Range<T>) -> Range<T> {
151 let a = self
152 .get_lower()
153 .clone()
154 .checked_sub(&other.get_upper().clone())
155 .unwrap_or(T::min_value());
156
157 let b = self
158 .get_upper()
159 .clone()
160 .checked_sub(&other.get_lower().clone())
161 .unwrap_or(T::max_value());
162
163 Range::new(a, b, RangeType::Regular)
164 }
165
166 pub fn mul(&self, other: &Range<T>) -> Range<T> {
167 let candidates = vec![
168 self.get_lower().clone() * other.get_lower().clone(),
169 self.get_lower().clone() * other.get_upper().clone(),
170 self.get_upper().clone() * other.get_lower().clone(),
171 self.get_upper().clone() * other.get_upper().clone(),
172 ];
173 let min = candidates
174 .iter()
175 .cloned()
176 .min_by(|a, b| a.partial_cmp(b).unwrap())
177 .unwrap();
178 let max = candidates
179 .iter()
180 .cloned()
181 .max_by(|a, b| a.partial_cmp(b).unwrap())
182 .unwrap();
183 Range::new(min, max, RangeType::Regular)
184 }
185
186 pub fn intersectwith(&self, other: &Range<T>) -> Range<T> {
187 if self.is_unknown() {
188 return Range::new(
189 other.get_lower().clone(),
190 other.get_upper().clone(),
191 RangeType::Regular,
192 );
193 } else if other.is_unknown() {
194 return Range::new(
195 self.get_lower().clone(),
196 self.get_upper().clone(),
197 RangeType::Regular,
198 );
199 } else {
200 let result = self.range.clone().intersection(&other.range.clone());
201 let mut range = Range::default(T::min_value());
202
203 if let r = result {
204 range = Range::init(r);
205 range
206 } else {
207 range
208 }
209
210 }
223 }
224 pub fn unionwith(&self, other: &Range<T>) -> Range<T> {
225 if self.is_unknown() {
226 return Range::new(
227 other.get_lower().clone(),
228 other.get_upper().clone(),
229 RangeType::Regular,
230 );
231 } else if other.is_unknown() {
232 return Range::new(
233 self.get_lower().clone(),
234 self.get_upper().clone(),
235 RangeType::Regular,
236 );
237 } else {
238 let left = std::cmp::min_by(self.get_lower(), other.get_lower(), |a, b| {
239 a.partial_cmp(b).unwrap()
240 });
241 let right = std::cmp::max_by(self.get_upper(), other.get_upper(), |a, b| {
242 a.partial_cmp(b).unwrap()
243 });
244 Range::new(left.clone(), right.clone(), RangeType::Regular)
245 }
246 }
247 }
264
265pub struct Meet;
267
268impl Meet {
269 pub fn widen<'tcx, T: IntervalArithmetic + ConstConvert>(
270 op: &mut BasicOpKind<'tcx, T>,
271 constant_vector: &[T],
272 vars: &mut VarNodes<'tcx, T>,
273 ) -> bool {
274 let old_interval = op.get_intersect().get_range().clone();
279 let new_interval = op.eval(vars);
280 let old_lower = old_interval.get_lower();
281 let old_upper = old_interval.get_upper();
282 let new_lower = new_interval.get_lower();
283 let new_upper = new_interval.get_upper();
284 let nlconstant = new_lower.clone();
285 let nuconstant = new_upper.clone();
286 let updated = if old_interval.is_unknown() {
287 new_interval
288 } else if new_lower < old_lower && new_upper > old_upper {
289 Range::new(nlconstant, nuconstant, RangeType::Regular)
290 } else if new_lower < old_lower {
291 Range::new(nlconstant, old_upper.clone(), RangeType::Regular)
292 } else if new_upper > old_upper {
293 Range::new(old_lower.clone(), nuconstant, RangeType::Regular)
294 } else {
295 old_interval.clone()
296 };
297
298 op.set_intersect(updated.clone());
299 let sink = op.get_sink();
300 let new_sink_interval = op.get_intersect().get_range().clone();
301 vars.get_mut(sink)
302 .unwrap()
303 .set_range(new_sink_interval.clone());
304 rap_trace!(
305 "WIDEN::{:?}: {:?} -> {:?}",
306 sink,
307 old_interval.range,
308 new_sink_interval
309 );
310 old_interval.range != new_sink_interval.range
311 }
312 pub fn narrow<'tcx, T: IntervalArithmetic + ConstConvert>(
313 op: &mut BasicOpKind<'tcx, T>,
314 vars: &mut VarNodes<'tcx, T>,
315 ) -> bool {
316 let old_range = vars[op.get_sink()].get_range();
317 let o_lower = old_range.get_lower().clone();
318 let o_upper = old_range.get_upper().clone();
319
320 let new_range = op.eval(vars);
321 let n_lower = new_range.get_lower().clone();
322 let n_upper = new_range.get_upper().clone();
323
324 let mut has_changed = false;
325 let min = T::min_value();
326 let max = T::max_value();
327
328 let mut result_lower = o_lower.clone();
329 let mut result_upper = o_upper.clone();
330
331 if o_lower == min && n_lower != min {
332 result_lower = n_lower;
333 has_changed = true;
334 } else {
335 let smin = T::min_value();
337 if o_lower != smin {
338 result_lower = smin;
339 has_changed = true;
340 }
341 }
342
343 if o_upper == max && n_upper != max {
344 result_upper = n_upper;
345 has_changed = true;
346 } else {
347 let smax = T::max_value();
349 if o_upper != smax {
350 result_upper = smax;
351 has_changed = true;
352 }
353 }
354
355 if has_changed {
356 let new_sink_range = Range::new(
357 result_lower.clone(),
358 result_upper.clone(),
359 RangeType::Regular,
360 );
361 let sink_node = vars.get_mut(op.get_sink()).unwrap();
362 sink_node.set_range(new_sink_range.clone());
363
364 }
371
372 has_changed
373 }
374}