svf-tools 1.0.937 → 1.0.939
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/svf/include/AE/Core/AbstractValue.h +6 -287
- package/svf/include/AE/Core/IntervalValue.h +44 -48
- package/svf/include/AE/Core/NumericValue.h +656 -0
- package/svf/include/AE/Core/RelationSolver.h +13 -4
- package/svf/include/AE/Svfexe/AbstractInterpretation.h +6 -6
- package/svf/include/AE/Svfexe/BufOverflowChecker.h +1 -1
- package/svf/include/AE/Svfexe/SVFIR2AbsState.h +2 -2
- package/svf/lib/AE/Core/RelationSolver.cpp +49 -46
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +22 -22
- package/svf/lib/AE/Svfexe/BufOverflowChecker.cpp +21 -21
- package/svf/lib/AE/Svfexe/SVFIR2AbsState.cpp +13 -13
- package/svf-llvm/tools/AE/ae.cpp +12 -12
- package/svf/include/AE/Core/BoundedZ3Expr.h +0 -404
- package/svf/include/AE/Core/NumericLiteral.h +0 -478
- package/svf/lib/AE/Core/BoundedZ3Expr.cpp +0 -64
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
//===- NumericValue.h ----Numeric Value-------------------------//
|
|
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
|
+
* Numeri Value.h
|
|
24
|
+
*
|
|
25
|
+
* Created on: May 11, 2024
|
|
26
|
+
* Author: Xiao Cheng, Jiawei Ren
|
|
27
|
+
*
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#ifndef SVF_NUMERICVALUE_H
|
|
31
|
+
#define SVF_NUMERICVALUE_H
|
|
32
|
+
|
|
33
|
+
#include "SVFIR/SVFType.h"
|
|
34
|
+
#include <cmath>
|
|
35
|
+
#include <cfloat> // For DBL_MAX
|
|
36
|
+
#include <utility>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
#define epsilon std::numeric_limits<double>::epsilon();
|
|
40
|
+
namespace SVF
|
|
41
|
+
{
|
|
42
|
+
|
|
43
|
+
/*!
|
|
44
|
+
* Bounded double numeric value
|
|
45
|
+
*/
|
|
46
|
+
class BoundedDouble
|
|
47
|
+
{
|
|
48
|
+
protected:
|
|
49
|
+
|
|
50
|
+
double _fVal;
|
|
51
|
+
|
|
52
|
+
BoundedDouble() = default;
|
|
53
|
+
|
|
54
|
+
public:
|
|
55
|
+
BoundedDouble(double fVal) : _fVal(fVal) {}
|
|
56
|
+
|
|
57
|
+
BoundedDouble(const BoundedDouble& rhs) : _fVal(rhs._fVal) {}
|
|
58
|
+
|
|
59
|
+
BoundedDouble& operator=(const BoundedDouble& rhs)
|
|
60
|
+
{
|
|
61
|
+
_fVal = rhs._fVal;
|
|
62
|
+
return *this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
BoundedDouble(BoundedDouble &&rhs) : _fVal(std::move(rhs._fVal)) {}
|
|
66
|
+
|
|
67
|
+
BoundedDouble& operator=(BoundedDouble&& rhs)
|
|
68
|
+
{
|
|
69
|
+
_fVal = std::move(rhs._fVal);
|
|
70
|
+
return *this;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
virtual ~BoundedDouble() {}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
static bool doubleEqual(double a, double b)
|
|
77
|
+
{
|
|
78
|
+
if (std::isinf(a) && std::isinf(b))
|
|
79
|
+
return a == b;
|
|
80
|
+
return std::fabs(a - b) < epsilon;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const double getFVal() const
|
|
84
|
+
{
|
|
85
|
+
return _fVal;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
bool is_plus_infinity() const
|
|
89
|
+
{
|
|
90
|
+
return _fVal == std::numeric_limits<double>::infinity();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
bool is_minus_infinity() const
|
|
94
|
+
{
|
|
95
|
+
return _fVal == -std::numeric_limits<double>::infinity();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
bool is_infinity() const
|
|
99
|
+
{
|
|
100
|
+
return is_plus_infinity() || is_minus_infinity();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void set_plus_infinity()
|
|
104
|
+
{
|
|
105
|
+
*this = plus_infinity();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
void set_minus_infinity()
|
|
109
|
+
{
|
|
110
|
+
*this = minus_infinity();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static BoundedDouble plus_infinity()
|
|
114
|
+
{
|
|
115
|
+
return std::numeric_limits<double>::infinity();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static BoundedDouble minus_infinity()
|
|
119
|
+
{
|
|
120
|
+
return -std::numeric_limits<double>::infinity();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
bool is_zero() const
|
|
125
|
+
{
|
|
126
|
+
return doubleEqual(_fVal, 0.0f);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static bool isZero(const BoundedDouble &expr)
|
|
130
|
+
{
|
|
131
|
+
return doubleEqual(expr.getFVal(), 0.0f);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
bool equal(const BoundedDouble &rhs) const
|
|
135
|
+
{
|
|
136
|
+
return doubleEqual(_fVal, rhs._fVal);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
bool leq(const BoundedDouble &rhs) const
|
|
140
|
+
{
|
|
141
|
+
if (is_infinity() ^ rhs.is_infinity())
|
|
142
|
+
{
|
|
143
|
+
if (is_infinity())
|
|
144
|
+
{
|
|
145
|
+
return is_minus_infinity();
|
|
146
|
+
}
|
|
147
|
+
else
|
|
148
|
+
{
|
|
149
|
+
return rhs.is_plus_infinity();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if(is_infinity() && rhs.is_infinity())
|
|
153
|
+
{
|
|
154
|
+
if(is_minus_infinity()) return true;
|
|
155
|
+
else return rhs.is_plus_infinity();
|
|
156
|
+
}
|
|
157
|
+
else
|
|
158
|
+
return _fVal <= rhs._fVal;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
bool geq(const BoundedDouble &rhs) const
|
|
162
|
+
{
|
|
163
|
+
if (is_infinity() ^ rhs.is_infinity())
|
|
164
|
+
{
|
|
165
|
+
if (is_infinity())
|
|
166
|
+
{
|
|
167
|
+
return is_plus_infinity();
|
|
168
|
+
}
|
|
169
|
+
else
|
|
170
|
+
{
|
|
171
|
+
return rhs.is_minus_infinity();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if(is_infinity() && rhs.is_infinity())
|
|
175
|
+
{
|
|
176
|
+
if(is_plus_infinity()) return true;
|
|
177
|
+
else return rhs.is_minus_infinity();
|
|
178
|
+
}
|
|
179
|
+
else
|
|
180
|
+
return _fVal >= rhs._fVal;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// Reload operator
|
|
184
|
+
//{%
|
|
185
|
+
friend BoundedDouble operator==(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
186
|
+
{
|
|
187
|
+
return lhs.equal(rhs);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
friend BoundedDouble operator!=(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
191
|
+
{
|
|
192
|
+
return !lhs.equal(rhs);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
friend BoundedDouble operator>(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
196
|
+
{
|
|
197
|
+
return !lhs.leq(rhs);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
friend BoundedDouble operator<(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
201
|
+
{
|
|
202
|
+
return !lhs.geq(rhs);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
friend BoundedDouble operator<=(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
206
|
+
{
|
|
207
|
+
return lhs.leq(rhs);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
friend BoundedDouble operator>=(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
211
|
+
{
|
|
212
|
+
return lhs.geq(rhs);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Adds two floating-point numbers safely, checking for overflow and
|
|
217
|
+
* underflow conditions.
|
|
218
|
+
*
|
|
219
|
+
* @param lhs Left-hand side operand of the addition.
|
|
220
|
+
* @param rhs Right-hand side operand of the addition.
|
|
221
|
+
* @return The sum of lhs and rhs. If overflow or underflow occurs, returns
|
|
222
|
+
* positive or negative infinity.
|
|
223
|
+
*/
|
|
224
|
+
static double safeAdd(double lhs, double rhs)
|
|
225
|
+
{
|
|
226
|
+
if ((lhs == std::numeric_limits<double>::infinity() &&
|
|
227
|
+
rhs == -std::numeric_limits<double>::infinity()) ||
|
|
228
|
+
(lhs == -std::numeric_limits<double>::infinity() &&
|
|
229
|
+
rhs == std::numeric_limits<double>::infinity()))
|
|
230
|
+
{
|
|
231
|
+
assert(false && "invalid add");
|
|
232
|
+
}
|
|
233
|
+
double res =
|
|
234
|
+
lhs + rhs; // Perform the addition and store the result in 'res'
|
|
235
|
+
|
|
236
|
+
// Check if the result is positive infinity due to overflow
|
|
237
|
+
if (res == std::numeric_limits<double>::infinity())
|
|
238
|
+
{
|
|
239
|
+
return res; // Positive overflow has occurred, return positive
|
|
240
|
+
// infinity
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Check if the result is negative infinity, which can indicate a large
|
|
244
|
+
// negative overflow
|
|
245
|
+
if (res == -std::numeric_limits<double>::infinity())
|
|
246
|
+
{
|
|
247
|
+
return res; // Negative "overflow", effectively an underflow to
|
|
248
|
+
// negative infinity
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Check for positive overflow: verify if both operands are positive and
|
|
252
|
+
// their sum exceeds the maximum double value
|
|
253
|
+
if (lhs > 0 && rhs > 0 &&
|
|
254
|
+
(std::numeric_limits<double>::max() - lhs) < rhs)
|
|
255
|
+
{
|
|
256
|
+
res =
|
|
257
|
+
std::numeric_limits<double>::infinity(); // Set result to
|
|
258
|
+
// positive infinity to
|
|
259
|
+
// indicate overflow
|
|
260
|
+
return res;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Check for an underflow scenario: both numbers are negative and their
|
|
264
|
+
// sum is more negative than what double can represent
|
|
265
|
+
if (lhs < 0 && rhs < 0 &&
|
|
266
|
+
(-std::numeric_limits<double>::max() - lhs) > rhs)
|
|
267
|
+
{
|
|
268
|
+
res = -std::numeric_limits<
|
|
269
|
+
double>::infinity(); // Set result to negative infinity to
|
|
270
|
+
// clarify extreme negative sum
|
|
271
|
+
return res;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// If none of the above conditions are met, return the result of the
|
|
275
|
+
// addition
|
|
276
|
+
return res;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
friend BoundedDouble operator+(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
280
|
+
{
|
|
281
|
+
return safeAdd(lhs._fVal, rhs._fVal);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
friend BoundedDouble operator-(const BoundedDouble &lhs)
|
|
285
|
+
{
|
|
286
|
+
return -lhs._fVal;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
friend BoundedDouble operator-(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
290
|
+
{
|
|
291
|
+
return safeAdd(lhs._fVal, -rhs._fVal);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Safely multiplies two floating-point numbers, checking for overflow and
|
|
296
|
+
* underflow.
|
|
297
|
+
*
|
|
298
|
+
* @param lhs Left-hand side operand of the multiplication.
|
|
299
|
+
* @param rhs Right-hand side operand of the multiplication.
|
|
300
|
+
* @return The product of lhs and rhs. If overflow or underflow occurs,
|
|
301
|
+
* returns positive or negative infinity accordingly.
|
|
302
|
+
*/
|
|
303
|
+
static double safeMul(double lhs, double rhs)
|
|
304
|
+
{
|
|
305
|
+
if (doubleEqual(lhs, 0.0f) || doubleEqual(rhs, 0.0f))
|
|
306
|
+
return 0.0f;
|
|
307
|
+
double res = lhs * rhs;
|
|
308
|
+
// Check if the result is positive infinity due to overflow
|
|
309
|
+
if (res == std::numeric_limits<double>::infinity())
|
|
310
|
+
{
|
|
311
|
+
return res; // Positive overflow has occurred, return positive
|
|
312
|
+
// infinity
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Check if the result is negative infinity, which can indicate a large
|
|
316
|
+
// negative overflow
|
|
317
|
+
if (res == -std::numeric_limits<double>::infinity())
|
|
318
|
+
{
|
|
319
|
+
return res; // Negative "overflow", effectively an underflow to
|
|
320
|
+
// negative infinity
|
|
321
|
+
}
|
|
322
|
+
// Check for overflow scenarios
|
|
323
|
+
if (lhs > 0 && rhs > 0 && lhs > std::numeric_limits<double>::max() / rhs)
|
|
324
|
+
{
|
|
325
|
+
return std::numeric_limits<double>::infinity();
|
|
326
|
+
}
|
|
327
|
+
if (lhs < 0 && rhs < 0 && lhs < std::numeric_limits<double>::max() / rhs)
|
|
328
|
+
{
|
|
329
|
+
return std::numeric_limits<double>::infinity();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Check for "underflow" scenarios (negative overflow)
|
|
333
|
+
if (lhs > 0 && rhs < 0 &&
|
|
334
|
+
rhs < std::numeric_limits<double>::lowest() / lhs)
|
|
335
|
+
{
|
|
336
|
+
return -std::numeric_limits<double>::infinity();
|
|
337
|
+
}
|
|
338
|
+
if (lhs < 0 && rhs > 0 &&
|
|
339
|
+
lhs < std::numeric_limits<double>::lowest() / rhs)
|
|
340
|
+
{
|
|
341
|
+
return -std::numeric_limits<double>::infinity();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return res; // If no overflow or underflow, return the product
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
friend BoundedDouble operator*(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
348
|
+
{
|
|
349
|
+
return safeMul(lhs._fVal, rhs._fVal);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Safely divides one floating-point number by another, checking for
|
|
354
|
+
* division by zero and overflow.
|
|
355
|
+
*
|
|
356
|
+
* @param lhs Left-hand side operand (numerator).
|
|
357
|
+
* @param rhs Right-hand side operand (denominator).
|
|
358
|
+
* @return The quotient of lhs and rhs. Returns positive or negative
|
|
359
|
+
* infinity for division by zero, or when overflow occurs.
|
|
360
|
+
*/
|
|
361
|
+
static double safeDiv(double lhs, double rhs)
|
|
362
|
+
{
|
|
363
|
+
// Check for division by zero
|
|
364
|
+
if (doubleEqual(rhs, 0.0f))
|
|
365
|
+
{
|
|
366
|
+
return (lhs >= 0.0f) ? std::numeric_limits<double>::infinity()
|
|
367
|
+
: -std::numeric_limits<double>::infinity();
|
|
368
|
+
}
|
|
369
|
+
double res = lhs / rhs;
|
|
370
|
+
// Check if the result is positive infinity due to overflow
|
|
371
|
+
if (res == std::numeric_limits<double>::infinity())
|
|
372
|
+
{
|
|
373
|
+
return res; // Positive overflow has occurred, return positive
|
|
374
|
+
// infinity
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Check if the result is negative infinity, which can indicate a large
|
|
378
|
+
// negative overflow
|
|
379
|
+
if (res == -std::numeric_limits<double>::infinity())
|
|
380
|
+
{
|
|
381
|
+
return res; // Negative "overflow", effectively an underflow to
|
|
382
|
+
// negative infinity
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Check for overflow when dividing small numbers
|
|
386
|
+
if (rhs > 0 && rhs < std::numeric_limits<double>::min() &&
|
|
387
|
+
lhs > std::numeric_limits<double>::max() * rhs)
|
|
388
|
+
{
|
|
389
|
+
return std::numeric_limits<double>::infinity();
|
|
390
|
+
}
|
|
391
|
+
if (rhs < 0 && rhs > -std::numeric_limits<double>::min() &&
|
|
392
|
+
lhs > std::numeric_limits<double>::max() * rhs)
|
|
393
|
+
{
|
|
394
|
+
return -std::numeric_limits<double>::infinity();
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return res; // If no special cases, return the quotient
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
friend BoundedDouble operator/(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
401
|
+
{
|
|
402
|
+
return safeDiv(lhs._fVal, rhs._fVal);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
friend BoundedDouble operator%(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
406
|
+
{
|
|
407
|
+
if (rhs.is_zero()) assert(false && "divide by zero");
|
|
408
|
+
else if (!lhs.is_infinity() && !rhs.is_infinity())
|
|
409
|
+
return std::fmod(lhs._fVal, rhs._fVal);
|
|
410
|
+
else if (!lhs.is_infinity() && rhs.is_infinity())
|
|
411
|
+
return 0.0f;
|
|
412
|
+
// TODO: not sure
|
|
413
|
+
else if (lhs.is_infinity() && !rhs.is_infinity())
|
|
414
|
+
return ite(rhs._fVal > 0.0f, lhs, -lhs);
|
|
415
|
+
else
|
|
416
|
+
// TODO: +oo/-oo L'Hôpital's rule?
|
|
417
|
+
return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
|
|
418
|
+
abort();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
inline bool is_int() const
|
|
422
|
+
{
|
|
423
|
+
return _fVal == std::round(_fVal);
|
|
424
|
+
}
|
|
425
|
+
inline bool is_real() const
|
|
426
|
+
{
|
|
427
|
+
return !is_int();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
friend BoundedDouble operator^(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
431
|
+
{
|
|
432
|
+
int lInt = std::round(rhs._fVal), rInt = std::round(rhs._fVal);
|
|
433
|
+
return lInt ^ rInt;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
friend BoundedDouble operator&(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
437
|
+
{
|
|
438
|
+
int lInt = std::round(rhs._fVal), rInt = std::round(rhs._fVal);
|
|
439
|
+
return lInt & rInt;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
friend BoundedDouble operator|(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
443
|
+
{
|
|
444
|
+
int lInt = std::round(rhs._fVal), rInt = std::round(rhs._fVal);
|
|
445
|
+
return lInt | rInt;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
friend BoundedDouble operator&&(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
450
|
+
{
|
|
451
|
+
return lhs._fVal && rhs._fVal;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
friend BoundedDouble operator||(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
455
|
+
{
|
|
456
|
+
return lhs._fVal || rhs._fVal;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
friend BoundedDouble operator!(const BoundedDouble &lhs)
|
|
460
|
+
{
|
|
461
|
+
return !lhs._fVal;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
friend BoundedDouble operator>>(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
465
|
+
{
|
|
466
|
+
assert(rhs.geq(0) && "rhs should be greater or equal than 0");
|
|
467
|
+
if (lhs.is_zero())
|
|
468
|
+
return lhs;
|
|
469
|
+
else if (lhs.is_infinity())
|
|
470
|
+
return lhs;
|
|
471
|
+
else if (rhs.is_infinity())
|
|
472
|
+
return lhs.geq(0) ? 0 : -1;
|
|
473
|
+
else
|
|
474
|
+
return (s32_t) lhs.getNumeral() >> (s32_t) rhs.getNumeral();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
friend BoundedDouble operator<<(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
478
|
+
{
|
|
479
|
+
assert(rhs.geq(0) && "rhs should be greater or equal than 0");
|
|
480
|
+
if (lhs.is_zero())
|
|
481
|
+
return lhs;
|
|
482
|
+
else if (lhs.is_infinity())
|
|
483
|
+
return lhs;
|
|
484
|
+
else if (rhs.is_infinity())
|
|
485
|
+
return lhs.geq(0) ? plus_infinity() : minus_infinity();
|
|
486
|
+
else
|
|
487
|
+
return (s32_t) lhs.getNumeral() << (s32_t) rhs.getNumeral();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
friend BoundedDouble ite(const BoundedDouble& cond, const BoundedDouble& lhs,
|
|
491
|
+
const BoundedDouble& rhs)
|
|
492
|
+
{
|
|
493
|
+
return cond._fVal != 0.0f ? lhs._fVal : rhs._fVal;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
friend std::ostream &operator<<(std::ostream &out, const BoundedDouble &expr)
|
|
497
|
+
{
|
|
498
|
+
out << expr._fVal;
|
|
499
|
+
return out;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
friend bool eq(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
503
|
+
{
|
|
504
|
+
return doubleEqual(lhs._fVal, rhs._fVal);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
friend BoundedDouble min(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
508
|
+
{
|
|
509
|
+
return std::min(lhs._fVal, rhs._fVal);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
friend BoundedDouble max(const BoundedDouble &lhs, const BoundedDouble &rhs)
|
|
513
|
+
{
|
|
514
|
+
return std::max(lhs._fVal, rhs._fVal);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
static BoundedDouble min(std::vector<BoundedDouble>& _l)
|
|
518
|
+
{
|
|
519
|
+
BoundedDouble ret(plus_infinity());
|
|
520
|
+
for (const auto &it: _l)
|
|
521
|
+
{
|
|
522
|
+
if (it.is_minus_infinity())
|
|
523
|
+
return minus_infinity();
|
|
524
|
+
else if (!it.geq(ret))
|
|
525
|
+
{
|
|
526
|
+
ret = it;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return ret;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
static BoundedDouble max(std::vector<BoundedDouble>& _l)
|
|
533
|
+
{
|
|
534
|
+
BoundedDouble ret(minus_infinity());
|
|
535
|
+
for (const auto &it: _l)
|
|
536
|
+
{
|
|
537
|
+
if (it.is_plus_infinity())
|
|
538
|
+
return plus_infinity();
|
|
539
|
+
else if (!it.leq(ret))
|
|
540
|
+
{
|
|
541
|
+
ret = it;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return ret;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
friend BoundedDouble abs(const BoundedDouble &lhs)
|
|
548
|
+
{
|
|
549
|
+
return lhs.leq(0) ? -lhs : lhs;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
inline bool is_true() const
|
|
553
|
+
{
|
|
554
|
+
return _fVal != 0.0f;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/// Return Numeral
|
|
558
|
+
inline s64_t getNumeral() const
|
|
559
|
+
{
|
|
560
|
+
if (is_minus_infinity())
|
|
561
|
+
{
|
|
562
|
+
return INT64_MIN;
|
|
563
|
+
}
|
|
564
|
+
else if (is_plus_infinity())
|
|
565
|
+
{
|
|
566
|
+
return INT64_MAX;
|
|
567
|
+
}
|
|
568
|
+
else
|
|
569
|
+
{
|
|
570
|
+
return std::round(_fVal);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
inline s64_t getIntNumeral() const
|
|
575
|
+
{
|
|
576
|
+
return getNumeral();
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
inline double getRealNumeral() const
|
|
580
|
+
{
|
|
581
|
+
return _fVal;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
inline virtual const std::string to_string() const
|
|
585
|
+
{
|
|
586
|
+
return std::to_string(_fVal);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
//%}
|
|
590
|
+
}; // end class BoundedDouble
|
|
591
|
+
|
|
592
|
+
class BoundedInt : public BoundedDouble
|
|
593
|
+
{
|
|
594
|
+
private:
|
|
595
|
+
BoundedInt() = default;
|
|
596
|
+
|
|
597
|
+
public:
|
|
598
|
+
|
|
599
|
+
BoundedInt(s32_t val)
|
|
600
|
+
{
|
|
601
|
+
_fVal = val;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
BoundedInt(s64_t val)
|
|
605
|
+
{
|
|
606
|
+
_fVal = val;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
BoundedInt(const BoundedInt& rhs)
|
|
610
|
+
{
|
|
611
|
+
_fVal = rhs._fVal;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
BoundedInt& operator=(const BoundedInt& rhs)
|
|
615
|
+
{
|
|
616
|
+
_fVal = rhs._fVal;
|
|
617
|
+
return *this;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
BoundedInt(BoundedInt&& rhs)
|
|
621
|
+
{
|
|
622
|
+
_fVal = rhs._fVal;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
BoundedInt& operator=(const BoundedInt&& rhs)
|
|
626
|
+
{
|
|
627
|
+
_fVal = rhs._fVal;
|
|
628
|
+
return *this;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
BoundedInt(double val)
|
|
632
|
+
{
|
|
633
|
+
_fVal = val;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
BoundedInt(const BoundedDouble& f)
|
|
637
|
+
{
|
|
638
|
+
_fVal = f.getFVal();
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
virtual ~BoundedInt() {}
|
|
642
|
+
|
|
643
|
+
inline const std::string to_string() const override
|
|
644
|
+
{
|
|
645
|
+
if (is_minus_infinity())
|
|
646
|
+
return "-∞";
|
|
647
|
+
else if (is_plus_infinity())
|
|
648
|
+
return "∞";
|
|
649
|
+
else
|
|
650
|
+
return std::to_string(getIntNumeral());
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
} // end namespace SVF
|
|
655
|
+
|
|
656
|
+
#endif // SVF_NUMERICVALUE_H
|
|
@@ -58,24 +58,33 @@ public:
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
/// Return Z3 expression lazily based on SVFVar ID
|
|
61
|
-
virtual inline Z3Expr
|
|
61
|
+
virtual inline Z3Expr toIntZ3Expr(u32_t varId) const
|
|
62
62
|
{
|
|
63
63
|
return Z3Expr::getContext().int_const(std::to_string(varId).c_str());
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
inline Z3Expr toIntVal(s32_t f) const
|
|
67
|
+
{
|
|
68
|
+
return Z3Expr::getContext().int_val(f);
|
|
69
|
+
}
|
|
70
|
+
inline Z3Expr toRealVal(BoundedDouble f) const
|
|
71
|
+
{
|
|
72
|
+
return Z3Expr::getContext().real_val(std::to_string(f.getFVal()).c_str());
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
/* two optional solvers: RSY and bilateral */
|
|
67
76
|
|
|
68
77
|
AbstractState bilateral(const AbstractState& domain, const Z3Expr &phi, u32_t descend_check = 0);
|
|
69
78
|
|
|
70
79
|
AbstractState RSY(const AbstractState& domain, const Z3Expr &phi);
|
|
71
80
|
|
|
72
|
-
Map<u32_t,
|
|
81
|
+
Map<u32_t, s32_t> BoxedOptSolver(const Z3Expr& phi, Map<u32_t, s32_t>& ret, Map<u32_t, s32_t>& low_values, Map<u32_t, s32_t>& high_values);
|
|
73
82
|
|
|
74
83
|
AbstractState BS(const AbstractState& domain, const Z3Expr &phi);
|
|
75
84
|
|
|
76
|
-
void updateMap(Map<u32_t,
|
|
85
|
+
void updateMap(Map<u32_t, s32_t>& map, u32_t key, const s32_t& value);
|
|
77
86
|
|
|
78
|
-
void decide_cpa_ext(const Z3Expr &phi, Map<u32_t, Z3Expr>&, Map<u32_t,
|
|
87
|
+
void decide_cpa_ext(const Z3Expr &phi, Map<u32_t, Z3Expr>&, Map<u32_t, s32_t>&, Map<u32_t, s32_t>&, Map<u32_t, s32_t>&, Map<u32_t, s32_t>&);
|
|
79
88
|
};
|
|
80
89
|
}
|
|
81
90
|
|