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

1#![allow(unused_imports)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4#![allow(unused_assignments)]
5use std::{default, fmt};
6
7use bounds::Bound;
8use intervals::*;
9use num_traits::{Bounded, Num, Zero};
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_unchecked(bounds::Closed(lb), bounds::Closed(ub)),
68        }
69    }
70    pub fn default(default: T) -> Self {
71        Self {
72            rtype: RangeType::Unknown,
73
74            range: Interval::new_unchecked(
75                bounds::Closed(T::min_value()),
76                bounds::Closed(T::max_value()),
77            ),
78        }
79    }
80    // Getter for lower bound
81    pub fn init(r: Closed<T>) -> Self {
82        Self {
83            rtype: RangeType::Regular,
84            range: r,
85        }
86    }
87    pub fn get_lower(&self) -> T {
88        self.range.left.0.clone()
89    }
90
91    // Getter for upper bound
92    pub fn get_upper(&self) -> T {
93        self.range.right.0.clone()
94    }
95
96    // Setter for lower bound
97    pub fn set_lower(&mut self, newl: T) {
98        self.range.left.0 = newl;
99    }
100
101    // Setter for upper bound
102    pub fn set_upper(&mut self, newu: T) {
103        self.range.right.0 = newu;
104    }
105
106    // Check if the range type is unknown
107    pub fn is_unknown(&self) -> bool {
108        self.rtype == RangeType::Unknown
109    }
110
111    // Set the range type to unknown
112    pub fn set_unknown(&mut self) {
113        self.rtype = RangeType::Unknown;
114    }
115
116    // Check if the range type is regular
117    pub fn is_regular(&self) -> bool {
118        self.rtype == RangeType::Regular
119    }
120
121    // Set the range type to regular
122    pub fn set_regular(&mut self) {
123        self.rtype = RangeType::Regular;
124    }
125
126    // Check if the range type is empty
127    pub fn is_empty(&self) -> bool {
128        self.rtype == RangeType::Empty
129    }
130
131    // Set the range type to empty
132    pub fn set_empty(&mut self) {
133        self.rtype = RangeType::Empty;
134    }
135    pub fn set_default(&mut self) {
136        self.rtype = RangeType::Regular;
137        self.range.left.0 = T::min_value();
138        self.range.right.0 = T::max_value();
139    }
140    pub fn add(&self, other: &Range<T>) -> Range<T> {
141        let a = self
142            .get_lower()
143            .clone()
144            .checked_add(&other.get_lower().clone())
145            .unwrap_or(T::max_value());
146
147        let b = self
148            .get_upper()
149            .clone()
150            .checked_add(&other.get_upper().clone())
151            .unwrap_or(T::max_value());
152
153        Range::new(a, b, RangeType::Regular)
154    }
155
156    pub fn sub(&self, other: &Range<T>) -> Range<T> {
157        let a = self
158            .get_lower()
159            .clone()
160            .checked_sub(&other.get_upper().clone())
161            .unwrap_or(T::min_value());
162
163        let b = self
164            .get_upper()
165            .clone()
166            .checked_sub(&other.get_lower().clone())
167            .unwrap_or(T::max_value());
168
169        Range::new(a, b, RangeType::Regular)
170    }
171
172    pub fn mul(&self, other: &Range<T>) -> Range<T> {
173        let candidates = vec![
174            self.get_lower().clone() * other.get_lower().clone(),
175            self.get_lower().clone() * other.get_upper().clone(),
176            self.get_upper().clone() * other.get_lower().clone(),
177            self.get_upper().clone() * other.get_upper().clone(),
178        ];
179        let min = candidates
180            .iter()
181            .cloned()
182            .min_by(|a, b| a.partial_cmp(b).unwrap())
183            .unwrap();
184        let max = candidates
185            .iter()
186            .cloned()
187            .max_by(|a, b| a.partial_cmp(b).unwrap())
188            .unwrap();
189        Range::new(min, max, RangeType::Regular)
190    }
191
192    pub fn intersectwith(&self, other: &Range<T>) -> Range<T> {
193        if self.is_unknown() {
194            return Range::new(
195                other.get_lower().clone(),
196                other.get_upper().clone(),
197                RangeType::Regular,
198            );
199        } else if other.is_unknown() {
200            return Range::new(
201                self.get_lower().clone(),
202                self.get_upper().clone(),
203                RangeType::Regular,
204            );
205        } else {
206            let result = self.range.clone().intersect(other.range.clone());
207            let result = self.range.clone().intersect(other.range.clone());
208            let mut range = Range::default(T::min_value());
209
210            if let Some(r) = result {
211                range = Range::init(r);
212                range
213            } else {
214                range
215            }
216
217            // let left = std::cmp::max_by(self.get_lower(), other.get_lower(), |a, b| {
218            //     a.partial_cmp(b).unwrap()
219            // });
220            // let right = std::cmp::min_by(self.get_upper(), other.get_upper(), |a, b| {
221            //     a.partial_cmp(b).unwrap()
222            // });
223            // if left <= right {
224            //     Range::new(left.clone(), right.clone(), RangeType::Regular)
225            // } else {
226            //     let empty = T::min_value();
227            //     Range::new(empty.clone(), empty, RangeType::Empty)
228            // }
229        }
230    }
231    pub fn unionwith(&self, other: &Range<T>) -> Range<T> {
232        if self.is_unknown() {
233            return Range::new(
234                other.get_lower().clone(),
235                other.get_upper().clone(),
236                RangeType::Regular,
237            );
238        } else if other.is_unknown() {
239            return Range::new(
240                self.get_lower().clone(),
241                self.get_upper().clone(),
242                RangeType::Regular,
243            );
244        } else {
245            let left = std::cmp::min_by(self.get_lower(), other.get_lower(), |a, b| {
246                a.partial_cmp(b).unwrap()
247            });
248            let right = std::cmp::max_by(self.get_upper(), other.get_upper(), |a, b| {
249                a.partial_cmp(b).unwrap()
250            });
251            Range::new(left.clone(), right.clone(), RangeType::Regular)
252        }
253    }
254    // Check if the range is the maximum range
255    // pub fn is_max_range(&self) -> bool {
256    //     self.range.lower() == T::min_value() && self.range.upper() == T::max_value()
257    // }
258
259    // // Print the range
260    // pub fn print(&self) {
261    //     println!("Range: [{} - {}]", self.get_lower(), self.get_upper());
262    // }
263
264    // // Arithmetic and bitwise operations (example for addition)
265    // pub fn add(&self, other: &Range<T>) -> Range<T> {
266    //     let lower = self.get_lower() + other.get_lower();
267    //     let upper = self.get_upper() + other.get_upper();
268    //     Range::with_bounds(lower, upper, RangeType::Regular)
269    // }
270}
271
272// Implement the comparison operators
273pub struct Meet;
274
275impl Meet {
276    pub fn widen<'tcx, T: IntervalArithmetic + ConstConvert + fmt::Debug>(
277        op: &mut BasicOpKind<'tcx, T>,
278        constant_vector: &[T],
279        vars: &mut VarNodes<'tcx, T>,
280    ) -> bool {
281        // use crate::range_util::{get_first_less_from_vector, get_first_greater_from_vector};
282
283        // assert!(!constant_vector.is_empty(), "Invalid constant vector");
284
285        let old_interval = op.get_intersect().get_range().clone();
286        let new_interval = op.eval(vars);
287
288        let old_lower = old_interval.get_lower();
289        let old_upper = old_interval.get_upper();
290        let new_lower = new_interval.get_lower();
291        let new_upper = new_interval.get_upper();
292
293        // let nlconstant = get_first_less_from_vector(constant_vector, new_lower);
294        // let nuconstant = get_first_greater_from_vector(constant_vector, new_upper);
295        // let nlconstant = constant_vector
296        //     .iter()
297        //     .find(|&&c| c <= new_lower)
298        //     .cloned()
299        //     .unwrap_or(T::min_value());
300        // let nuconstant = constant_vector
301        //     .iter()
302        //     .find(|&&c| c >= new_upper)
303        //     .cloned()
304        //     .unwrap_or(T::max_value());
305        let nlconstant = new_lower.clone();
306        let nuconstant = new_upper.clone();
307        let updated = if old_interval.is_unknown() {
308            new_interval
309        } else if new_lower < old_lower && new_upper > old_upper {
310            Range::new(nlconstant, nuconstant, RangeType::Regular)
311        } else if new_lower < old_lower {
312            Range::new(nlconstant, old_upper.clone(), RangeType::Regular)
313        } else if new_upper > old_upper {
314            Range::new(old_lower.clone(), nuconstant, RangeType::Regular)
315        } else {
316            old_interval.clone()
317        };
318
319        op.set_intersect(updated.clone());
320
321        let sink = op.get_sink();
322        let new_sink_interval = op.get_intersect().get_range().clone();
323        vars.get_mut(sink)
324            .unwrap()
325            .set_range(new_sink_interval.clone());
326        rap_trace!(
327            "WIDEN::{:?}: {:?} -> {:?}",
328            sink,
329            old_interval,
330            new_sink_interval
331        );
332
333        old_interval != new_sink_interval
334    }
335    pub fn narrow<'tcx, T: IntervalArithmetic + ConstConvert + fmt::Debug>(
336        op: &mut BasicOpKind<'tcx, T>,
337        vars: &mut VarNodes<'tcx, T>,
338    ) -> bool {
339        let old_range = vars[op.get_sink()].get_range();
340        let o_lower = old_range.get_lower().clone();
341        let o_upper = old_range.get_upper().clone();
342
343        let new_range = op.eval(vars);
344        let n_lower = new_range.get_lower().clone();
345        let n_upper = new_range.get_upper().clone();
346
347        let mut has_changed = false;
348        let min = T::min_value();
349        let max = T::max_value();
350
351        let mut result_lower = o_lower.clone();
352        let mut result_upper = o_upper.clone();
353
354        if o_lower == min && n_lower != min {
355            result_lower = n_lower;
356            has_changed = true;
357        } else {
358            // let smin = o_lower.clone().min(n_lower.clone());
359            let smin = T::min_value();
360            if o_lower != smin {
361                result_lower = smin;
362                has_changed = true;
363            }
364        }
365
366        if o_upper == max && n_upper != max {
367            result_upper = n_upper;
368            has_changed = true;
369        } else {
370            // let smax = o_upper.clone().max(n_upper.clone());
371            let smax = T::max_value();
372            if o_upper != smax {
373                result_upper = smax;
374                has_changed = true;
375            }
376        }
377
378        if has_changed {
379            let new_sink_range = Range::new(
380                result_lower.clone(),
381                result_upper.clone(),
382                RangeType::Regular,
383            );
384            let sink_node = vars.get_mut(op.get_sink()).unwrap();
385            sink_node.set_range(new_sink_range.clone());
386
387            // println!(
388            //     "NARROW::{}: {:?} -> {:?}",
389            // ,
390            //     Range::new(o_lower, o_upper),
391            //     new_sink_range
392            // );
393        }
394
395        has_changed
396    }
397}