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},
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
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 = 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 = 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 = 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 }
387
388 has_changed
389 }
390}