rapx/analysis/core/range_analysis/domain/
range.rs1#![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};
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_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 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 pub fn get_upper(&self) -> T {
93 self.range.right.0.clone()
94 }
95
96 pub fn set_lower(&mut self, newl: T) {
98 self.range.left.0 = newl;
99 }
100
101 pub fn set_upper(&mut self, newu: T) {
103 self.range.right.0 = newu;
104 }
105
106 pub fn is_unknown(&self) -> bool {
108 self.rtype == RangeType::Unknown
109 }
110
111 pub fn set_unknown(&mut self) {
113 self.rtype = RangeType::Unknown;
114 }
115
116 pub fn is_regular(&self) -> bool {
118 self.rtype == RangeType::Regular
119 }
120
121 pub fn set_regular(&mut self) {
123 self.rtype = RangeType::Regular;
124 }
125
126 pub fn is_empty(&self) -> bool {
128 self.rtype == RangeType::Empty
129 }
130
131 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 }
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 }
271
272pub 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 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 = 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 = 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 = 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 }
394
395 has_changed
396 }
397}