Static Value-Flow Analysis
Loading...
Searching...
No Matches
PointsTo.cpp
Go to the documentation of this file.
1//===- PointsTo.cpp -- Wrapper of set-like data structures ------------//
2
3/*
4 * PointsTo.cpp
5 *
6 * Abstracts away data structures to be used as points-to sets (implementation).
7 *
8 * Created on: Feb 01, 2021
9 * Author: Mohamad Barbar
10 */
11
12#include <new>
13#include <utility>
14
15#include "Util/Options.h"
17#include "SVFIR/SVFValue.h"
18
19namespace SVF
20{
21
24
26 : type(Options::PtType()), nodeMapping(currentBestNodeMapping),
27 reverseNodeMapping(currentBestReverseNodeMapping)
28{
29 if (type == SBV) new (&sbv) SparseBitVector<>();
30 else if (type == CBV) new (&cbv) CoreBitVector();
31 else if (type == BV) new (&bv) BitVector();
32 else assert(false && "PointsTo::PointsTo: unknown type");
33}
34
36 : type(pt.type), nodeMapping(pt.nodeMapping),
37 reverseNodeMapping(pt.reverseNodeMapping)
38{
39 if (type == SBV) new (&sbv) SparseBitVector<>(pt.sbv);
40 else if (type == CBV) new (&cbv) CoreBitVector(pt.cbv);
41 else if (type == BV) new (&bv) BitVector(pt.bv);
42 else assert(false && "PointsTo::PointsTo&: unknown type");
43}
44
46noexcept : type(pt.type), nodeMapping(std::move(pt.nodeMapping)),
47 reverseNodeMapping(std::move(pt.reverseNodeMapping))
48{
49 if (type == SBV) new (&sbv) SparseBitVector<>(std::move(pt.sbv));
50 else if (type == CBV) new (&cbv) CoreBitVector(std::move(pt.cbv));
51 else if (type == BV) new (&bv) BitVector(std::move(pt.bv));
52 else assert(false && "PointsTo::PointsTo&&: unknown type");
53}
54
56{
57 if (type == SBV) sbv.~SparseBitVector<>();
58 else if (type == CBV) cbv.~CoreBitVector();
59 else if (type == BV) bv.~BitVector();
60 else assert(false && "PointsTo::~PointsTo: unknown type");
61
62 nodeMapping = nullptr;
63 reverseNodeMapping = nullptr;
64}
65
67{
68 if (this == &rhs)
69 return *this;
70 this->type = rhs.type;
71 this->nodeMapping = rhs.nodeMapping;
73 // Placement new because if type has changed, we have
74 // not constructed the new type yet.
75 if (type == SBV) new (&sbv) SparseBitVector<>(rhs.sbv);
76 else if (type == CBV) new (&cbv) CoreBitVector(rhs.cbv);
77 else if (type == BV) new (&bv) BitVector(rhs.bv);
78 else assert(false && "PointsTo::PointsTo=&: unknown type");
79
80 return *this;
81}
82
84noexcept
85{
86 this->type = rhs.type;
87 this->nodeMapping = rhs.nodeMapping;
88 this->reverseNodeMapping = rhs.reverseNodeMapping;
89 // See comment in copy assignment.
90 if (type == SBV) new (&sbv) SparseBitVector<>(std::move(rhs.sbv));
91 else if (type == CBV) new (&cbv) CoreBitVector(std::move(rhs.cbv));
92 else if (type == BV) new (&bv) BitVector(std::move(rhs.bv));
93 else assert(false && "PointsTo::PointsTo=&&: unknown type");
94
95 return *this;
96}
97
98bool PointsTo::empty() const
99{
100 if (type == CBV) return cbv.empty();
101 else if (type == SBV) return sbv.empty();
102 else if (type == BV) return bv.empty();
103 else
104 {
105 assert(false && "PointsTo::empty: unknown type");
106 abort();
107 }
108}
109
112{
113 if (type == CBV) return cbv.count();
114 else if (type == SBV) return sbv.count();
115 else if (type == BV) return bv.count();
116 else
117 {
118 assert(false && "PointsTo::count: unknown type");
119 abort();
120 }
121}
122
124{
125 if (type == CBV) cbv.clear();
126 else if (type == SBV) sbv.clear();
127 else if (type == BV) bv.clear();
128 else assert(false && "PointsTo::clear: unknown type");
129}
130
132{
134 if (type == CBV) return cbv.test(n);
135 else if (type == SBV) return sbv.test(n);
136 else if (type == BV) return bv.test(n);
137 else
138 {
139 assert(false && "PointsTo::test: unknown type");
140 abort();
141 }
142}
143
145{
147 if (type == CBV) return cbv.test_and_set(n);
148 else if (type == SBV) return sbv.test_and_set(n);
149 else if (type == BV) return bv.test_and_set(n);
150 else
151 {
152 assert(false && "PointsTo::test_and_set: unknown type");
153 abort();
154 }
155}
156
158{
160 if (type == CBV) cbv.set(n);
161 else if (type == SBV) sbv.set(n);
162 else if (type == BV) bv.set(n);
163 else assert(false && "PointsTo::set: unknown type");
164}
165
167{
169 if (type == CBV) cbv.reset(n);
170 else if (type == SBV) sbv.reset(n);
171 else if (type == BV) bv.reset(n);
172 else assert(false && "PointsTo::reset: unknown type");
173}
174
176{
177 assert(metaSame(rhs) && "PointsTo::contains: mappings of operands do not match!");
178
179 if (type == CBV) return cbv.contains(rhs.cbv);
180 else if (type == SBV) return sbv.contains(rhs.sbv);
181 else if (type == BV) return bv.contains(rhs.bv);
182 else
183 {
184 assert(false && "PointsTo::contains: unknown type");
185 abort();
186 }
187}
188
190{
191 assert(metaSame(rhs) && "PointsTo::intersects: mappings of operands do not match!");
192
193 if (type == CBV) return cbv.intersects(rhs.cbv);
194 else if (type == SBV) return sbv.intersects(rhs.sbv);
195 else if (type == BV) return bv.intersects(rhs.bv);
196 else
197 {
198 assert(false && "PointsTo::intersects: unknown type");
199 abort();
200 }
201}
202
204{
205 if (count() == 0) return -1;
206 return *begin();
207}
208
210{
211 assert(metaSame(rhs) && "PointsTo::==: mappings of operands do not match!");
212
213 if (type == CBV) return cbv == rhs.cbv;
214 else if (type == SBV) return sbv == rhs.sbv;
215 else if (type == BV) return bv == rhs.bv;
216 else
217 {
218 assert(false && "PointsTo::==: unknown type");
219 abort();
220 }
221}
222
224{
225 // TODO: we're asserting and checking twice... should be okay...
226 assert(metaSame(rhs) && "PointsTo::!=: mappings of operands do not match!");
227
228 return !(*this == rhs);
229}
230
232{
233 assert(metaSame(rhs) && "PointsTo::|=: mappings of operands do not match!");
234
235 if (type == CBV) return cbv |= rhs.cbv;
236 else if (type == SBV) return sbv |= rhs.sbv;
237 else if (type == BV) return bv |= rhs.bv;
238 else
239 {
240 assert(false && "PointsTo::|=: unknown type");
241 abort();
242 }
243}
244
246{
247 // TODO:
248 bool changed = false;
249 for (NodeID n : rhs)
250 {
251 if (changed) set(n);
252 else changed = test_and_set(n);
253 }
254
255 return changed;
256}
257
259{
260 assert(metaSame(rhs) && "PointsTo::&=: mappings of operands do not match!");
261
262 if (type == CBV) return cbv &= rhs.cbv;
263 else if (type == SBV) return sbv &= rhs.sbv;
264 else if (type == BV) return bv &= rhs.bv;
265 else
266 {
267 assert(false && "PointsTo::&=: unknown type");
268 abort();
269 }
270}
271
273{
274 assert(metaSame(rhs) && "PointsTo::-=: mappings of operands do not match!");
275
276 if (type == CBV) return cbv.intersectWithComplement(rhs.cbv);
277 else if (type == SBV) return sbv.intersectWithComplement(rhs.sbv);
278 else if (type == BV) return bv.intersectWithComplement(rhs.bv);
279 else
280 {
281 assert(false && "PointsTo::-=: unknown type");
282 abort();
283 }
284}
285
287{
288 assert(metaSame(rhs) && "PointsTo::intersectWithComplement: mappings of operands do not match!");
289
290 if (type == CBV) return cbv.intersectWithComplement(rhs.cbv);
291 else if (type == SBV) return sbv.intersectWithComplement(rhs.sbv);
292 else if (type == BV) return bv.intersectWithComplement(rhs.bv);
293
294 assert(false && "PointsTo::intersectWithComplement(PT): unknown type");
295 abort();
296}
297
299{
300 assert(metaSame(rhs) && "PointsTo::intersectWithComplement: mappings of operands do not match!");
301 assert(metaSame(lhs) && "PointsTo::intersectWithComplement: mappings of operands do not match!");
302
303 if (type == CBV) cbv.intersectWithComplement(lhs.cbv, rhs.cbv);
304 else if (type == SBV) sbv.intersectWithComplement(lhs.sbv, rhs.sbv);
305 else if (type == BV) bv.intersectWithComplement(lhs.bv, rhs.bv);
306 else
307 {
308 assert(false && "PointsTo::intersectWithComplement(PT, PT): unknown type");
309 abort();
310 }
311}
312
314{
315 NodeBS nbs;
316 for (const NodeID o : *this) nbs.set(o);
317 return nbs;
318}
319
320size_t PointsTo::hash() const
321{
322 if (type == CBV) return cbv.hash();
323 else if (type == SBV)
324 {
325 std::hash<SparseBitVector<>> h;
326 return h(sbv);
327 }
328 else if (type == BV) return bv.hash();
329
330 else
331 {
332 assert(false && "PointsTo::hash: unknown type");
333 abort();
334 }
335}
336
341
343{
344 if (nodeMapping == nullptr) return n;
346 return nodeMapping->at(n);
347}
348
350{
351 if (reverseNodeMapping == nullptr) return n;
353 return reverseNodeMapping->at(n);
354}
355
356bool PointsTo::metaSame(const PointsTo &pt) const
357{
359}
360
365
370
377
379{
381 {
382 // newPt constructed with correct node mapping.
384 for (const NodeID o : *this) newPt.set(o);
385 *this = std::move(newPt);
386 }
387}
388
390 : pt(pt)
391{
392 if (pt->type == Type::CBV)
393 {
395 }
396 else if (pt->type == Type::SBV)
397 {
399 }
400 else if (pt->type == Type::BV)
401 {
402 new (&bvIt) BitVector::iterator(end ? pt->bv.end() : pt->bv.begin());
403 }
404 else
405 {
406 assert(false && "PointsToIterator::PointsToIterator: unknown type");
407 abort();
408 }
409}
410
412 : pt(pt.pt)
413{
414 if (this->pt->type == PointsTo::Type::SBV)
415 {
417 }
418 else if (this->pt->type == PointsTo::Type::CBV)
419 {
420 new (&cbvIt) CoreBitVector::iterator(pt.cbvIt);
421 }
422 else if (this->pt->type == PointsTo::Type::BV)
423 {
424 new (&bvIt) BitVector::iterator(pt.bvIt);
425 }
426 else
427 {
428 assert(false && "PointsToIterator::PointsToIterator&: unknown type");
429 abort();
430 }
431}
432
434noexcept : pt(pt.pt)
435{
436 if (this->pt->type == PointsTo::Type::SBV)
437 {
438 new (&sbvIt) SparseBitVector<>::iterator(std::move(pt.sbvIt));
439 }
440 else if (this->pt->type == PointsTo::Type::CBV)
441 {
442 new (&cbvIt) CoreBitVector::iterator(std::move(pt.cbvIt));
443 }
444 else if (this->pt->type == PointsTo::Type::BV)
445 {
446 new (&bvIt) BitVector::iterator(std::move(pt.bvIt));
447 }
448 else
449 {
450 assert(false && "PointsToIterator::PointsToIterator&&: unknown type");
451 abort();
452 }
453}
454
456{
457 this->pt = rhs.pt;
458
459 if (this->pt->type == PointsTo::Type::SBV)
460 {
461 new (&sbvIt) SparseBitVector<>::iterator(rhs.sbvIt);
462 }
463 else if (this->pt->type == PointsTo::Type::CBV)
464 {
465 new (&cbvIt) CoreBitVector::iterator(rhs.cbvIt);
466 }
467 else if (this->pt->type == PointsTo::Type::BV)
468 {
469 new (&bvIt) BitVector::iterator(rhs.bvIt);
470 }
471 else assert(false && "PointsToIterator::PointsToIterator&: unknown type");
472
473 return *this;
474}
475
477{
478 this->pt = rhs.pt;
479
480 if (this->pt->type == PointsTo::Type::SBV)
481 {
482 new (&sbvIt) SparseBitVector<>::iterator(std::move(rhs.sbvIt));
483 }
484 else if (this->pt->type == PointsTo::Type::CBV)
485 {
486 new (&cbvIt) CoreBitVector::iterator(std::move(rhs.cbvIt));
487 }
488 else if (this->pt->type == PointsTo::Type::BV)
489 {
490 new (&bvIt) BitVector::iterator(std::move(rhs.bvIt));
491 }
492 else assert(false && "PointsToIterator::PointsToIterator&&: unknown type");
493
494 return *this;
495}
496
498{
499 assert(!atEnd() && "PointsToIterator::++(pre): incrementing past end!");
500 if (pt->type == Type::CBV) ++cbvIt;
501 else if (pt->type == Type::SBV) ++sbvIt;
502 else if (pt->type == Type::BV) ++bvIt;
503 else assert(false && "PointsToIterator::++(void): unknown type");
504
505 return *this;
506}
507
509{
510 assert(!atEnd() && "PointsToIterator::++(pre): incrementing past end!");
511 PointsToIterator old = *this;
512 ++*this;
513 return old;
514}
515
517{
518 assert(!atEnd() && "PointsToIterator: dereferencing end!");
519 if (pt->type == Type::CBV) return pt->getExternalNode(*cbvIt);
520 else if (pt->type == Type::SBV) return pt->getExternalNode(*sbvIt);
521 else if (pt->type == Type::BV) return pt->getExternalNode(*bvIt);
522 else
523 {
524 assert(false && "PointsToIterator::*: unknown type");
525 abort();
526 }
527}
528
530{
531 assert(pt == rhs.pt
532 && "PointsToIterator::==: comparing iterators from different PointsTos!");
533
534 // Handles end implicitly.
535 if (pt->type == Type::CBV) return cbvIt == rhs.cbvIt;
536 else if (pt->type == Type::SBV) return sbvIt == rhs.sbvIt;
537 else if (pt->type == Type::BV) return bvIt == rhs.bvIt;
538 else
539 {
540 assert(false && "PointsToIterator::==: unknown type");
541 abort();
542 }
543}
544
546{
547 assert(pt == rhs.pt
548 && "PointsToIterator::!=: comparing iterators from different PointsTos!");
549 return !(*this == rhs);
550}
551
553{
554 assert(pt != nullptr && "PointsToIterator::atEnd: iterator iterating over nothing!");
555 if (pt->type == Type::CBV) return cbvIt == pt->cbv.end();
556 else if (pt->type == Type::SBV) return sbvIt == pt->sbv.end();
557 else if (pt->type == Type::BV) return bvIt == pt->bv.end();
558 else
559 {
560 assert(false && "PointsToIterator::atEnd: unknown type");
561 abort();
562 }
563}
564
566{
567 // TODO: optimise.
569 result |= rhs;
570 return result;
571}
572
574{
575 // TODO: optimise.
577 result &= rhs;
578 return result;
579}
580
582{
583 // TODO: optimise.
585 result -= rhs;
586 return result;
587}
588
589}; // namespace SVF
newitem type
Definition cJSON.cpp:2739
cJSON * n
Definition cJSON.cpp:2558
bool intersects(const CoreBitVector &rhs) const
Returns true if this CBV and rhs share any set bits.
void clear(void)
Empty the CBV.
bool test_and_set(u32_t bit)
void reset(u32_t bit)
Resets bit in the CBV.
void set(u32_t bit)
Sets bit in the CBV.
bool test(u32_t bit) const
Returns true if bit is set in this CBV.
const_iterator begin(void) const
bool intersectWithComplement(const CoreBitVector &rhs)
const_iterator end(void) const
bool empty(void) const
Returns true if no bits are set.
u32_t count(void) const
Returns number of bits set.
bool contains(const CoreBitVector &rhs) const
Returns true if this CBV is a superset of rhs.
size_t hash(void) const
Hash for this CBV.
Carries around command line options.
Definition Options.h:20
u32_t operator*() const
Dereference: *it.
Definition PointsTo.cpp:516
CoreBitVector::iterator cbvIt
Definition PointsTo.h:228
SparseBitVector ::iterator sbvIt
Definition PointsTo.h:227
const PointsTo * pt
PointsTo we are iterating over.
Definition PointsTo.h:222
BitVector::iterator bvIt
Definition PointsTo.h:229
bool operator!=(const PointsToIterator &rhs) const
Inequality: *this != rhs.
Definition PointsTo.cpp:545
PointsToIterator()=delete
Deleted because we don't want iterators with null pt.
const PointsToIterator & operator++()
Pre-increment: ++it.
Definition PointsTo.cpp:497
PointsToIterator & operator=(const PointsToIterator &rhs)
Definition PointsTo.cpp:455
bool operator==(const PointsToIterator &rhs) const
Equality: *this == rhs.
Definition PointsTo.cpp:529
bool test_and_set(u32_t n)
Definition PointsTo.cpp:144
bool empty() const
Returns true if set is empty.
Definition PointsTo.cpp:98
void clear()
Empty the set.
Definition PointsTo.cpp:123
static MappingPtr getCurrentBestReverseNodeMapping()
Definition PointsTo.cpp:366
MappingPtr reverseNodeMapping
Internal nodes -> external nodes.
Definition PointsTo.h:178
void reset(u32_t n)
Removes n from the set.
Definition PointsTo.cpp:166
bool operator-=(const PointsTo &rhs)
Definition PointsTo.cpp:272
PointsTo & operator=(const PointsTo &rhs)
Copy assignment.
Definition PointsTo.cpp:66
size_t hash() const
Return a hash of this set.
Definition PointsTo.cpp:320
bool operator&=(const PointsTo &rhs)
Definition PointsTo.cpp:258
static MappingPtr currentBestReverseNodeMapping
Likewise, but reversed.
Definition PointsTo.h:159
MappingPtr getNodeMapping() const
Definition PointsTo.cpp:337
BitVector bv
Bit vector backing.
Definition PointsTo.h:170
bool operator==(const PointsTo &rhs) const
Returns true if this set and rhs contain exactly the same elements.
Definition PointsTo.cpp:209
const_iterator end() const
Definition PointsTo.h:132
void checkAndRemap()
Definition PointsTo.cpp:378
CoreBitVector cbv
Core bit vector backing.
Definition PointsTo.h:168
NodeID getExternalNode(NodeID n) const
Returns reverseNodeMapping[n], checking for nullptr and size.
Definition PointsTo.cpp:349
std::shared_ptr< std::vector< NodeID > > MappingPtr
Definition PointsTo.h:42
static void setCurrentBestNodeMapping(MappingPtr newCurrentBestNodeMapping, MappingPtr newCurrentBestReverseNodeMapping)
Definition PointsTo.cpp:371
bool operator!=(const PointsTo &rhs) const
Returns true if either this set or rhs has an element not in the other.
Definition PointsTo.cpp:223
static MappingPtr currentBestNodeMapping
Best node mapping we know of the for the analyses at hand.
Definition PointsTo.h:157
u32_t count() const
Returns number of elements.
Definition PointsTo.cpp:111
bool metaSame(const PointsTo &pt) const
Definition PointsTo.cpp:356
bool operator|=(const PointsTo &rhs)
Definition PointsTo.cpp:231
enum Type type
Type of this points-to set.
Definition PointsTo.h:174
void set(u32_t n)
Inserts n in the set.
Definition PointsTo.cpp:157
bool contains(const PointsTo &rhs) const
Returns true if this set is a superset of rhs.
Definition PointsTo.cpp:175
PointsTo()
Construct empty points-to set.
Definition PointsTo.cpp:25
MappingPtr nodeMapping
External nodes -> internal nodes.
Definition PointsTo.h:176
NodeBS toNodeBS() const
Returns this points-to set as a NodeBS.
Definition PointsTo.cpp:313
const_iterator begin() const
Definition PointsTo.h:128
bool intersects(const PointsTo &rhs) const
Returns true if this set and rhs share any elements.
Definition PointsTo.cpp:189
static MappingPtr getCurrentBestNodeMapping()
Definition PointsTo.cpp:361
SparseBitVector sbv
Sparse bit vector backing.
Definition PointsTo.h:166
NodeID getInternalNode(NodeID n) const
Returns nodeMapping[n], checking for nullptr and size.
Definition PointsTo.cpp:342
bool test(u32_t n) const
Returns true if n is in this set.
Definition PointsTo.cpp:131
bool intersectWithComplement(const PointsTo &rhs)
Definition PointsTo.cpp:286
bool test(unsigned Idx) const
bool intersects(const SparseBitVector< ElementSize > *RHS) const
bool test_and_set(unsigned Idx)
void set(unsigned Idx)
bool intersectWithComplement(const SparseBitVector &RHS)
unsigned count() const
bool contains(const SparseBitVector< ElementSize > &RHS) const
iterator begin() const
void reset(unsigned Idx)
for isBitcode
Definition BasicTypes.h:68
u32_t NodeID
Definition GeneralType.h:55
IntervalValue operator-(const IntervalValue &lhs, const IntervalValue &rhs)
Subtract IntervalValues.
IntervalValue operator&(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise AND of IntervalValues.
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise OR of IntervalValues.
unsigned u32_t
Definition GeneralType.h:46