rapx/analysis/core/range_analysis/domain/
range.rs

1#![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};
11// use std::ops::Range;
12use std::ops::{Add, Mul, Sub};
13
14use crate::{
15    analysis::core::range_analysis::{Range, RangeType},
16    rap_trace,
17};
18
19use super::domain::*;
20
21// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22//     let lower: &Lazy<String> = if self.range.left.0 == T::min_value() {
23//         &STR_MIN
24//     } else if self.range.left.0 == T::max_value() {
25//         &STR_MAX
26//     } else {
27//         static DUMMY: Lazy<String> = Lazy::new(|| String::new());
28//         let tmp = format!("{}", self.range.left.0);
29//         let tmp_clone = tmp.clone();
30//         let local = Lazy::new(|| tmp);
31//         return write!(
32//             f,
33//             "{} [{}, {}]",
34//             self.rtype,
35//             *local,
36//             if self.range.right.0 == T::min_value() {
37//                 &*STR_MIN
38//             } else if self.range.right.0 == T::max_value() {
39//                 &*STR_MAX
40//             } else {
41//                 return write!(f, "{} [{}, {}]", self.rtype, tmp_clone, self.range.right.0);
42//             }
43//         );
44//     };
45
46//     let upper: &Lazy<String> = if self.range.right.0 == T::min_value() {
47//         &STR_MIN
48//     } else if self.range.right.0 == T::max_value() {
49//         &STR_MAX
50//     } else {
51//         let tmp = format!("{}", self.range.right.0);
52//         let local = Lazy::new(|| tmp);
53//         return write!(f, "{} [{}, {}]", self.rtype, &**lower, *local);
54//     };
55
56//     write!(f, "{} [{}, {}]", self.rtype, &**lower, &**upper)
57// }
58
59impl<T> Range<T>
60where
61    T: IntervalArithmetic,
62{
63    // Parameterized constructor
64    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    // Getter for lower bound
78    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    // Getter for upper bound
89    pub fn get_upper(&self) -> T {
90        self.range.upper().unwrap().clone()
91    }
92
93    // // Setter for lower bound
94    // pub fn set_lower(&mut self, newl: T) {
95    // }
96
97    // // Setter for upper bound
98    // pub fn set_upper(&mut self, newu: T) {
99    // }
100
101    // Check if the range type is unknown
102    pub fn is_unknown(&self) -> bool {
103        self.rtype == RangeType::Unknown
104    }
105
106    // Set the range type to unknown
107    pub fn set_unknown(&mut self) {
108        self.rtype = RangeType::Unknown;
109    }
110
111    // Check if the range type is regular
112    pub fn is_regular(&self) -> bool {
113        self.rtype == RangeType::Regular
114    }
115
116    // Set the range type to regular
117    pub fn set_regular(&mut self) {
118        self.rtype = RangeType::Regular;
119    }
120
121    // Check if the range type is empty
122    pub fn is_empty(&self) -> bool {
123        self.rtype == RangeType::Empty
124    }
125
126    // Set the range type to empty
127    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            // let left = std::cmp::max_by(self.get_lower(), other.get_lower(), |a, b| {
211            //     a.partial_cmp(b).unwrap()
212            // });
213            // let right = std::cmp::min_by(self.get_upper(), other.get_upper(), |a, b| {
214            //     a.partial_cmp(b).unwrap()
215            // });
216            // if left <= right {
217            //     Range::new(left.clone(), right.clone(), RangeType::Regular)
218            // } else {
219            //     let empty = T::min_value();
220            //     Range::new(empty.clone(), empty, RangeType::Empty)
221            // }
222        }
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    // Check if the range is the maximum range
248    // pub fn is_max_range(&self) -> bool {
249    //     self.range.lower() == T::min_value() && self.range.upper() == T::max_value()
250    // }
251
252    // // Print the range
253    // pub fn print(&self) {
254    //     println!("Range: [{} - {}]", self.get_lower(), self.get_upper());
255    // }
256
257    // // Arithmetic and bitwise operations (example for addition)
258    // pub fn add(&self, other: &Range<T>) -> Range<T> {
259    //     let lower = self.get_lower() + other.get_lower();
260    //     let upper = self.get_upper() + other.get_upper();
261    //     Range::with_bounds(lower, upper, RangeType::Regular)
262    // }
263}
264
265// Implement the comparison operators
266pub 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        // use crate::range_util::{get_first_less_from_vector, get_first_greater_from_vector};
275
276        // assert!(!constant_vector.is_empty(), "Invalid constant vector");
277
278        let old_interval = op.get_intersect().get_range().clone();
279        let new_interval = op.eval(vars);
280
281        let old_lower = old_interval.get_lower();
282        let old_upper = old_interval.get_upper();
283        let new_lower = new_interval.get_lower();
284        let new_upper = new_interval.get_upper();
285
286        // let nlconstant = get_first_less_from_vector(constant_vector, new_lower);
287        // let nuconstant = get_first_greater_from_vector(constant_vector, new_upper);
288        // let nlconstant = constant_vector
289        //     .iter()
290        //     .find(|&&c| c <= new_lower)
291        //     .cloned()
292        //     .unwrap_or(T::min_value());
293        // let nuconstant = constant_vector
294        //     .iter()
295        //     .find(|&&c| c >= new_upper)
296        //     .cloned()
297        //     .unwrap_or(T::max_value());
298        let nlconstant = new_lower.clone();
299        let nuconstant = new_upper.clone();
300        let updated = if old_interval.is_unknown() {
301            new_interval
302        } else if new_lower < old_lower && new_upper > old_upper {
303            Range::new(nlconstant, nuconstant, RangeType::Regular)
304        } else if new_lower < old_lower {
305            Range::new(nlconstant, old_upper.clone(), RangeType::Regular)
306        } else if new_upper > old_upper {
307            Range::new(old_lower.clone(), nuconstant, RangeType::Regular)
308        } else {
309            old_interval.clone()
310        };
311
312        op.set_intersect(updated.clone());
313
314        let sink = op.get_sink();
315        let new_sink_interval = op.get_intersect().get_range().clone();
316        vars.get_mut(sink)
317            .unwrap()
318            .set_range(new_sink_interval.clone());
319        rap_trace!(
320            "WIDEN::{:?}: {:?} -> {:?}",
321            sink,
322            old_interval.range,
323            new_sink_interval
324        );
325
326        old_interval.range != new_sink_interval.range
327    }
328    pub fn narrow<'tcx, T: IntervalArithmetic + ConstConvert>(
329        op: &mut BasicOpKind<'tcx, T>,
330        vars: &mut VarNodes<'tcx, T>,
331    ) -> bool {
332        let old_range = vars[op.get_sink()].get_range();
333        let o_lower = old_range.get_lower().clone();
334        let o_upper = old_range.get_upper().clone();
335
336        let new_range = op.eval(vars);
337        let n_lower = new_range.get_lower().clone();
338        let n_upper = new_range.get_upper().clone();
339
340        let mut has_changed = false;
341        let min = T::min_value();
342        let max = T::max_value();
343
344        let mut result_lower = o_lower.clone();
345        let mut result_upper = o_upper.clone();
346
347        if o_lower == min && n_lower != min {
348            result_lower = n_lower;
349            has_changed = true;
350        } else {
351            // let smin = o_lower.clone().min(n_lower.clone());
352            let smin = T::min_value();
353            if o_lower != smin {
354                result_lower = smin;
355                has_changed = true;
356            }
357        }
358
359        if o_upper == max && n_upper != max {
360            result_upper = n_upper;
361            has_changed = true;
362        } else {
363            // let smax = o_upper.clone().max(n_upper.clone());
364            let smax = T::max_value();
365            if o_upper != smax {
366                result_upper = smax;
367                has_changed = true;
368            }
369        }
370
371        if has_changed {
372            let new_sink_range = Range::new(
373                result_lower.clone(),
374                result_upper.clone(),
375                RangeType::Regular,
376            );
377            let sink_node = vars.get_mut(op.get_sink()).unwrap();
378            sink_node.set_range(new_sink_range.clone());
379
380            // println!(
381            //     "NARROW::{}: {:?} -> {:?}",
382            // ,
383            //     Range::new(o_lower, o_upper),
384            //     new_sink_range
385            // );
386        }
387
388        has_changed
389    }
390}