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::destroyBacking: unknown type");
61}
62
64{
66
67 nodeMapping = nullptr;
68 reverseNodeMapping = nullptr;
69}
70
72{
73 if (this == &rhs)
74 return *this;
75 // End the lifetime of the backing held now before placement new builds the
76 // new one over it. Destroy through the type stored now, which may differ
77 // from rhs's. Without this the old backing's storage is never freed.
79 this->type = rhs.type;
80 this->nodeMapping = rhs.nodeMapping;
82 // Placement new because if type has changed, we have
83 // not constructed the new type yet.
84 if (type == SBV) new (&sbv) SparseBitVector<>(rhs.sbv);
85 else if (type == CBV) new (&cbv) CoreBitVector(rhs.cbv);
86 else if (type == BV) new (&bv) BitVector(rhs.bv);
87 else assert(false && "PointsTo::PointsTo=&: unknown type");
88
89 return *this;
90}
91
93noexcept
94{
95 if (this == &rhs)
96 return *this;
97 // See comment in copy assignment.
98 destroyBacking();
99 this->type = rhs.type;
100 this->nodeMapping = rhs.nodeMapping;
101 this->reverseNodeMapping = rhs.reverseNodeMapping;
102 if (type == SBV) new (&sbv) SparseBitVector<>(std::move(rhs.sbv));
103 else if (type == CBV) new (&cbv) CoreBitVector(std::move(rhs.cbv));
104 else if (type == BV) new (&bv) BitVector(std::move(rhs.bv));
105 else assert(false && "PointsTo::PointsTo=&&: unknown type");
106
107 return *this;
108}
109
110bool PointsTo::empty() const
111{
112 if (type == CBV) return cbv.empty();
113 else if (type == SBV) return sbv.empty();
114 else if (type == BV) return bv.empty();
115 else
116 {
117 assert(false && "PointsTo::empty: unknown type");
118 abort();
119 }
120}
121
124{
125 if (type == CBV) return cbv.count();
126 else if (type == SBV) return sbv.count();
127 else if (type == BV) return bv.count();
128 else
129 {
130 assert(false && "PointsTo::count: unknown type");
131 abort();
132 }
133}
134
136{
137 if (type == CBV) cbv.clear();
138 else if (type == SBV) sbv.clear();
139 else if (type == BV) bv.clear();
140 else assert(false && "PointsTo::clear: unknown type");
141}
142
144{
146 if (type == CBV) return cbv.test(n);
147 else if (type == SBV) return sbv.test(n);
148 else if (type == BV) return bv.test(n);
149 else
150 {
151 assert(false && "PointsTo::test: unknown type");
152 abort();
153 }
154}
155
157{
159 if (type == CBV) return cbv.test_and_set(n);
160 else if (type == SBV) return sbv.test_and_set(n);
161 else if (type == BV) return bv.test_and_set(n);
162 else
163 {
164 assert(false && "PointsTo::test_and_set: unknown type");
165 abort();
166 }
167}
168
170{
172 if (type == CBV) cbv.set(n);
173 else if (type == SBV) sbv.set(n);
174 else if (type == BV) bv.set(n);
175 else assert(false && "PointsTo::set: unknown type");
176}
177
179{
181 if (type == CBV) cbv.reset(n);
182 else if (type == SBV) sbv.reset(n);
183 else if (type == BV) bv.reset(n);
184 else assert(false && "PointsTo::reset: unknown type");
185}
186
188{
189 assert(metaSame(rhs) && "PointsTo::contains: mappings of operands do not match!");
190
191 if (type == CBV) return cbv.contains(rhs.cbv);
192 else if (type == SBV) return sbv.contains(rhs.sbv);
193 else if (type == BV) return bv.contains(rhs.bv);
194 else
195 {
196 assert(false && "PointsTo::contains: unknown type");
197 abort();
198 }
199}
200
202{
203 assert(metaSame(rhs) && "PointsTo::intersects: mappings of operands do not match!");
204
205 if (type == CBV) return cbv.intersects(rhs.cbv);
206 else if (type == SBV) return sbv.intersects(rhs.sbv);
207 else if (type == BV) return bv.intersects(rhs.bv);
208 else
209 {
210 assert(false && "PointsTo::intersects: unknown type");
211 abort();
212 }
213}
214
216{
217 if (count() == 0) return -1;
218 return *begin();
219}
220
222{
223 assert(metaSame(rhs) && "PointsTo::==: mappings of operands do not match!");
224
225 if (type == CBV) return cbv == rhs.cbv;
226 else if (type == SBV) return sbv == rhs.sbv;
227 else if (type == BV) return bv == rhs.bv;
228 else
229 {
230 assert(false && "PointsTo::==: unknown type");
231 abort();
232 }
233}
234
236{
237 // TODO: we're asserting and checking twice... should be okay...
238 assert(metaSame(rhs) && "PointsTo::!=: mappings of operands do not match!");
239
240 return !(*this == rhs);
241}
242
244{
245 assert(metaSame(rhs) && "PointsTo::|=: mappings of operands do not match!");
246
247 if (type == CBV) return cbv |= rhs.cbv;
248 else if (type == SBV) return sbv |= rhs.sbv;
249 else if (type == BV) return bv |= rhs.bv;
250 else
251 {
252 assert(false && "PointsTo::|=: unknown type");
253 abort();
254 }
255}
256
258{
259 // TODO:
260 bool changed = false;
261 for (NodeID n : rhs)
262 {
263 if (changed) set(n);
264 else changed = test_and_set(n);
265 }
266
267 return changed;
268}
269
271{
272 assert(metaSame(rhs) && "PointsTo::&=: mappings of operands do not match!");
273
274 if (type == CBV) return cbv &= rhs.cbv;
275 else if (type == SBV) return sbv &= rhs.sbv;
276 else if (type == BV) return bv &= rhs.bv;
277 else
278 {
279 assert(false && "PointsTo::&=: unknown type");
280 abort();
281 }
282}
283
285{
286 assert(metaSame(rhs) && "PointsTo::-=: mappings of operands do not match!");
287
288 if (type == CBV) return cbv.intersectWithComplement(rhs.cbv);
289 else if (type == SBV) return sbv.intersectWithComplement(rhs.sbv);
290 else if (type == BV) return bv.intersectWithComplement(rhs.bv);
291 else
292 {
293 assert(false && "PointsTo::-=: unknown type");
294 abort();
295 }
296}
297
299{
300 assert(metaSame(rhs) && "PointsTo::intersectWithComplement: mappings of operands do not match!");
301
302 if (type == CBV) return cbv.intersectWithComplement(rhs.cbv);
303 else if (type == SBV) return sbv.intersectWithComplement(rhs.sbv);
304 else if (type == BV) return bv.intersectWithComplement(rhs.bv);
305
306 assert(false && "PointsTo::intersectWithComplement(PT): unknown type");
307 abort();
308}
309
311{
312 assert(metaSame(rhs) && "PointsTo::intersectWithComplement: mappings of operands do not match!");
313 assert(metaSame(lhs) && "PointsTo::intersectWithComplement: mappings of operands do not match!");
314
315 if (type == CBV) cbv.intersectWithComplement(lhs.cbv, rhs.cbv);
316 else if (type == SBV) sbv.intersectWithComplement(lhs.sbv, rhs.sbv);
317 else if (type == BV) bv.intersectWithComplement(lhs.bv, rhs.bv);
318 else
319 {
320 assert(false && "PointsTo::intersectWithComplement(PT, PT): unknown type");
321 abort();
322 }
323}
324
326{
327 NodeBS nbs;
328 for (const NodeID o : *this) nbs.set(o);
329 return nbs;
330}
331
332size_t PointsTo::hash() const
333{
334 if (type == CBV) return cbv.hash();
335 else if (type == SBV)
336 {
337 std::hash<SparseBitVector<>> h;
338 return h(sbv);
339 }
340 else if (type == BV) return bv.hash();
341
342 else
343 {
344 assert(false && "PointsTo::hash: unknown type");
345 abort();
346 }
347}
348
353
355{
356 if (nodeMapping == nullptr) return n;
358 return nodeMapping->at(n);
359}
360
362{
363 if (reverseNodeMapping == nullptr) return n;
365 return reverseNodeMapping->at(n);
366}
367
368bool PointsTo::metaSame(const PointsTo &pt) const
369{
371}
372
377
382
389
391{
393 {
394 // newPt constructed with correct node mapping.
396 for (const NodeID o : *this) newPt.set(o);
397 *this = std::move(newPt);
398 }
399}
400
402 : pt(pt)
403{
404 if (pt->type == Type::CBV)
405 {
407 }
408 else if (pt->type == Type::SBV)
409 {
411 }
412 else if (pt->type == Type::BV)
413 {
414 new (&bvIt) BitVector::iterator(end ? pt->bv.end() : pt->bv.begin());
415 }
416 else
417 {
418 assert(false && "PointsToIterator::PointsToIterator: unknown type");
419 abort();
420 }
421}
422
424 : pt(pt.pt)
425{
426 if (this->pt->type == PointsTo::Type::SBV)
427 {
429 }
430 else if (this->pt->type == PointsTo::Type::CBV)
431 {
432 new (&cbvIt) CoreBitVector::iterator(pt.cbvIt);
433 }
434 else if (this->pt->type == PointsTo::Type::BV)
435 {
436 new (&bvIt) BitVector::iterator(pt.bvIt);
437 }
438 else
439 {
440 assert(false && "PointsToIterator::PointsToIterator&: unknown type");
441 abort();
442 }
443}
444
446noexcept : pt(pt.pt)
447{
448 if (this->pt->type == PointsTo::Type::SBV)
449 {
450 new (&sbvIt) SparseBitVector<>::iterator(std::move(pt.sbvIt));
451 }
452 else if (this->pt->type == PointsTo::Type::CBV)
453 {
454 new (&cbvIt) CoreBitVector::iterator(std::move(pt.cbvIt));
455 }
456 else if (this->pt->type == PointsTo::Type::BV)
457 {
458 new (&bvIt) BitVector::iterator(std::move(pt.bvIt));
459 }
460 else
461 {
462 assert(false && "PointsToIterator::PointsToIterator&&: unknown type");
463 abort();
464 }
465}
466
468{
469 this->pt = rhs.pt;
470
471 if (this->pt->type == PointsTo::Type::SBV)
472 {
473 new (&sbvIt) SparseBitVector<>::iterator(rhs.sbvIt);
474 }
475 else if (this->pt->type == PointsTo::Type::CBV)
476 {
477 new (&cbvIt) CoreBitVector::iterator(rhs.cbvIt);
478 }
479 else if (this->pt->type == PointsTo::Type::BV)
480 {
481 new (&bvIt) BitVector::iterator(rhs.bvIt);
482 }
483 else assert(false && "PointsToIterator::PointsToIterator&: unknown type");
484
485 return *this;
486}
487
489{
490 this->pt = rhs.pt;
491
492 if (this->pt->type == PointsTo::Type::SBV)
493 {
494 new (&sbvIt) SparseBitVector<>::iterator(std::move(rhs.sbvIt));
495 }
496 else if (this->pt->type == PointsTo::Type::CBV)
497 {
498 new (&cbvIt) CoreBitVector::iterator(std::move(rhs.cbvIt));
499 }
500 else if (this->pt->type == PointsTo::Type::BV)
501 {
502 new (&bvIt) BitVector::iterator(std::move(rhs.bvIt));
503 }
504 else assert(false && "PointsToIterator::PointsToIterator&&: unknown type");
505
506 return *this;
507}
508
510{
511 assert(!atEnd() && "PointsToIterator::++(pre): incrementing past end!");
512 if (pt->type == Type::CBV) ++cbvIt;
513 else if (pt->type == Type::SBV) ++sbvIt;
514 else if (pt->type == Type::BV) ++bvIt;
515 else assert(false && "PointsToIterator::++(void): unknown type");
516
517 return *this;
518}
519
521{
522 assert(!atEnd() && "PointsToIterator::++(pre): incrementing past end!");
523 PointsToIterator old = *this;
524 ++*this;
525 return old;
526}
527
529{
530 assert(!atEnd() && "PointsToIterator: dereferencing end!");
531 if (pt->type == Type::CBV) return pt->getExternalNode(*cbvIt);
532 else if (pt->type == Type::SBV) return pt->getExternalNode(*sbvIt);
533 else if (pt->type == Type::BV) return pt->getExternalNode(*bvIt);
534 else
535 {
536 assert(false && "PointsToIterator::*: unknown type");
537 abort();
538 }
539}
540
542{
543 assert(pt == rhs.pt
544 && "PointsToIterator::==: comparing iterators from different PointsTos!");
545
546 // Handles end implicitly.
547 if (pt->type == Type::CBV) return cbvIt == rhs.cbvIt;
548 else if (pt->type == Type::SBV) return sbvIt == rhs.sbvIt;
549 else if (pt->type == Type::BV) return bvIt == rhs.bvIt;
550 else
551 {
552 assert(false && "PointsToIterator::==: unknown type");
553 abort();
554 }
555}
556
558{
559 assert(pt == rhs.pt
560 && "PointsToIterator::!=: comparing iterators from different PointsTos!");
561 return !(*this == rhs);
562}
563
565{
566 assert(pt != nullptr && "PointsToIterator::atEnd: iterator iterating over nothing!");
567 if (pt->type == Type::CBV) return cbvIt == pt->cbv.end();
568 else if (pt->type == Type::SBV) return sbvIt == pt->sbv.end();
569 else if (pt->type == Type::BV) return bvIt == pt->bv.end();
570 else
571 {
572 assert(false && "PointsToIterator::atEnd: unknown type");
573 abort();
574 }
575}
576
578{
579 // TODO: optimise.
581 result |= rhs;
582 return result;
583}
584
586{
587 // TODO: optimise.
589 result &= rhs;
590 return result;
591}
592
594{
595 // TODO: optimise.
597 result -= rhs;
598 return result;
599}
600
601}; // 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:16
u32_t operator*() const
Dereference: *it.
Definition PointsTo.cpp:528
CoreBitVector::iterator cbvIt
Definition PointsTo.h:234
SparseBitVector ::iterator sbvIt
Definition PointsTo.h:233
const PointsTo * pt
PointsTo we are iterating over.
Definition PointsTo.h:228
BitVector::iterator bvIt
Definition PointsTo.h:235
bool operator!=(const PointsToIterator &rhs) const
Inequality: *this != rhs.
Definition PointsTo.cpp:557
PointsToIterator()=delete
Deleted because we don't want iterators with null pt.
const PointsToIterator & operator++()
Pre-increment: ++it.
Definition PointsTo.cpp:509
PointsToIterator & operator=(const PointsToIterator &rhs)
Definition PointsTo.cpp:467
bool operator==(const PointsToIterator &rhs) const
Equality: *this == rhs.
Definition PointsTo.cpp:541
bool test_and_set(u32_t n)
Definition PointsTo.cpp:156
bool empty() const
Returns true if set is empty.
Definition PointsTo.cpp:110
void clear()
Empty the set.
Definition PointsTo.cpp:135
static MappingPtr getCurrentBestReverseNodeMapping()
Definition PointsTo.cpp:378
MappingPtr reverseNodeMapping
Internal nodes -> external nodes.
Definition PointsTo.h:184
void reset(u32_t n)
Removes n from the set.
Definition PointsTo.cpp:178
bool operator-=(const PointsTo &rhs)
Definition PointsTo.cpp:284
PointsTo & operator=(const PointsTo &rhs)
Copy assignment.
Definition PointsTo.cpp:71
size_t hash() const
Return a hash of this set.
Definition PointsTo.cpp:332
bool operator&=(const PointsTo &rhs)
Definition PointsTo.cpp:270
static MappingPtr currentBestReverseNodeMapping
Likewise, but reversed.
Definition PointsTo.h:165
MappingPtr getNodeMapping() const
Definition PointsTo.cpp:349
BitVector bv
Bit vector backing.
Definition PointsTo.h:176
bool operator==(const PointsTo &rhs) const
Returns true if this set and rhs contain exactly the same elements.
Definition PointsTo.cpp:221
const_iterator end() const
Definition PointsTo.h:133
void checkAndRemap()
Definition PointsTo.cpp:390
CoreBitVector cbv
Core bit vector backing.
Definition PointsTo.h:174
NodeID getExternalNode(NodeID n) const
Returns reverseNodeMapping[n], checking for nullptr and size.
Definition PointsTo.cpp:361
std::shared_ptr< std::vector< NodeID > > MappingPtr
Definition PointsTo.h:43
static void setCurrentBestNodeMapping(MappingPtr newCurrentBestNodeMapping, MappingPtr newCurrentBestReverseNodeMapping)
Definition PointsTo.cpp:383
bool operator!=(const PointsTo &rhs) const
Returns true if either this set or rhs has an element not in the other.
Definition PointsTo.cpp:235
static MappingPtr currentBestNodeMapping
Best node mapping we know of the for the analyses at hand.
Definition PointsTo.h:163
u32_t count() const
Returns number of elements.
Definition PointsTo.cpp:123
bool metaSame(const PointsTo &pt) const
Definition PointsTo.cpp:368
bool operator|=(const PointsTo &rhs)
Definition PointsTo.cpp:243
enum Type type
Type of this points-to set.
Definition PointsTo.h:180
void set(u32_t n)
Inserts n in the set.
Definition PointsTo.cpp:169
bool contains(const PointsTo &rhs) const
Returns true if this set is a superset of rhs.
Definition PointsTo.cpp:187
PointsTo()
Construct empty points-to set.
Definition PointsTo.cpp:25
MappingPtr nodeMapping
External nodes -> internal nodes.
Definition PointsTo.h:182
void destroyBacking()
Definition PointsTo.cpp:55
NodeBS toNodeBS() const
Returns this points-to set as a NodeBS.
Definition PointsTo.cpp:325
const_iterator begin() const
Definition PointsTo.h:129
bool intersects(const PointsTo &rhs) const
Returns true if this set and rhs share any elements.
Definition PointsTo.cpp:201
static MappingPtr getCurrentBestNodeMapping()
Definition PointsTo.cpp:373
SparseBitVector sbv
Sparse bit vector backing.
Definition PointsTo.h:172
NodeID getInternalNode(NodeID n) const
Returns nodeMapping[n], checking for nullptr and size.
Definition PointsTo.cpp:354
bool test(u32_t n) const
Returns true if n is in this set.
Definition PointsTo.cpp:143
bool intersectWithComplement(const PointsTo &rhs)
Definition PointsTo.cpp:298
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:70
u32_t NodeID
Definition GeneralType.h:76
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:76
IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise OR of IntervalValues.
unsigned u32_t
Definition GeneralType.h:67