Static Value-Flow Analysis
Loading...
Searching...
No Matches
IntervalValue.h
Go to the documentation of this file.
1//===- IntervalValue.h ----Interval Value for Abstract Domain-------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2022> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22/*
23 * IntervalValue.h
24 *
25 * Created on: Aug 4, 2022
26 * Author: Jiawei Wang, Xiao Cheng
27 *
28 */
29// The implementation is based on
30// Xiao Cheng, Jiawei Wang and Yulei Sui. Precise Sparse Abstract Execution via Cross-Domain Interaction.
31// 46th International Conference on Software Engineering. (ICSE24)
32
33#ifndef Z3_EXAMPLE_IntervalValue_H
34#define Z3_EXAMPLE_IntervalValue_H
35
36#include <sstream>
38
39namespace SVF
40{
41
46{
47private:
48 // Lower bound
50
51 // Upper bound
53
54 // Invariant: isBottom() <=> _lb = +inf && _ub = -inf
55public:
65
66 bool isTop() const
67 {
69 }
70
71 bool isBottom() const
72 {
74 }
75
78 {
80 }
81
84 {
86 }
87
88 static bool is_infinite(const BoundedInt &e)
89 {
90 return e.is_infinity();
91 }
92
95 {
97 }
98
101 {
103 }
104
107
109 explicit IntervalValue(s64_t n) : _lb(n), _ub(n) {}
110
112
114
115 explicit IntervalValue(double n) : _lb(n), _ub(n) {}
116
118
120 explicit IntervalValue(BoundedInt lb, BoundedInt ub) : _lb(std::move(lb)), _ub(std::move(ub))
121 {
122 assert((isBottom() || _lb.leq(_ub)) && "lower bound should be less than or equal to upper bound");
123 }
124
126
127 explicit IntervalValue(double lb, double ub) : IntervalValue(BoundedInt(lb), BoundedInt(ub)) {}
128
129 explicit IntervalValue(float lb, float ub) : IntervalValue(BoundedInt(lb), BoundedInt(ub)) {}
130
132
134
136
138 IntervalValue(const IntervalValue &) = default;
139
142
145
148
151 {
152 if (this->isBottom() || other.isBottom())
153 {
154 return bottom();
155 }
156 else if (this->isTop() || other.isTop())
157 {
158 return top();
159 }
160 else
161 {
162 if (this->is_numeral() && other.is_numeral())
163 {
164 return eq(this->_lb, other._lb) ? IntervalValue(1, 1) : IntervalValue(0, 0);
165 }
166 else
167 {
168 IntervalValue value = *this;
169 value.meet_with(other);
170 if (value.isBottom())
171 {
172 return IntervalValue(0, 0);
173 }
174 else
175 {
176 // return top();
177 return IntervalValue(0, 1);
178 }
179 }
180 }
181 }
182
185 {
186 if (this->isBottom() || other.isBottom())
187 {
188 return bottom();
189 }
190 else if (this->isTop() || other.isTop())
191 {
192 return top();
193 }
194 else
195 {
196 if (this->is_numeral() && other.is_numeral())
197 {
198 return eq(this->_lb, other._lb) ? IntervalValue(0, 0) : IntervalValue(1, 1);
199 }
200 else
201 {
202 IntervalValue value = *this;
203 value.meet_with(other);
204 if (!value.isBottom())
205 {
206 return IntervalValue(0, 1);
207 }
208 else
209 {
210 return IntervalValue(1, 1);
211 }
212 }
213 }
214 }
215
217 ~IntervalValue() = default;
218
220 const BoundedInt &lb() const
221 {
222 assert(!this->isBottom() && "bottom interval does not have lower bound");
223 return this->_lb;
224 }
225
227 const BoundedInt &ub() const
228 {
229 assert(!this->isBottom() && "bottom interval does not have upper bound");
230 return this->_ub;
231 }
232
234 bool is_zero() const
235 {
236 return _lb.is_zero() && _ub.is_zero();
237 }
238
240 bool is_infinite() const
241 {
242 return _lb.is_infinity() || _ub.is_infinity();
243 }
244
245 bool is_int() const
246 {
247 return !is_real();
248 }
249
250 bool is_real() const
251 {
252 bool lb_real = _lb.is_real();
253 bool ub_real = _ub.is_real();
254 return lb_real || ub_real;
255 }
256
259 {
260 assert(is_numeral() && "this IntervalValue is not numeral");
261 return _lb.getNumeral();
262 }
263
265 {
266 assert(is_numeral() && "this IntervalValue is not numeral");
267 return _lb.getIntNumeral();
268 }
269
270 double getRealNumeral() const
271 {
272 assert(is_numeral() && "this IntervalValue is not numeral");
273 return _lb.getRealNumeral();
274 }
275
277 bool is_numeral() const
278 {
279 return eq(_lb, _ub);
280 }
281
284 {
285 this->_lb = plus_infinity();
286 this->_ub = minus_infinity();
287 }
288
291 {
292 this->_lb = minus_infinity();
293 this->_ub = plus_infinity();
294 }
295
301 {
302 if (this->isBottom())
303 {
304 return true;
305 }
306 else if (other.isBottom())
307 {
308 return false;
309 }
310 else
311 {
312 return other._lb.leq(this->_lb) && this->_ub.leq(other._ub);
313 }
314
315 }
316
321 bool contain(const IntervalValue &other) const
322 {
323 if (this->isBottom())
324 {
325 return true;
326 }
327 else if (other.isBottom())
328 {
329 return false;
330 }
331 else
332 {
333 return other._lb.geq(this->_lb) && this->_ub.geq(other._ub);
334 }
335 }
336
339 bool leq(const IntervalValue &other) const
340 {
341 if (this->isBottom())
342 {
343 return true;
344 }
345 else if (other.isBottom())
346 {
347 return false;
348 }
349 else
350 {
351 return this->_ub.leq(other._lb);
352 }
353 }
354
357 bool geq(const IntervalValue &other) const
358 {
359 if (this->isBottom())
360 {
361 return true;
362 }
363 else if (other.isBottom())
364 {
365 return false;
366 }
367 else
368 {
369 return this->_lb.geq(other._ub);
370 }
371 }
372
373
375 bool equals(const IntervalValue &other) const
376 {
377 if (this->isBottom())
378 {
379 return other.isBottom();
380 }
381 else if (other.isBottom())
382 {
383 return false;
384 }
385 else
386 {
387 if (this->is_real() && other.is_real())
388 {
389 return this->_lb.equal(other._lb) && this->_ub.equal(other._ub);
390 }
391 else if (this->is_int() && other.is_int())
392 {
393 return this->_lb.equal(other._lb) && this->_ub.equal(other._ub);
394 }
395 else if (this->is_int())
396 {
397 double thislb = this->_lb.getIntNumeral();
398 double thisub = this->_ub.getIntNumeral();
399 double otherlb = other._lb.getRealNumeral();
400 double otherub = other._ub.getRealNumeral();
401 return thislb == otherlb && thisub == otherub;
402 }
403 else
404 {
405 double thislb = this->_lb.getRealNumeral();
406 double thisub = this->_ub.getRealNumeral();
407 double otherlb = other._lb.getIntNumeral();
408 double otherub = other._ub.getIntNumeral();
409 return thislb == otherlb && thisub == otherub;
410 }
411 assert(false && "not implemented");
412 }
413 }
414
417 {
418 if (this->isBottom())
419 {
420 if (other.isBottom())
421 {
422 return;
423 }
424 else
425 {
426 setValue(other.lb(), other.ub());
427 }
428 }
429 else if (other.isBottom())
430 {
431 return;
432 }
433 else
434 {
435 setValue(min(this->lb(), other.lb()), max(this->ub(), other.ub()));
436 }
437 }
438
441 {
442 if (this->isBottom())
443 {
444 this->_lb = other._lb;
445 this->_ub = other._ub;
446 }
447 else if (other.isBottom())
448 {
449 return;
450 }
451 else
452 {
453 setValue(!lb().leq(other.lb()) ? minus_infinity() : this->lb(), !ub().geq(other.ub()) ? plus_infinity() : this->ub());
454 }
455 }
456
459 {
460 if (this->isBottom() || other.isBottom())
461 {
462 this->set_to_bottom();
463 }
464 else if (other.isBottom())
465 {
466 return;
467 }
468 else
469 {
470 setValue(is_infinite(this->lb()) ? other._lb : this->_lb, is_infinite(this->ub()) ? other._ub : this->_ub);
471 }
472 }
473
476 {
477 if (this->isBottom() || other.isBottom())
478 {
479 this->set_to_bottom();
480 }
481 else
482 {
483 if (!(max(this->_lb, other.lb()).leq(min(this->_ub, other.ub()))))
484 {
485 this->set_to_bottom();
486 }
487 else
488 {
489 setValue(max(this->_lb, other.lb()), min(this->_ub, other.ub()));
490 }
491 }
492 }
493
495 bool contains(int n) const
496 {
497 return this->_lb.leq(n) && this->_ub.geq(n);
498 }
499
500 void dump(std::ostream &o) const
501 {
502 if (this->isBottom())
503 {
504 o << "⊥";
505 }
506 else
507 {
508 o << "[" << this->_lb << ", " << this->_ub << "]";
509 }
510 }
511
512 const std::string toString() const
513 {
514 std::string str;
515 std::stringstream rawStr(str);
516 if (this->isBottom())
517 {
518 rawStr << "⊥";
519 }
520 else
521 {
522 rawStr << "[" << lb().to_string() << ", " << ub().to_string() << "]";
523 }
524 return rawStr.str();
525 }
526private:
528 void setValue(const BoundedInt &lb, const BoundedInt &ub)
529 {
530 assert((isBottom() || _lb.leq(_ub)) && "lower bound should be less than or equal to upper bound");
531 this->_lb = lb;
532 this->_ub = ub;
533 }
534
535private:
536 // internal use for create bottom-tolerant IntervalValue
538 {
539 if (!lb.leq(ub))
540 return IntervalValue::bottom();
541 else
542 return IntervalValue(lb, ub);
543 }
544}; // end class IntervalValue
545
548 const IntervalValue &rhs)
549{
550 if (lhs.isBottom() || rhs.isBottom())
551 {
552 return IntervalValue::bottom();
553 }
554 else if (lhs.isTop() || rhs.isTop())
555 {
556 return IntervalValue::top();
557 }
558 else
559 {
560 return IntervalValue(lhs.lb() + rhs.lb(), lhs.ub() + rhs.ub());
561 }
562}
563
566 const IntervalValue &rhs)
567{
568 if (lhs.isBottom() || rhs.isBottom())
569 {
570 return IntervalValue::bottom();
571 }
572 else if (lhs.isTop() || rhs.isTop())
573 {
574 return IntervalValue::top();
575 }
576 else
577 {
578 return IntervalValue(lhs.lb() - rhs.ub(), lhs.ub() - rhs.lb());
579 }
580}
581
584 const IntervalValue &rhs)
585{
586 if (lhs.isBottom() || rhs.isBottom())
587 {
588 return IntervalValue::bottom();
589 }
590 else
591 {
592 BoundedInt ll = lhs.lb() * rhs.lb();
593 BoundedInt lu = lhs.lb() * rhs.ub();
594 BoundedInt ul = lhs.ub() * rhs.lb();
595 BoundedInt uu = lhs.ub() * rhs.ub();
596 std::vector<BoundedInt> vec{ll, lu, ul, uu};
599 }
600}
601
604 const IntervalValue &rhs)
605{
606 if (lhs.isBottom() || rhs.isBottom())
607 {
608 return IntervalValue::bottom();
609 }
610 else if (rhs.contains(0))
611 {
614 IntervalValue l_res = lhs / lb;
615 IntervalValue r_res = lhs / ub;
617 return l_res;
618 }
619 else if (lhs.contains(0))
620 {
623 IntervalValue l_res = lb / rhs;
624 IntervalValue r_res = ub / rhs;
626 l_res.join_with(IntervalValue(0));
627 return l_res;
628 }
629 else
630 {
631 // Neither the dividend nor the divisor contains 0
632 BoundedInt ll = lhs.lb() / rhs.lb();
633 BoundedInt lu = lhs.lb() / rhs.ub();
634 BoundedInt ul = lhs.ub() / rhs.lb();
635 BoundedInt uu = lhs.ub() / rhs.ub();
636 std::vector<BoundedInt> vec{ll, lu, ul, uu};
637
640 return res;
641 }
642}
643
646 const IntervalValue &rhs)
647{
648 if (lhs.isBottom() || rhs.isBottom())
649 {
650 return IntervalValue::bottom();
651 }
652 else if (rhs.contains(0))
653 {
654 return lhs.is_zero() ? IntervalValue(0, 0) : IntervalValue::top();
655 }
656 else if (lhs.is_numeral() && rhs.is_numeral())
657 {
658 return IntervalValue(lhs.lb() % rhs.lb(), lhs.lb() % rhs.lb());
659 }
660 else
661 {
662 BoundedInt n_ub = max(abs(lhs.lb()), abs(lhs.ub()));
663 BoundedInt d_ub = max(abs(rhs.lb()), rhs.ub()) - 1;
664 BoundedInt ub = min(n_ub, d_ub);
665
666 if (lhs.lb().getNumeral() < 0)
667 {
668 if (lhs.ub().getNumeral() > 0)
669 {
670 return IntervalValue(-ub, ub);
671 }
672 else
673 {
674 return IntervalValue(-ub, 0);
675 }
676 }
677 else
678 {
679 return IntervalValue(0, ub);
680 }
681 }
682}
683
684// Compare two IntervalValues for greater than
686{
687 // If either lhs or rhs is bottom, the result is bottom
688 if (lhs.isBottom() || rhs.isBottom())
689 {
690 return IntervalValue::bottom();
691 }
692 // If either lhs or rhs is top, the result is top
693 else if (lhs.isTop() || rhs.isTop())
694 {
695 return IntervalValue::top();
696 }
697 else
698 {
699 // If both lhs and rhs are numerals (lb = ub), directly compare their values
700 if (lhs.is_numeral() && rhs.is_numeral())
701 {
702 // It means lhs.lb() > rhs.lb()? true: false
703 return lhs.lb().leq(rhs.lb()) ? IntervalValue(0, 0) : IntervalValue(1, 1);
704 }
705 else
706 {
707 // Return [1,1] means lhs is totally greater than rhs
708 // When lhs.lb > rhs.ub, e.g., lhs:[3, 4] rhs:[1, 2]
709 // lhs.lb(3) > rhs.ub(2)
710 // It means lhs.lb() > rhs.ub()
711 if (!lhs.lb().leq(rhs.ub()))
712 {
713 return IntervalValue(1, 1);
714 }
715 // Return [0,0] means lhs is totally impossible to be greater than rhs
716 // i.e., lhs is totally less than or equal to rhs
717 // When lhs.ub <= rhs.lb, e.g., lhs:[3, 4] rhs:[4,5]
718 // lhs.ub(4) <= rhs.lb(4)
719 else if (lhs.ub().leq(rhs.lb()))
720 {
721 return IntervalValue(0, 0);
722 }
723 // For other cases, lhs can be greater than or not, depending on the values
724 // e.g., lhs: [2,4], rhs: [1,3],
725 // lhs can be greater than rhs if lhs is 4 and rhs is 1.
726 // lhs can also not be greater than rhs if lhs is 2 and rhs is 3
727 else
728 {
729 return IntervalValue(0, 1);
730 }
731 }
732 }
733}
734
735// Compare two IntervalValues for less than
737{
738 // If either lhs or rhs is bottom, the result is bottom
739 if (lhs.isBottom() || rhs.isBottom())
740 {
741 return IntervalValue::bottom();
742 }
743 // If either lhs or rhs is top, the result is top
744 else if (lhs.isTop() || rhs.isTop())
745 {
746 return IntervalValue::top();
747 }
748 else
749 {
750 // If both lhs and rhs are numerals (lb = ub), directly compare their values
751 if (lhs.is_numeral() && rhs.is_numeral())
752 {
753 // It means lhs.lb() < rhs.lb()? true: false
754 return lhs.lb().geq(rhs.lb()) ? IntervalValue(0, 0) : IntervalValue(1, 1);
755 }
756 else
757 {
758 // Return [1,1] means lhs is totally less than rhs
759 // When lhs.ub < rhs.lb, e.g., lhs:[1, 2] rhs:[3, 4]
760 // lhs.ub(2) < rhs.lb(3)
761 // It means lhs.ub() < rhs.lb()
762 if (!lhs.ub().geq(rhs.lb()))
763 {
764 return IntervalValue(1, 1);
765 }
766 // Return [0,0] means lhs is totally impossible to be less than rhs
767 // i.e., lhs is totally greater than or equal to rhs
768 // When lhs.lb >= rhs.ub, e.g., lhs:[4,5] rhs:[3,4]
769 // lhs.lb(4) >= rhs.ub(4)
770 else if (lhs.lb().geq(rhs.ub()))
771 {
772 return IntervalValue(0, 0);
773 }
774 // For other cases, lhs can be less than rhs or not, depending on the values
775 // e.g., lhs: [2,4], rhs: [1,3],
776 // lhs can be less than rhs if lhs is 2, rhs is 3.
777 // lhs can also not be less than rhs if lhs is 4 and rhs is 1
778 else
779 {
780 return IntervalValue(0, 1);
781 }
782 }
783 }
784}
785
786
787// Compare two IntervalValues for greater than or equal to
789{
790 // If either lhs or rhs is bottom, the result is bottom
791 if (lhs.isBottom() || rhs.isBottom())
792 {
793 return IntervalValue::bottom();
794 }
795 // If either lhs or rhs is top, the result is top
796 else if (lhs.isTop() || rhs.isTop())
797 {
798 return IntervalValue::top();
799 }
800 else
801 {
802 // If both lhs and rhs are numerals (lb = ub), directly compare their values
803 if (lhs.is_numeral() && rhs.is_numeral())
804 {
805 return lhs.lb().geq(rhs.lb()) ? IntervalValue(1, 1) : IntervalValue(0, 0);
806 }
807 else
808 {
809 // Return [1,1] means lhs is totally greater than or equal to rhs
810 // When lhs.lb >= rhs.ub, e.g., lhs:[2, 3] rhs:[1, 2]
811 // lhs.lb(2) >= rhs.ub(2)
812 if (lhs.lb().geq(rhs.ub()))
813 {
814 return IntervalValue(1, 1);
815 }
816 // Return [0,0] means lhs is totally impossible to be greater than or equal to rhs
817 // i.e., lhs is totally less than rhs
818 // When lhs.ub < rhs.lb, e.g., lhs:[1, 2] rhs:[3, 4]
819 // lhs.ub(2) < rhs.lb(3)
820 // It means lhs.ub() < rhs.lb()
821 else if (!lhs.ub().geq(rhs.lb()))
822 {
823 return IntervalValue(0, 0);
824 }
825 // For other cases, lhs can be greater than or equal to rhs or not, depending on the values
826 // e.g., lhs: [2,4], rhs: [1,3],
827 // lhs can be greater than or equal to rhs if lhs is 3, rhs is 2.
828 // lhs can also not be greater than or equal to rhs if lhs is 2 and rhs is 3
829 else
830 {
831 return IntervalValue(0, 1);
832 }
833 }
834 }
835}
836
837// Compare two IntervalValues for less than or equal to
839{
840 // If either lhs or rhs is bottom, the result is bottom
841 if (lhs.isBottom() || rhs.isBottom())
842 {
843 return IntervalValue::bottom();
844 }
845 // If either lhs or rhs is top, the result is top
846 else if (lhs.isTop() || rhs.isTop())
847 {
848 return IntervalValue::top();
849 }
850 else
851 {
852 // If both lhs and rhs are numerals (lb = ub), directly compare their values
853 if (lhs.is_numeral() && rhs.is_numeral())
854 {
855 return lhs.lb().leq(rhs.lb()) ? IntervalValue(1, 1) : IntervalValue(0, 0);
856 }
857 else
858 {
859 // Return [1,1] means lhs is totally less than or equal to rhs
860 // When lhs.ub <= rhs.lb, e.g., lhs:[1, 2] rhs:[2, 3]
861 // lhs.ub(2) <= rhs.lb(2)
862 if (lhs.ub().leq(rhs.lb()))
863 {
864 return IntervalValue(1, 1);
865 }
866 // Return [0,0] means lhs is totally impossible to be less than or equal to rhs
867 // i.e., lhs is totally greater than rhs
868 // When lhs.lb > rhs.ub, e.g., lhs:[3, 4] rhs:[1, 2]
869 // lhs.lb(3) > rhs.ub(2)
870 // It means lhs.lb() > rhs.ub()
871 else if (!lhs.lb().leq(rhs.ub()))
872 {
873 return IntervalValue(0, 0);
874 }
875 // For other cases, lhs can be less than or equal to rhs or not, depending on the values
876 // e.g., lhs: [2,4], rhs: [1,3],
877 // lhs can be less than or equal to rhs if lhs is 3, rhs is 3.
878 // lhs can also not be less than or equal to rhs if lhs is 3 and rhs is 2
879 else
880 {
881 return IntervalValue(0, 1);
882 }
883 }
884 }
885}
886
889{
890 //TODO: implement <<
891 if (lhs.isBottom() || rhs.isBottom())
892 return IntervalValue::bottom();
893 if (lhs.isTop() && rhs.isTop())
894 return IntervalValue::top();
895 else
896 {
899 if (shift.isBottom())
900 return IntervalValue::bottom();
901 BoundedInt lb = 0;
902 // If the shift is greater than 32, the result is always 0
903 if ((s32_t) shift.lb().getNumeral() >= 32 || shift.lb().is_infinity())
904 {
906 }
907 else
908 {
909 lb = (1 << (s32_t) shift.lb().getNumeral());
910 }
911 BoundedInt ub = 0;
912 if (shift.ub().is_infinity())
913 {
915 }
916 else
917 {
918 ub = (1 << (s32_t) shift.ub().getNumeral());
919 }
920 IntervalValue coeff(lb, ub);
921 return lhs * coeff;
922 }
923}
924
927{
928 //TODO: implement >>
929 if (lhs.isBottom() || rhs.isBottom())
930 return IntervalValue::bottom();
931 else if (lhs.isTop() && rhs.isTop())
932 return IntervalValue::top();
933 else
934 {
937 if (shift.isBottom())
938 return IntervalValue::bottom();
939 if (lhs.contains(0))
940 {
943 IntervalValue tmp = l >> rhs;
944 tmp.join_with(u >> rhs);
945 tmp.join_with(IntervalValue(0));
946 return tmp;
947 }
948 else
949 {
950 BoundedInt ll = lhs.lb() >> shift.lb();
951 BoundedInt lu = lhs.lb() >> shift.ub();
952 BoundedInt ul = lhs.ub() >> shift.lb();
953 BoundedInt uu = lhs.ub() >> shift.ub();
954 std::vector<BoundedInt> vec{ll, lu, ul, uu};
957 }
958 }
959}
960
963{
964 if (lhs.isBottom() || rhs.isBottom())
965 return IntervalValue::bottom();
966 else if (lhs.is_numeral() && rhs.is_numeral())
967 {
968 return IntervalValue(lhs.lb() & rhs.lb());
969 }
970 else if (lhs.lb().getNumeral() >= 0 && rhs.lb().getNumeral() >= 0)
971 {
972 return IntervalValue((s64_t) 0, min(lhs.ub(), rhs.ub()));
973 }
974 else if (lhs.lb().getNumeral() >= 0)
975 {
976 return IntervalValue((s64_t) 0, lhs.ub());
977 }
978 else if (rhs.lb().getNumeral() >= 0)
979 {
980 return IntervalValue((s64_t) 0, rhs.ub());
981 }
982 else
983 {
984 return IntervalValue::top();
985 }
986}
987
990{
991 auto next_power_of_2 = [](s64_t num)
992 {
993 int i = 1;
994 while ((num >> i) != 0)
995 {
996 ++i;
997 }
998 return 1 << i;
999 };
1000 if (lhs.isBottom() || rhs.isBottom())
1001 return IntervalValue::bottom();
1002 else if (lhs.is_numeral() && rhs.is_numeral())
1003 return IntervalValue(lhs.lb() | rhs.lb());
1004 else if (lhs.lb().getNumeral() >= 0 && !lhs.ub().is_infinity() &&
1005 rhs.lb().getNumeral() >= 0 && !rhs.ub().is_infinity())
1006 {
1007 s64_t m = std::max(lhs.ub().getNumeral(), rhs.ub().getNumeral());
1008 s64_t ub = next_power_of_2(s64_t(m)) - 1;
1009 return IntervalValue((s64_t) 0, (s64_t) ub);
1010 }
1011 else
1012 {
1013 return IntervalValue::top();
1014 }
1015}
1016
1019{
1020 auto next_power_of_2 = [](s64_t num)
1021 {
1022 int i = 1;
1023 while ((num >> i) != 0)
1024 {
1025 ++i;
1026 }
1027 return 1 << i;
1028 };
1029 if (lhs.isBottom() || rhs.isBottom())
1030 return IntervalValue::bottom();
1031 else if (lhs.is_numeral() && rhs.is_numeral())
1032 return IntervalValue(lhs.lb() ^ rhs.lb());
1033 else if (lhs.lb().getNumeral() >= 0 && !lhs.ub().is_infinity() &&
1034 rhs.lb().getNumeral() >= 0 && !rhs.ub().is_infinity())
1035 {
1036 s64_t m = std::max(lhs.ub().getNumeral(), rhs.ub().getNumeral());
1037 s64_t ub = next_power_of_2(s64_t(m)) - 1;
1038 return IntervalValue((s64_t) 0, (s64_t) ub);
1039 }
1040 else
1041 {
1042 return IntervalValue::top();
1043 }
1044}
1045
1047inline std::ostream &operator<<(std::ostream &o,
1049{
1051 return o;
1052}
1053
1054} // end namespace SVF
1055#endif //Z3_EXAMPLE_IntervalValue_H
cJSON * a
Definition cJSON.cpp:2560
cJSON * n
Definition cJSON.cpp:2558
A class representing a bounded 64-bit integer.
static BoundedInt plus_infinity()
bool is_minus_infinity() const
s64_t getNumeral() const
Retrieves the numeral value of the BoundedInt object.
bool is_plus_infinity() const
bool is_infinity() const
friend BoundedInt max(const BoundedInt &lhs, const BoundedInt &rhs)
s64_t getIntNumeral() const
bool is_zero() const
static BoundedInt minus_infinity()
friend BoundedInt min(const BoundedInt &lhs, const BoundedInt &rhs)
bool geq(const BoundedInt &rhs) const
bool equal(const BoundedInt &rhs) const
bool leq(const BoundedInt &rhs) const
double getRealNumeral() const
bool is_real() const
virtual const std::string to_string() const
IntervalValue & operator=(const IntervalValue &a)=default
Copy assignment operator.
void meet_with(const IntervalValue &other)
Return a intersected IntervalValue.
IntervalValue operator!=(const IntervalValue &other) const
Equality comparison.
friend IntervalValue operator/(const IntervalValue &lhs, const IntervalValue &rhs)
Divide IntervalValues.
static BoundedInt minus_infinity()
Get minus infinity -inf.
bool isTop() const
bool is_int() const
IntervalValue(s64_t n)
Create the IntervalValue [n, n].
bool leq(const IntervalValue &other) const
IntervalValue(u32_t lb, u32_t ub)
bool geq(const IntervalValue &other) const
const BoundedInt & ub() const
Return the upper bound.
IntervalValue(u64_t lb, u64_t ub)
void join_with(const IntervalValue &other)
Current IntervalValue joins with another IntervalValue.
IntervalValue & operator=(IntervalValue &&)=default
Move assignment operator.
IntervalValue operator==(const IntervalValue &other) const
Equality comparison.
friend IntervalValue operator&(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise AND of IntervalValues.
s64_t getIntNumeral() const
IntervalValue(double lb, double ub)
bool is_numeral() const
Return true if the IntervalValue is a number [num, num].
friend IntervalValue operator>>(const IntervalValue &lhs, const IntervalValue &rhs)
Left binary shift of IntervalValues.
const std::string toString() const
friend IntervalValue operator^(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise XOR of IntervalValues.
bool isBottom() const
void narrow_with(const IntervalValue &other)
Current IntervalValue narrow with another IntervalValue.
IntervalValue(s64_t lb, s64_t ub)
bool is_infinite() const
Return true if the IntervalValue is infinite IntervalValue.
IntervalValue(BoundedInt n)
void set_to_top()
Set current IntervalValue as top.
friend IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise OR of IntervalValues.
~IntervalValue()=default
Destructor.
friend IntervalValue operator*(const IntervalValue &lhs, const IntervalValue &rhs)
Multiply IntervalValues.
friend IntervalValue operator<<(const IntervalValue &lhs, const IntervalValue &rhs)
Left binary shift of IntervalValues.
bool is_zero() const
Return true if the IntervalValue is [0, 0].
static IntervalValue bottom()
Create the bottom IntervalValue [+inf, -inf].
double getRealNumeral() const
bool contain(const IntervalValue &other) const
friend IntervalValue operator-(const IntervalValue &lhs, const IntervalValue &rhs)
Subtract IntervalValues.
static BoundedInt plus_infinity()
Get plus infinity +inf.
void widen_with(const IntervalValue &other)
Current IntervalValue widen with another IntervalValue.
IntervalValue(float lb, float ub)
static IntervalValue create(const BoundedInt &lb, const BoundedInt &ub)
bool containedWithin(const IntervalValue &other) const
bool equals(const IntervalValue &other) const
Equality comparison.
IntervalValue(s32_t lb, s32_t ub)
void dump(std::ostream &o) const
void set_to_bottom()
Set current IntervalValue as bottom.
void setValue(const BoundedInt &lb, const BoundedInt &ub)
Set the lower bound.
IntervalValue()
Create default IntervalValue.
IntervalValue(BoundedInt lb, BoundedInt ub)
Create the IntervalValue [lb, ub].
static IntervalValue top()
Create the IntervalValue [-inf, +inf].
s64_t getNumeral() const
Return.
IntervalValue(IntervalValue &&)=default
Move constructor.
friend IntervalValue operator+(const IntervalValue &lhs, const IntervalValue &rhs)
Add IntervalValues.
static bool is_infinite(const BoundedInt &e)
bool is_real() const
const BoundedInt & lb() const
Return the lower bound.
IntervalValue(const IntervalValue &)=default
Copy constructor.
bool contains(int n) const
Return true if the IntervalValue contains n.
for isBitcode
Definition BasicTypes.h:68
IntervalValue operator>=(const IntervalValue &lhs, const IntervalValue &rhs)
IntervalValue operator<=(const IntervalValue &lhs, const IntervalValue &rhs)
IntervalValue operator/(const IntervalValue &lhs, const IntervalValue &rhs)
Divide IntervalValues.
IntervalValue operator%(const IntervalValue &lhs, const IntervalValue &rhs)
Divide IntervalValues.
unsigned long long u64_t
Definition GeneralType.h:48
IntervalValue operator>>(const IntervalValue &lhs, const IntervalValue &rhs)
Left binary shift of IntervalValues.
IntervalValue operator-(const IntervalValue &lhs, const IntervalValue &rhs)
Subtract IntervalValues.
IntervalValue operator^(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise XOR of IntervalValues.
IntervalValue operator&(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise AND of IntervalValues.
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
signed s32_t
Definition GeneralType.h:47
IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise OR of IntervalValues.
IntervalValue operator*(const IntervalValue &lhs, const IntervalValue &rhs)
Multiply IntervalValues.
unsigned u32_t
Definition GeneralType.h:46
signed long long s64_t
Definition GeneralType.h:49
IntervalValue operator+(const IntervalValue &lhs, const IntervalValue &rhs)
Add IntervalValues.
IntervalValue operator<(const IntervalValue &lhs, const IntervalValue &rhs)
IntervalValue operator>(const IntervalValue &lhs, const IntervalValue &rhs)
IntervalValue operator<<(const IntervalValue &lhs, const IntervalValue &rhs)
Left binary shift of IntervalValues.