Static Value-Flow Analysis
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"
16 #include "MemoryModel/PointsTo.h"
17 #include "SVFIR/SVFValue.h"
18 
19 namespace 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 
46 noexcept : 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 
84 noexcept
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 
98 bool 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 
131 bool PointsTo::test(u32_t n) const
132 {
133  n = getInternalNode(n);
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 {
146  n = getInternalNode(n);
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 {
159  n = getInternalNode(n);
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 {
168  n = getInternalNode(n);
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 
175 bool PointsTo::contains(const PointsTo &rhs) const
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 
189 bool PointsTo::intersects(const PointsTo &rhs) const
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 
209 bool PointsTo::operator==(const PointsTo &rhs) const
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 
223 bool PointsTo::operator!=(const PointsTo &rhs) const
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 
245 bool PointsTo::operator|=(const NodeBS &rhs)
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 
320 size_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 
338 {
339  return nodeMapping;
340 }
341 
343 {
344  if (nodeMapping == nullptr) return n;
345  assert(n < nodeMapping->size());
346  return nodeMapping->at(n);
347 }
348 
350 {
351  if (reverseNodeMapping == nullptr) return n;
352  assert(n < reverseNodeMapping->size());
353  return reverseNodeMapping->at(n);
354 }
355 
356 bool PointsTo::metaSame(const PointsTo &pt) const
357 {
359 }
360 
362 {
363  return currentBestNodeMapping;
364 }
365 
367 {
369 }
370 
371 void PointsTo::setCurrentBestNodeMapping(MappingPtr newCurrentBestNodeMapping,
372  MappingPtr newCurrentBestReverseNodeMapping)
373 {
374  currentBestNodeMapping = std::move(newCurrentBestNodeMapping);
375  currentBestReverseNodeMapping = std::move(newCurrentBestReverseNodeMapping);
376 }
377 
379 {
381  {
382  // newPt constructed with correct node mapping.
383  PointsTo newPt;
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  {
394  new (&cbvIt) CoreBitVector::iterator(end ? pt->cbv.end() : pt->cbv.begin());
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  {
416  new (&sbvIt) SparseBitVector<>::iterator(pt.sbvIt);
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 
434 noexcept : 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 
565 PointsTo operator|(const PointsTo &lhs, const PointsTo &rhs)
566 {
567  // TODO: optimise.
568  PointsTo result = lhs;
569  result |= rhs;
570  return result;
571 }
572 
573 PointsTo operator&(const PointsTo &lhs, const PointsTo &rhs)
574 {
575  // TODO: optimise.
576  PointsTo result = lhs;
577  result &= rhs;
578  return result;
579 }
580 
581 PointsTo operator-(const PointsTo &lhs, const PointsTo &rhs)
582 {
583  // TODO: optimise.
584  PointsTo result = lhs;
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
int find_first()
Definition: PointsTo.cpp:203
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
iterator end() 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)
constexpr std::remove_reference< T >::type && move(T &&t) noexcept
Definition: SVFUtil.h:447
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.
IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rhs)
Bitwise OR of IntervalValues.
unsigned u32_t
Definition: GeneralType.h:46