Static Value-Flow Analysis
PersistentPointsToDS.h
Go to the documentation of this file.
1 
4 /*
5  * PersistentPointsToDS.h
6  *
7  * Authors: Mohamad Barbar
8  *
9  * The implementation is based on
10  * Mohamad Barbar and Yulei Sui. Hash Consed Points-To Sets.
11  * 28th Static Analysis Symposium (SAS'21)
12  */
13 
14 #ifndef PERSISTENT_POINTSTO_H_
15 #define PERSISTENT_POINTSTO_H_
16 
19 #include "MemoryModel/PointsTo.h"
20 #include "Util/SVFUtil.h"
21 
22 namespace SVF
23 {
24 
25 template <typename Key, typename KeySet, typename Data, typename DataSet>
26 class PersistentDFPTData;
27 template <typename Key, typename KeySet, typename Data, typename DataSet>
28 class PersistentIncDFPTData;
29 template <typename Key, typename KeySet, typename Data, typename DataSet, typename VersionedKey, typename VersionedKeySet>
30 class PersistentVersionedPTData;
31 
33 template <typename Key, typename KeySet, typename Data, typename DataSet>
34 class PersistentPTData : public PTData<Key, KeySet, Data, DataSet>
35 {
36  template <typename K, typename KS, typename D, typename DS, typename VK, typename VKS>
38  friend class PersistentDFPTData<Key, KeySet, Data, DataSet>;
39  friend class PersistentIncDFPTData<Key, KeySet, Data, DataSet>;
40 public:
42  typedef typename BasePTData::PTDataTy PTDataTy;
43 
46 
48  explicit PersistentPTData(PersistentPointsToCache<DataSet> &cache, bool reversePT = true, PTDataTy ty = PTDataTy::PersBase)
49  : BasePTData(reversePT, ty), ptCache(cache) { }
50 
51  ~PersistentPTData() override = default;
52 
53  inline void clear() override
54  {
55  ptsMap.clear();
56  revPtsMap.clear();
57  }
58 
59  inline const DataSet& getPts(const Key &var) override
60  {
61  PointsToID id = ptsMap[var];
62  return ptCache.getActualPts(id);
63  }
64 
65  inline const KeySet& getRevPts(const Data &data) override
66  {
67  assert(this->rev && "PersistentPTData::getRevPts: constructed without reverse PT support!");
68  return revPtsMap[data];
69  }
70 
71  inline bool addPts(const Key &dstKey, const Data &element) override
72  {
73  DataSet srcPts;
74  srcPts.set(element);
75  PointsToID srcId = ptCache.emplacePts(srcPts);
76  return unionPtsFromId(dstKey, srcId);
77  }
78 
79  inline bool unionPts(const Key& dstKey, const Key& srcKey) override
80  {
81  PointsToID srcId = ptsMap[srcKey];
82  return unionPtsFromId(dstKey, srcId);
83  }
84 
85  inline bool unionPts(const Key& dstKey, const DataSet& srcData) override
86  {
87  PointsToID srcId = ptCache.emplacePts(srcData);
88  return unionPtsFromId(dstKey, srcId);
89  }
90 
91  inline void dumpPTData() override
92  {
93  }
94 
95  void clearPts(const Key &var, const Data &element) override
96  {
97  DataSet toRemoveData;
98  toRemoveData.set(element);
99  PointsToID toRemoveId = ptCache.emplacePts(toRemoveData);
100  PointsToID varId = ptsMap[var];
101  PointsToID complementId = ptCache.complementPts(varId, toRemoveId);
102  if (varId != complementId)
103  {
104  ptsMap[var] = complementId;
105  clearSingleRevPts(revPtsMap[element], var);
106  }
107  }
108 
109  void clearFullPts(const Key& var) override
110  {
111  clearRevPts(getPts(var), var);
113  }
114 
115  void remapAllPts() override
116  {
118  }
119 
120  Map<DataSet, unsigned> getAllPts(bool liveOnly) const override
121  {
122  Map<DataSet, unsigned> allPts;
123  if (liveOnly)
124  {
125  for (const typename KeyToIDMap::value_type &ki : ptsMap)
126  {
127  ++allPts[ptCache.getActualPts(ki.second)];
128  }
129  }
130  else
131  {
132  allPts = ptCache.getAllPts();
133  }
134 
135  return allPts;
136  }
137 
141  {
142  return true;
143  }
144 
145  static inline bool classof(const PTData<Key, KeySet, Data, DataSet>* ptd)
146  {
147  return ptd->getPTDTY() == PTDataTy::PersBase;
148  }
150 
151 private:
154  inline bool unionPtsFromId(const Key &dstKey, PointsToID srcId)
155  {
156  PointsToID dstId = ptsMap[dstKey];
157  PointsToID newDstId = ptCache.unionPts(dstId, srcId);
158 
159  bool changed = newDstId != dstId;
160  if (changed)
161  {
162  ptsMap[dstKey] = newDstId;
163 
164  // Reverse points-to only needs to be handled when dst's
165  // points-to set has changed (i.e., do it the first time only).
166  if (this->rev)
167  {
168  const DataSet &srcPts = ptCache.getActualPts(srcId);
169  for (const Data &d : srcPts) SVFUtil::insertKey(dstKey, revPtsMap[d]);
170  }
171  }
172 
173  return changed;
174  }
175 
176  inline void clearSingleRevPts(KeySet &revSet, const Key &k)
177  {
178  if (this->rev)
179  {
180  SVFUtil::removeKey(k, revSet);
181  }
182  }
183 
184  inline void clearRevPts(const DataSet &pts, const Key &k)
185  {
186  if (this->rev)
187  {
188  for (const Data &d : pts) clearSingleRevPts(revPtsMap[d], k);
189  }
190  }
191 
192 protected:
196 };
197 
199 template <typename Key, typename KeySet, typename Data, typename DataSet>
200 class PersistentDiffPTData : public DiffPTData<Key, KeySet, Data, DataSet>
201 {
202 public:
206  typedef typename BasePTData::PTDataTy PTDataTy;
207 
210 
212  explicit PersistentDiffPTData(PersistentPointsToCache<DataSet> &cache, bool reversePT = true, PTDataTy ty = PTDataTy::PersDiff)
213  : BaseDiffPTData(reversePT, ty), ptCache(cache), persPTData(cache, reversePT) { }
214 
215  ~PersistentDiffPTData() override = default;
216 
217  void clear() override
218  {
219  persPTData.clear();
220  diffPtsMap.clear();
221  propaPtsMap.clear();
222  }
223 
224  inline const DataSet &getPts(const Key& var) override
225  {
226  return persPTData.getPts(var);
227  }
228 
229  inline const KeySet& getRevPts(const Data &data) override
230  {
231  assert(this->rev && "PersistentDiffPTData::getRevPts: constructed without reverse PT support!");
232  return persPTData.getRevPts(data);
233  }
234 
235  inline bool addPts(const Key &dstKey, const Data &element) override
236  {
237  return persPTData.addPts(dstKey, element);
238  }
239 
240  inline bool unionPts(const Key& dstKey, const Key& srcKey) override
241  {
242  return persPTData.unionPts(dstKey, srcKey);
243  }
244 
245  inline bool unionPts(const Key &dstKey, const DataSet &srcDataSet) override
246  {
247  return persPTData.unionPts(dstKey, srcDataSet);
248  }
249 
250  void clearPts(const Key &var, const Data &element) override
251  {
252  return persPTData.clearPts(var, element);
253  }
254 
255  void clearFullPts(const Key &var) override
256  {
257  return persPTData.clearFullPts(var);
258  }
259 
260  void remapAllPts() override
261  {
263  }
264 
265  inline void dumpPTData() override
266  {
267  // TODO.
268  }
269 
270  inline const DataSet &getDiffPts(Key &var) override
271  {
272  PointsToID id = diffPtsMap[var];
273  return ptCache.getActualPts(id);
274  }
275 
276  inline bool computeDiffPts(Key &var, const DataSet &all) override
277  {
278  PointsToID propaId = propaPtsMap[var];
279  PointsToID allId = ptCache.emplacePts(all);
280  // Diff is made up of the entire points-to set minus what has been propagated.
281  PointsToID diffId = ptCache.complementPts(allId, propaId);
282  diffPtsMap[var] = diffId;
283 
284  // We've now propagated the entire thing.
285  propaPtsMap[var] = allId;
286 
287  // Whether diff is empty or not; just need to check against the ID since it
288  // is the only empty set.
289  return diffId != ptCache.emptyPointsToId();
290  }
291 
292  inline void updatePropaPtsMap(Key &src, Key &dst) override
293  {
294  PointsToID dstId = propaPtsMap[dst];
295  PointsToID srcId = propaPtsMap[src];
296  propaPtsMap[dst] = ptCache.intersectPts(dstId, srcId);
297  }
298 
299  inline void clearPropaPts(Key &var) override
300  {
302  }
303 
304  Map<DataSet, unsigned> getAllPts(bool liveOnly) const override
305  {
306  return persPTData.getAllPts(liveOnly);
307  }
308 
312  {
313  return true;
314  }
315 
316  static inline bool classof(const PTData<Key, KeySet, Data, DataSet>* ptd)
317  {
318  return ptd->getPTDTY() == PTDataTy::PersDiff;
319  }
321 
322 private:
330 };
331 
333 template <typename Key, typename KeySet, typename Data, typename DataSet>
334 class PersistentDFPTData : public DFPTData<Key, KeySet, Data, DataSet>
335 {
336 public:
338  typedef typename BasePTData::PTDataTy PTDataTy;
341 
342  typedef typename BaseDFPTData::LocID LocID;
345 
346  explicit PersistentDFPTData(PersistentPointsToCache<DataSet> &cache, bool reversePT = true, PTDataTy ty = PTDataTy::PersDataFlow)
347  : BaseDFPTData(reversePT, ty), ptCache(cache), persPTData(cache, reversePT) { }
348 
349  ~PersistentDFPTData() override = default;
350 
351  inline void clear() override
352  {
353  dfInPtsMap.clear();
354  dfOutPtsMap.clear();
355  persPTData.clear();
356  }
357 
358  inline const DataSet &getPts(const Key& var) override
359  {
360  return persPTData.getPts(var);
361  }
362 
363  inline const KeySet& getRevPts(const Data&) override
364  {
365  assert(false && "PersistentDFPTData::getRevPts: not supported yet!");
366  abort();
367  }
368 
369  inline bool unionPts(const Key& dstKey, const Key& srcKey) override
370  {
371  return persPTData.unionPts(dstKey, srcKey);
372  }
373 
374  inline bool unionPts(const Key& dstKey, const DataSet &srcDataSet) override
375  {
376  return persPTData.unionPts(dstKey, srcDataSet);
377  }
378 
379  inline bool addPts(const Key &dstKey, const Data &element) override
380  {
381  return persPTData.addPts(dstKey, element);
382  }
383 
384  void clearPts(const Key& var, const Data &element) override
385  {
386  persPTData.clearPts(var, element);
387  }
388 
389  void clearFullPts(const Key& var) override
390  {
391  persPTData.clearFullPts(var);
392  }
393 
394  void remapAllPts() override
395  {
397  }
398 
399  inline void dumpPTData() override
400  {
401  persPTData.dumpPTData();
402  }
403 
404  bool hasDFInSet(LocID loc) const override
405  {
406  return dfInPtsMap.find(loc) != dfInPtsMap.end();
407  }
408 
409  bool hasDFOutSet(LocID loc) const override
410  {
411  return dfOutPtsMap.find(loc) != dfOutPtsMap.end();
412  }
413 
414  bool hasDFInSet(LocID loc, const Key& var) const override
415  {
416  typename DFKeyToIDMap::const_iterator foundInKeyToId = dfInPtsMap.find(loc);
417  if (foundInKeyToId == dfInPtsMap.end()) return false;
418  const KeyToIDMap &inKeyToId = foundInKeyToId->second;
419  return (inKeyToId.find(var) != inKeyToId.end());
420  }
421 
422  bool hasDFOutSet(LocID loc, const Key& var) const override
423  {
424  typename DFKeyToIDMap::const_iterator foundOutKeyToId = dfOutPtsMap.find(loc);
425  if (foundOutKeyToId == dfOutPtsMap.end()) return false;
426  const KeyToIDMap &outKeyToId = foundOutKeyToId->second;
427  return (outKeyToId.find(var) != outKeyToId.end());
428  }
429 
430  const DataSet &getDFInPtsSet(LocID loc, const Key& var) override
431  {
432  PointsToID id = dfInPtsMap[loc][var];
433  return ptCache.getActualPts(id);
434  }
435 
436  const DataSet &getDFOutPtsSet(LocID loc, const Key& var) override
437  {
438  PointsToID id = dfOutPtsMap[loc][var];
439  return ptCache.getActualPts(id);
440  }
441 
442  bool updateDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
443  {
444  return unionPtsThroughIds(getDFInPtIdRef(dstLoc, dstVar), getDFInPtIdRef(srcLoc, srcVar));
445  }
446 
447  bool updateAllDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
448  {
449  return updateDFInFromIn(srcLoc, srcVar, dstLoc, dstVar);
450  }
451 
452  bool updateDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
453  {
454  return unionPtsThroughIds(getDFInPtIdRef(dstLoc, dstVar), getDFOutPtIdRef(srcLoc, srcVar));
455  }
456 
457  bool updateAllDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
458  {
459  return updateDFInFromOut(srcLoc, srcVar, dstLoc, dstVar);
460  }
461 
462  bool updateDFOutFromIn(LocID srcLoc, const Key& srcVar, LocID dstLoc, const Key& dstVar) override
463  {
464  return unionPtsThroughIds(getDFOutPtIdRef(dstLoc, dstVar), getDFInPtIdRef(srcLoc, srcVar));
465  }
466 
467  bool updateAllDFOutFromIn(LocID loc, const Key &singleton, bool strongUpdates) override
468  {
469  bool changed = false;
470  if (this->hasDFInSet(loc))
471  {
472  const KeyToIDMap &inKeyToId = dfInPtsMap[loc];
473  for (const typename KeyToIDMap::value_type &ki : inKeyToId)
474  {
475  const Key var = ki.first;
477  if (strongUpdates && var == singleton) continue;
478 
479  if (updateDFOutFromIn(loc, var, loc, var)) changed = true;
480  }
481  }
482 
483  return changed;
484  }
485 
487  {
488  }
489 
491  bool updateTLVPts(LocID srcLoc, const Key &srcVar, const Key &dstVar) override
492  {
493  return unionPtsThroughIds(persPTData.ptsMap[dstVar], getDFInPtIdRef(srcLoc, srcVar));
494  }
495 
496  bool updateATVPts(const Key& srcVar, LocID dstLoc, const Key& dstVar) override
497  {
498  return unionPtsThroughIds(getDFOutPtIdRef(dstLoc, dstVar), persPTData.ptsMap[srcVar]);
499  }
500 
501  Map<DataSet, unsigned> getAllPts(bool liveOnly) const override
502  {
503  Map<DataSet, unsigned> allPts = persPTData.getAllPts(liveOnly);
504  for (const typename DFKeyToIDMap::value_type &lki : dfInPtsMap)
505  {
506  for (const typename KeyToIDMap::value_type &ki : lki.second)
507  {
508  ++allPts[ptCache.getActualPts(ki.second)];
509  }
510  }
511 
512  for (const typename DFKeyToIDMap::value_type &lki : dfOutPtsMap)
513  {
514  for (const typename KeyToIDMap::value_type &ki : lki.second)
515  {
516  ++allPts[ptCache.getActualPts(ki.second)];
517  }
518  }
519 
520  if (!liveOnly)
521  {
522  // Subtract 1 from each counted points-to set because the live points-to
523  // sets have already been inserted and accounted for how often they occur.
524  // They will each occur one more time in the cache.
525  // In essence, we want the ptCache.getAllPts() to just add the unused, non-GC'd
526  // points-to sets to allPts.
527  for (typename Map<DataSet, unsigned>::value_type pto : allPts) pto.second -= 1;
528  SVFUtil::mergePtsOccMaps<DataSet>(allPts, ptCache.getAllPts());
529  }
530 
531  return allPts;
532  }
533 
537  {
538  return true;
539  }
540 
541  static inline bool classof(const PTData<Key, KeySet, Data, DataSet> *ptd)
542  {
543  return ptd->getPTDTY() == PTDataTy::PersDataFlow
544  || ptd->getPTDTY() == PTDataTy::PersIncDataFlow;
545  }
547 
548 protected:
549  inline bool unionPtsThroughIds(PointsToID &dst, PointsToID &src)
550  {
551  PointsToID oldDst = dst;
552  dst = ptCache.unionPts(dst, src);
553  return oldDst != dst;
554  }
555 
556  PointsToID &getDFInPtIdRef(LocID loc, const Key &var)
557  {
558  return dfInPtsMap[loc][var];
559  }
560 
561  PointsToID &getDFOutPtIdRef(LocID loc, const Key &var)
562  {
563  return dfOutPtsMap[loc][var];
564  }
565 
566 protected:
568 
571 
576 };
577 
579 template <typename Key, typename KeySet, typename Data, typename DataSet>
580 class PersistentIncDFPTData : public PersistentDFPTData<Key, KeySet, Data, DataSet>
581 {
582 public:
587  typedef typename BasePTData::PTDataTy PTDataTy;
588 
589  typedef typename BaseDFPTData::LocID LocID;
591 
592 public:
595  : BasePersDFPTData(cache, reversePT, ty) { }
596 
597  ~PersistentIncDFPTData() override = default;
598 
599  inline bool updateDFInFromIn(LocID srcLoc, const Key& srcVar, LocID dstLoc, const Key& dstVar) override
600  {
601  if (varHasNewDFInPts(srcLoc, srcVar)
602  && this->unionPtsThroughIds(this->getDFInPtIdRef(dstLoc, dstVar), this->getDFInPtIdRef(srcLoc, srcVar)))
603  {
604  setVarDFInSetUpdated(dstLoc, dstVar);
605  return true;
606  }
607 
608  return false;
609  }
610 
611  inline bool updateDFInFromOut(LocID srcLoc, const Key& srcVar, LocID dstLoc, const Key& dstVar) override
612  {
613  if (varHasNewDFOutPts(srcLoc, srcVar)
614  && this->unionPtsThroughIds(this->getDFInPtIdRef(dstLoc, dstVar), this->getDFOutPtIdRef(srcLoc, srcVar)))
615  {
616  setVarDFInSetUpdated(dstLoc, dstVar);
617  return true;
618  }
619 
620  return false;
621  }
622 
623  inline bool updateDFOutFromIn(LocID srcLoc, const Key& srcVar, LocID dstLoc, const Key& dstVar) override
624  {
625  if (varHasNewDFInPts(srcLoc, srcVar))
626  {
627  removeVarFromDFInUpdatedSet(srcLoc, srcVar);
628  if (this->unionPtsThroughIds(this->getDFOutPtIdRef(dstLoc, dstVar), this->getDFInPtIdRef(srcLoc, srcVar)))
629  {
630  setVarDFOutSetUpdated(dstLoc, dstVar);
631  return true;
632  }
633  }
634 
635  return false;
636  }
637 
638  inline bool updateAllDFInFromOut(LocID srcLoc, const Key& srcVar, LocID dstLoc, const Key& dstVar) override
639  {
640  if (this->unionPtsThroughIds(this->getDFInPtIdRef(dstLoc, dstVar), this->getDFOutPtIdRef(srcLoc, srcVar)))
641  {
642  setVarDFInSetUpdated(dstLoc, dstVar);
643  return true;
644  }
645 
646  return false;
647  }
648 
649  inline bool updateAllDFInFromIn(LocID srcLoc, const Key& srcVar, LocID dstLoc, const Key& dstVar) override
650  {
651  if (this->unionPtsThroughIds(this->getDFInPtIdRef(dstLoc, dstVar), this->getDFInPtIdRef(srcLoc, srcVar)))
652  {
653  setVarDFInSetUpdated(dstLoc, dstVar);
654  return true;
655  }
656 
657  return false;
658  }
659 
660  inline bool updateAllDFOutFromIn(LocID loc, const Key& singleton, bool strongUpdates) override
661  {
662  bool changed = false;
663  if (this->hasDFInSet(loc))
664  {
666  const KeySet vars = getDFInUpdatedVar(loc);
667  for (const Key &var : vars)
668  {
670  if (strongUpdates && var == singleton) continue;
671  if (updateDFOutFromIn(loc, var, loc, var)) changed = true;
672  }
673  }
674 
675  return changed;
676  }
677 
678  inline bool updateTLVPts(LocID srcLoc, const Key& srcVar, const Key& dstVar) override
679  {
680  if (varHasNewDFInPts(srcLoc, srcVar))
681  {
682  removeVarFromDFInUpdatedSet(srcLoc, srcVar);
683  return this->unionPtsThroughIds(this->persPTData.ptsMap[dstVar], this->getDFInPtIdRef(srcLoc, srcVar));
684  }
685 
686  return false;
687  }
688 
689  inline bool updateATVPts(const Key& srcVar, LocID dstLoc, const Key& dstVar) override
690  {
691  if (this->unionPtsThroughIds(this->getDFOutPtIdRef(dstLoc, dstVar), this->persPTData.ptsMap[srcVar]))
692  {
693  setVarDFOutSetUpdated(dstLoc, dstVar);
694  return true;
695  }
696 
697  return false;
698  }
699 
700  inline void clearAllDFOutUpdatedVar(LocID loc) override
701  {
702  if (this->hasDFOutSet(loc))
703  {
704  const KeySet vars = getDFOutUpdatedVar(loc);
705  for (const Key &var : vars)
706  {
708  }
709  }
710  }
711 
712  inline void clear() override
713  {
714  outUpdatedVarMap.clear();
715  inUpdatedVarMap.clear();
717  }
718 
722  {
723  return true;
724  }
725 
726  static inline bool classof(const PTData<Key, KeySet, Data, DataSet> *ptd)
727  {
728  return ptd->getPTDTY() == BasePTData::PersIncDataFlow;
729  }
731 
732 private:
733 
735 
736  inline void setVarDFInSetUpdated(LocID loc, const Key& var)
738  {
740  }
741 
743  inline void removeVarFromDFInUpdatedSet(LocID loc, const Key& var)
744  {
745  typename UpdatedVarMap::iterator it = inUpdatedVarMap.find(loc);
746  if (it != inUpdatedVarMap.end()) it->second.erase(var);
747  }
748 
750  inline bool varHasNewDFInPts(LocID loc, const Key& var)
751  {
752  typename UpdatedVarMap::iterator it = inUpdatedVarMap.find(loc);
753  if (it != inUpdatedVarMap.end()) return it->second.find(var) != it->second.end();
754  return false;
755  }
756 
758  inline const KeySet& getDFInUpdatedVar(LocID loc)
759  {
760  return inUpdatedVarMap[loc];
761  }
763 
767  inline void setVarDFOutSetUpdated(LocID loc, const Key& var)
768  {
770  }
771 
773  inline void removeVarFromDFOutUpdatedSet(LocID loc, const Key& var)
774  {
775  typename UpdatedVarMap::iterator it = outUpdatedVarMap.find(loc);
776  if (it != outUpdatedVarMap.end()) it->second.erase(var);
777  }
778 
780  inline bool varHasNewDFOutPts(LocID loc, const Key& var)
781  {
782  typename UpdatedVarMap::iterator it = outUpdatedVarMap.find(loc);
783  if (it != outUpdatedVarMap.end()) return it->second.find(var) != it->second.end();
784  return false;
785  }
786 
788  inline const KeySet& getDFOutUpdatedVar(LocID loc)
789  {
790  return outUpdatedVarMap[loc];
791  }
793 
794 
795 private:
798 };
799 
804 template <typename Key, typename KeySet, typename Data, typename DataSet, typename VersionedKey, typename VersionedKeySet>
805 class PersistentVersionedPTData : public VersionedPTData<Key, KeySet, Data, DataSet, VersionedKey, VersionedKeySet>
806 {
807 public:
810  typedef typename BasePTData::PTDataTy PTDataTy;
811 
814 
815  explicit PersistentVersionedPTData(PersistentPointsToCache<DataSet> &cache, bool reversePT = true, PTDataTy ty = PTDataTy::PersVersioned)
816  : BaseVersionedPTData(reversePT, ty), tlPTData(cache, reversePT), atPTData(cache, reversePT) { }
817 
818  ~PersistentVersionedPTData() override = default;
819 
820  inline void clear() override
821  {
822  tlPTData.clear();
823  atPTData.clear();
824  }
825 
826  const DataSet &getPts(const Key& vk) override
827  {
828  return tlPTData.getPts(vk);
829  }
830  const DataSet &getPts(const VersionedKey& vk) override
831  {
832  return atPTData.getPts(vk);
833  }
834 
835  const KeySet& getRevPts(const Data &data) override
836  {
837  assert(this->rev && "PersistentVersionedPTData::getRevPts: constructed without reverse PT support!");
838  return tlPTData.getRevPts(data);
839  }
840  const VersionedKeySet& getVersionedKeyRevPts(const Data &data) override
841  {
842  assert(this->rev && "PersistentVersionedPTData::getVersionedKeyRevPts: constructed without reverse PT support!");
843  return atPTData.getRevPts(data);
844  }
845 
846  bool addPts(const Key& k, const Data &element) override
847  {
848  return tlPTData.addPts(k, element);
849  }
850  bool addPts(const VersionedKey& vk, const Data &element) override
851  {
852  return atPTData.addPts(vk, element);
853  }
854 
855  bool unionPts(const Key& dstVar, const Key& srcVar) override
856  {
857  return tlPTData.unionPts(dstVar, srcVar);
858  }
859  bool unionPts(const VersionedKey& dstVar, const VersionedKey& srcVar) override
860  {
861  return atPTData.unionPts(dstVar, srcVar);
862  }
863  bool unionPts(const VersionedKey& dstVar, const Key& srcVar) override
864  {
865  return atPTData.unionPtsFromId(dstVar, tlPTData.ptsMap[srcVar]);
866  }
867  bool unionPts(const Key& dstVar, const VersionedKey& srcVar) override
868  {
869  return tlPTData.unionPtsFromId(dstVar, atPTData.ptsMap[srcVar]);
870  }
871  bool unionPts(const Key &dstVar, const DataSet &srcDataSet) override
872  {
873  return tlPTData.unionPts(dstVar, srcDataSet);
874  }
875  bool unionPts(const VersionedKey &dstVar, const DataSet &srcDataSet) override
876  {
877  return atPTData.unionPts(dstVar, srcDataSet);
878  }
879 
880  void clearPts(const Key& k, const Data &element) override
881  {
882  tlPTData.clearPts(k, element);
883  }
884  void clearPts(const VersionedKey& vk, const Data &element) override
885  {
886  atPTData.clearPts(vk, element);
887  }
888 
889  void clearFullPts(const Key& k) override
890  {
891  tlPTData.clearFullPts(k);
892  }
893  void clearFullPts(const VersionedKey& vk) override
894  {
896  }
897 
898  void remapAllPts() override
899  {
900  // tlPTData and atPTData use the same cache.
901  tlPTData.remapAllPts();
902  }
903 
904  Map<DataSet, unsigned> getAllPts(bool liveOnly) const override
905  {
906  // Explicitly pass in true because if we call it with false,
907  // we will double up on the cache, since it is shared with atPTData.
908  // if liveOnly == false, we will handle it in the if below.
909  Map<DataSet, unsigned> allPts = tlPTData.getAllPts(true);
910  SVFUtil::mergePtsOccMaps<DataSet>(allPts, atPTData.getAllPts(true));
911 
912  if (!liveOnly)
913  {
914  // Subtract 1 from each counted points-to set because the live points-to
915  // sets have already been inserted and accounted for how often they occur.
916  // They will each occur one more time in the cache.
917  // In essence, we want the ptCache.getAllPts() to just add the unused, non-GC'd
918  // points-to sets to allPts.
919  for (typename Map<DataSet, unsigned>::value_type &pto : allPts) pto.second -= 1;
920  SVFUtil::mergePtsOccMaps<DataSet>(allPts, tlPTData.ptCache.getAllPts());
921  }
922 
923  return allPts;
924  }
925 
926  inline void dumpPTData() override
927  {
928  SVFUtil::outs() << "== Top-level points-to information\n";
929  tlPTData.dumpPTData();
930  SVFUtil::outs() << "== Address-taken points-to information\n";
932  }
933 
937  {
938  return true;
939  }
940 
941  static inline bool classof(const PTData<Key, KeySet, Data, DataSet>* ptd)
942  {
943  return ptd->getPTDTY() == PTDataTy::PersVersioned;
944  }
946 
947 private:
952 };
953 
954 } // End namespace SVF
955 #endif // PERSISTENT_POINTSTO_H_
bool rev
Whether we maintain reverse points-to sets or not.
PTDataTy
Types of a points-to data structures.
PTDataTy getPTDTY() const
Get the type of points-to data structure that this is.
DFPTData backed by a PersistentPointsToCache.
void clearFullPts(const Key &var) override
Fully clears the points-to set of var.
Map< LocID, KeyToIDMap > DFKeyToIDMap
bool updateATVPts(const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Update address-taken variables OUT[dstLoc:dstVar] with points-to of top-level pointers.
bool hasDFInSet(LocID loc) const override
const KeySet & getRevPts(const Data &) override
Get reverse points-to set of a datum.
bool updateDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
bool updateDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (IN[dstLoc:dstVar], OUT[srcLoc:srcVar]).
const DataSet & getDFOutPtsSet(LocID loc, const Key &var) override
bool updateAllDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (IN[dstLoc::dstVar], IN[srcLoc:srcVar]. There is no flag check, unlike the above.
const DataSet & getPts(const Key &var) override
Get points-to set of var.
bool unionPts(const Key &dstKey, const DataSet &srcDataSet) override
Performs pts(dstVar) = pts(dstVar) U srcDataSet.
bool unionPtsThroughIds(PointsToID &dst, PointsToID &src)
bool unionPts(const Key &dstKey, const Key &srcKey) override
Performs pts(dstVar) = pts(dstVar) U pts(srcVar).
PersistentPTData< Key, KeySet, Data, DataSet > persPTData
PTData for top-level pointers. We will also use its cache for address-taken pointers.
bool hasDFOutSet(LocID loc, const Key &var) const override
PTData< Key, KeySet, Data, DataSet > BasePTData
static bool classof(const PTData< Key, KeySet, Data, DataSet > *ptd)
bool updateAllDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (IN[dstLoc::dstVar], OUT[srcLoc:srcVar]. There is no flag check, unlike the above.
void clearPts(const Key &var, const Data &element) override
Clears element from the points-to set of var.
~PersistentDFPTData() override=default
void clearAllDFOutUpdatedVar(LocID) override
DFKeyToIDMap dfInPtsMap
Address-taken points-to sets in IN-sets.
PersistentDFPTData(PersistentPointsToCache< DataSet > &cache, bool reversePT=true, PTDataTy ty=PTDataTy::PersDataFlow)
bool addPts(const Key &dstKey, const Data &element) override
Adds element to the points-to set associated with var.
const DataSet & getDFInPtsSet(LocID loc, const Key &var) override
bool updateAllDFOutFromIn(LocID loc, const Key &singleton, bool strongUpdates) override
For each variable var in IN at loc, do updateDFOutFromIn(loc, var, loc, var).
PointsToID & getDFOutPtIdRef(LocID loc, const Key &var)
bool updateDFOutFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (OUT[dstLoc:dstVar], IN[srcLoc:srcVar]).
void clear() override
Clears all points-to sets as if nothing is stored.
void dumpPTData() override
Dump stored keys and points-to sets.
BasePTData::PTDataTy PTDataTy
Map< DataSet, unsigned > getAllPts(bool liveOnly) const override
static bool classof(const PersistentDFPTData< Key, KeySet, Data, DataSet > *)
bool hasDFInSet(LocID loc, const Key &var) const override
DFKeyToIDMap dfOutPtsMap
Address-taken points-to sets in OUT-sets.
bool updateTLVPts(LocID srcLoc, const Key &srcVar, const Key &dstVar) override
Update points-to set of top-level pointers with IN[srcLoc:srcVar].
BasePersPTData::KeyToIDMap KeyToIDMap
void remapAllPts() override
Remaps all points-to sets to use the current mapping.
PersistentPointsToCache< DataSet > & ptCache
bool hasDFOutSet(LocID loc) const override
DFPTData< Key, KeySet, Data, DataSet > BaseDFPTData
PointsToID & getDFInPtIdRef(LocID loc, const Key &var)
PersistentPTData< Key, KeySet, Data, DataSet > BasePersPTData
DiffPTData implemented with a persistent points-to backing.
Map< DataSet, unsigned > getAllPts(bool liveOnly) const override
bool computeDiffPts(Key &var, const DataSet &all) override
PersistentPTData< Key, KeySet, Data, DataSet > persPTData
Backing to implement basic PTData methods. Allows us to avoid multiple inheritance.
PersistentDiffPTData(PersistentPointsToCache< DataSet > &cache, bool reversePT=true, PTDataTy ty=PTDataTy::PersDiff)
Constructor.
~PersistentDiffPTData() override=default
const DataSet & getDiffPts(Key &var) override
Get diff points to.
void dumpPTData() override
Dump stored keys and points-to sets.
DiffPTData< Key, KeySet, Data, DataSet > BaseDiffPTData
PersistentPointsToCache< DataSet > & ptCache
void clearPts(const Key &var, const Data &element) override
Clears element from the points-to set of var.
BasePersPTData::KeyToIDMap KeyToIDMap
static bool classof(const PTData< Key, KeySet, Data, DataSet > *ptd)
void clearPropaPts(Key &var) override
Clear propagated points-to set of var.
bool addPts(const Key &dstKey, const Data &element) override
Adds element to the points-to set associated with var.
BasePTData::PTDataTy PTDataTy
const KeySet & getRevPts(const Data &data) override
Get reverse points-to set of a datum.
PTData< Key, KeySet, Data, DataSet > BasePTData
PersistentPTData< Key, KeySet, Data, DataSet > BasePersPTData
void updatePropaPtsMap(Key &src, Key &dst) override
const DataSet & getPts(const Key &var) override
Get points-to set of var.
KeyToIDMap propaPtsMap
Points-to already propagated.
BasePersPTData::RevPtsMap RevPtsMap
void remapAllPts() override
Remaps all points-to sets to use the current mapping.
KeyToIDMap diffPtsMap
Diff points-to to be propagated.
bool unionPts(const Key &dstKey, const Key &srcKey) override
Performs pts(dstVar) = pts(dstVar) U pts(srcVar).
void clear() override
Clears all points-to sets as if nothing is stored.
void clearFullPts(const Key &var) override
Fully clears the points-to set of var.
bool unionPts(const Key &dstKey, const DataSet &srcDataSet) override
Performs pts(dstVar) = pts(dstVar) U srcDataSet.
static bool classof(const PersistentDiffPTData< Key, KeySet, Data, DataSet > *)
Incremental version of the persistent data-flow points-to data structure.
const KeySet & getDFInUpdatedVar(LocID loc)
Get all variables which have new pts information in loc's IN set.
bool updateATVPts(const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Update address-taken variables OUT[dstLoc:dstVar] with points-to of top-level pointers.
void setVarDFInSetUpdated(LocID loc, const Key &var)
Handle address-taken variables whose IN pts changed.
bool updateTLVPts(LocID srcLoc, const Key &srcVar, const Key &dstVar) override
Update points-to set of top-level pointers with IN[srcLoc:srcVar].
bool updateAllDFOutFromIn(LocID loc, const Key &singleton, bool strongUpdates) override
For each variable var in IN at loc, do updateDFOutFromIn(loc, var, loc, var).
static bool classof(const PTData< Key, KeySet, Data, DataSet > *ptd)
PersistentIncDFPTData(PersistentPointsToCache< DataSet > &cache, bool reversePT=true, PTDataTy ty=BasePTData::PersIncDataFlow)
Constructor.
bool updateAllDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (IN[dstLoc::dstVar], OUT[srcLoc:srcVar]. There is no flag check, unlike the above.
bool varHasNewDFInPts(LocID loc, const Key &var)
Return TRUE if var has a new pts in loc's IN set.
bool updateDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
static bool classof(const PersistentIncDFPTData< Key, KeySet, Data, DataSet > *)
PTData< Key, KeySet, Data, DataSet > BasePTData
bool updateAllDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (IN[dstLoc::dstVar], IN[srcLoc:srcVar]. There is no flag check, unlike the above.
const KeySet & getDFOutUpdatedVar(LocID loc)
Get all variables which have new pts info in loc's OUT set.
void setVarDFOutSetUpdated(LocID loc, const Key &var)
bool updateDFOutFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (OUT[dstLoc:dstVar], IN[srcLoc:srcVar]).
void clearAllDFOutUpdatedVar(LocID loc) override
Map< LocID, KeySet > UpdatedVarMap
PersistentDFPTData< Key, KeySet, Data, DataSet > BasePersDFPTData
PersistentPTData< Key, KeySet, Data, DataSet > BasePersPTData
void removeVarFromDFOutUpdatedSet(LocID loc, const Key &var)
Remove var from loc's OUT updated set.
void removeVarFromDFInUpdatedSet(LocID loc, const Key &var)
Remove var from loc's IN updated set.
void clear() override
Clears all points-to sets as if nothing is stored.
~PersistentIncDFPTData() override=default
bool varHasNewDFOutPts(LocID loc, const Key &var)
Return TRUE if var has a new pts in loc's OUT set.
DFPTData< Key, KeySet, Data, DataSet > BaseDFPTData
bool updateDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar) override
Union (IN[dstLoc:dstVar], OUT[srcLoc:srcVar]).
PTData backed by a PersistentPointsToCache.
bool unionPtsFromId(const Key &dstKey, PointsToID srcId)
PersistentPointsToCache< DataSet > & ptCache
static bool classof(const PersistentPTData< Key, KeySet, Data, DataSet > *)
void clearRevPts(const DataSet &pts, const Key &k)
const KeySet & getRevPts(const Data &data) override
Get reverse points-to set of a datum.
Map< DataSet, unsigned > getAllPts(bool liveOnly) const override
void clearSingleRevPts(KeySet &revSet, const Key &k)
bool addPts(const Key &dstKey, const Data &element) override
Adds element to the points-to set associated with var.
void clear() override
Clears all points-to sets as if nothing is stored.
static bool classof(const PTData< Key, KeySet, Data, DataSet > *ptd)
bool unionPts(const Key &dstKey, const Key &srcKey) override
Performs pts(dstVar) = pts(dstVar) U pts(srcVar).
PersistentPTData(PersistentPointsToCache< DataSet > &cache, bool reversePT=true, PTDataTy ty=PTDataTy::PersBase)
Constructor.
~PersistentPTData() override=default
BasePTData::PTDataTy PTDataTy
void remapAllPts() override
Remaps all points-to sets to use the current mapping.
PTData< Key, KeySet, Data, DataSet > BasePTData
void clearPts(const Key &var, const Data &element) override
Clears element from the points-to set of var.
void dumpPTData() override
Dump stored keys and points-to sets.
bool unionPts(const Key &dstKey, const DataSet &srcData) override
Performs pts(dstVar) = pts(dstVar) U srcDataSet.
const DataSet & getPts(const Key &var) override
Get points-to set of var.
Map< Key, PointsToID > KeyToIDMap
Map< Data, KeySet > RevPtsMap
void clearFullPts(const Key &var) override
Fully clears the points-to set of var.
PointsToID unionPts(PointsToID lhs, PointsToID rhs)
Unions lhs and rhs and returns their union's ID.
PointsToID intersectPts(PointsToID lhs, PointsToID rhs)
Intersects lhs and rhs (lhs AND rhs) and returns the intersection's ID.
PointsToID complementPts(PointsToID lhs, PointsToID rhs)
Relatively complements lhs and rhs (lhs \ rhs) and returns it's ID.
void remapAllPts(void)
Remaps all points-to sets stored in the cache to the current mapping.
static PointsToID emptyPointsToId(void)
PointsToID emplacePts(const Data &pts)
const Data & getActualPts(PointsToID id) const
Returns the points-to set which id represents. id must be stored in the cache.
Map< Data, unsigned > getAllPts(void)
void clearFullPts(const Key &k) override
Fully clears the points-to set of var.
bool unionPts(const Key &dstVar, const Key &srcVar) override
Performs pts(dstVar) = pts(dstVar) U pts(srcVar).
PersistentPTData< Key, KeySet, Data, DataSet >::KeyToIDMap KeyToIDMap
static bool classof(const PTData< Key, KeySet, Data, DataSet > *ptd)
static bool classof(const PersistentVersionedPTData< Key, KeySet, Data, DataSet, VersionedKey, VersionedKeySet > *)
PersistentPTData< Key, KeySet, Data, DataSet > tlPTData
PTData for Keys (top-level pointers, generally).
PersistentPTData< VersionedKey, VersionedKeySet, Data, DataSet >::KeyToIDMap VersionedKeyToIDMap
bool addPts(const VersionedKey &vk, const Data &element) override
const KeySet & getRevPts(const Data &data) override
Get reverse points-to set of a datum.
void clearPts(const Key &k, const Data &element) override
Clears element from the points-to set of var.
void remapAllPts() override
Remaps all points-to sets to use the current mapping.
PersistentVersionedPTData(PersistentPointsToCache< DataSet > &cache, bool reversePT=true, PTDataTy ty=PTDataTy::PersVersioned)
bool unionPts(const VersionedKey &dstVar, const Key &srcVar) override
PersistentPTData< VersionedKey, VersionedKeySet, Data, DataSet > atPTData
PTData for VersionedKeys (address-taken objects, generally).
void clearPts(const VersionedKey &vk, const Data &element) override
~PersistentVersionedPTData() override=default
void clearFullPts(const VersionedKey &vk) override
bool unionPts(const Key &dstVar, const DataSet &srcDataSet) override
Performs pts(dstVar) = pts(dstVar) U srcDataSet.
void dumpPTData() override
Dump stored keys and points-to sets.
bool unionPts(const VersionedKey &dstVar, const DataSet &srcDataSet) override
VersionedPTData< Key, KeySet, Data, DataSet, VersionedKey, VersionedKeySet > BaseVersionedPTData
const DataSet & getPts(const Key &vk) override
Get points-to set of var.
bool addPts(const Key &k, const Data &element) override
Adds element to the points-to set associated with var.
const VersionedKeySet & getVersionedKeyRevPts(const Data &data) override
Map< DataSet, unsigned > getAllPts(bool liveOnly) const override
PTData< Key, KeySet, Data, DataSet > BasePTData
bool unionPts(const Key &dstVar, const VersionedKey &srcVar) override
bool unionPts(const VersionedKey &dstVar, const VersionedKey &srcVar) override
const DataSet & getPts(const VersionedKey &vk) override
void clear() override
Clears all points-to sets as if nothing is stored.
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
void removeKey(const Key &key, KeySet &keySet)
Removes an element from a Set/CondSet (or anything implementing ::erase).
Definition: SVFUtil.h:252
void insertKey(const Key &key, KeySet &keySet)
Inserts an element into a Set/CondSet (with ::insert).
Definition: SVFUtil.h:239
for isBitcode
Definition: BasicTypes.h:68
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
unsigned PointsToID
Definition: GeneralType.h:63