SVF
FlowSensitiveTBHC.cpp
Go to the documentation of this file.
1 //===- FlowSensitiveTBHC.cpp -- flow-sensitive type filter ------------//
2 
3 /*
4  * FlowSensitiveTBHC.cpp
5  *
6  * Created on: Oct 08, 2019
7  * Author: Mohamad Barbar
8  */
9 
10 #include "Util/Options.h"
11 #include "SVF-FE/DCHG.h"
12 #include "SVF-FE/CPPUtil.h"
13 #include "WPA/FlowSensitiveTBHC.h"
14 #include "WPA/WPAStat.h"
15 #include "WPA/Andersen.h"
16 
17 using namespace SVF;
18 
20 {
21  // Using `this` as the argument for TypeBasedHeapCloning is okay. As PointerAnalysis, it's
22  // already constructed. TypeBasedHeapCloning also doesn't use pta in the constructor so it
23  // just needs to be allocated, which it is.
26 }
27 
29 {
31 }
32 
34 {
37  svfg = memSSA.buildFullSVFG(ander);
38  setGraph(svfg);
39  stat = new FlowSensitiveStat(this);
40 
42  assert(dchg != nullptr && "FSTBHC: DCHGraph required!");
43 
46 
47  // Populates loadGeps.
49 }
50 
52 {
54  // ^ Will print call graph and alias stats.
55 
56  if(print_stat)
57  dumpStats();
58  // getDFPTDataTy()->dumpPTData();
59 
61 }
62 
64 {
65  PAGNode *cloneObj = pag->getPAGNode(clone);
66  assert(cloneObj && "FSTBHC: clone does not exist in PAG?");
67  PAGNode *originalObj = pag->getPAGNode(getOriginalObj(clone));
68  assert(cloneObj && "FSTBHC: original object does not exist in PAG?");
69  // Check the original object too because when reuse of a gep occurs, the new object
70  // is an FI object.
71  if (SVFUtil::isa<CloneGepObjPN>(cloneObj) || SVFUtil::isa<GepObjPN>(originalObj))
72  {
73  // Since getGepObjClones is updated, some GEP nodes need to be redone.
74  const NodeBS &retrievers = gepToSVFGRetrievers[getOriginalObj(clone)];
75  for (NodeID r : retrievers)
76  {
78  }
79  }
80  else if (SVFUtil::isa<CloneFIObjPN>(cloneObj) || SVFUtil::isa<CloneDummyObjPN>(cloneObj))
81  {
83  }
84  else
85  {
86  assert(false && "FSTBHC: unexpected object type?");
87  }
88 }
89 
91 {
92  SVFGNode* src = edge->getSrcNode();
93  SVFGNode* dst = edge->getDstNode();
94 
95  bool changed = false;
96 
97  // Get points-to targets may be used by next SVFG node.
98  // Propagate points-to set for node used in dst.
99  const PointsTo& pts = edge->getPointsTo();
100 
101  // Since the base Andersen's analysis does NOT perform type-based heap cloning,
102  // it uses only the base objects; we want to account for clones too.
103  PointsTo edgePtsAndClones;
104 
105  // TODO: the conditional bool may be unnecessary.
106  // Adding all clones is redundant, and introduces too many calls to propVarPts...
107  // This introduces performance and precision penalties.
108  // We should filter out according to src.
109  bool isStore = false;
110  const DIType *tildet = nullptr;
111  PointsTo storePts;
112  if (const StoreSVFGNode *store = SVFUtil::dyn_cast<StoreSVFGNode>(src))
113  {
114  tildet = getTypeFromCTirMetadata(store);
115  isStore = true;
116  storePts = getPts(store->getPAGDstNodeID());
117  }
118 
119  const PointsTo &filterSet = getFilterSet(src->getId());
120  for (NodeID o : pts)
121  {
122  if (!filterSet.test(o))
123  {
124  edgePtsAndClones.set(o);
125  }
126 
127  for (NodeID c : getClones(o))
128  {
129  if (!isStore)
130  {
131  if (!filterSet.test(c))
132  {
133  edgePtsAndClones.set(c);
134  }
135  }
136  else
137  {
138  if (storePts.test(c) && !filterSet.test(c))
139  {
140  edgePtsAndClones.set(c);
141  }
142  }
143  }
144 
145  if (GepObjPN *gep = SVFUtil::dyn_cast<GepObjPN>(pag->getPAGNode(o)))
146  {
147  // Want the geps which are at the same "level" as this one (same mem obj, same offset).
148  const NodeBS &geps = getGepObjsFromMemObj(gep->getMemObj(), gep->getLocationSet().getOffset());
149  for (NodeID g : geps)
150  {
151  const DIType *gepType = getType(g);
152  if (!isStore || gepType || isBase(tildet, gepType))
153  {
154  if (!filterSet.test(g))
155  {
156  edgePtsAndClones.set(g);
157  }
158  }
159  }
160  }
161  }
162 
163  for (NodeID o : edgePtsAndClones)
164  {
165  if (propVarPtsFromSrcToDst(o, src, dst))
166  changed = true;
167 
168  if (isFIObjNode(o))
169  {
171  const NodeBS &allFields = getAllFieldsObjNode(o);
172  for (NodeID f : allFields)
173  {
174  if (propVarPtsFromSrcToDst(f, src, dst))
175  changed = true;
176  }
177  }
178  }
179 
180  return changed;
181 }
182 
184 {
185  double start = stat->getClk();
186  bool changed = false;
187 
188  SVFGNode* src = edge->getSrcNode();
189  SVFGNode* dst = edge->getDstNode();
190  // If this is an actual-param or formal-ret, top-level pointer's pts must be
191  // propagated from src to dst.
192  if (ActualParmSVFGNode* ap = SVFUtil::dyn_cast<ActualParmSVFGNode>(src))
193  {
194  if (!ap->getParam()->isPointer()) return false;
195  changed = propagateFromAPToFP(ap, dst);
196  }
197  else if (FormalRetSVFGNode* fp = SVFUtil::dyn_cast<FormalRetSVFGNode>(src))
198  {
199  if (!fp->getRet()->isPointer()) return false;
200  changed = propagateFromFRToAR(fp, dst);
201  }
202  else
203  {
204  // Direct SVFG edge links between def and use of a top-level pointer.
205  // There's no points-to information propagated along direct edge.
206  // Since the top-level pointer's value has been changed at src node,
207  // return TRUE to put dst node into the work list.
208  changed = true;
209  }
210 
211  double end = stat->getClk();
212  directPropaTime += (end - start) / TIMEINTERVAL;
213  return changed;
214 }
215 
217 {
218  double start = stat->getClk();
219 
220  NodeID srcID = addr->getPAGSrcNodeID();
221  NodeID dstID = addr->getPAGDstNodeID();
222 
223  double end = stat->getClk();
224  addrTime += (end - start) / TIMEINTERVAL;
225 
226  if (!addr->getPAGEdge()->isPTAEdge()) return false;
227 
228  bool changed = FlowSensitive::processAddr(addr);
229 
230  start = stat->getClk();
231 
232  const DIType *objType;
233  if (isHeapMemObj(srcID))
234  {
235  objType = undefType;
236  }
237  else if (pag->isConstantObj(srcID))
238  {
239  // Probably constants that have been merged into one.
240  // We make it undefined even though it's technically a global
241  // to keep in line with SVF's design.
242  // This will end up splitting into one for each type of constant.
243  objType = undefType;
244  }
245  else
246  {
247  // Stack/global.
248  objType = getTypeFromCTirMetadata(addr);
249  }
250 
251  setType(srcID, objType);
252  setAllocationSite(srcID, addr->getId());
253 
254  // All the typed versions of srcID. This handles back-propagation.
255  const NodeBS &clones = getClones(srcID);
256  for (NodeID c : clones)
257  {
258  changed = addPts(dstID, c) || changed;
259  // No need for typing these are all clones; they are all typed.
260  }
261 
262  end = stat->getClk();
263  addrTime += (end - start) / TIMEINTERVAL;
264 
265  return changed;
266 }
267 
269 {
270  // Copy of that in FlowSensitive.cpp + some changes.
271  double start = stat->getClk();
272  bool changed = false;
273 
274  NodeID q = gep->getPAGSrcNodeID();
275 
276  const DIType *tildet = getTypeFromCTirMetadata(gep);
277  if (tildet != undefType)
278  {
279  bool reuse = Options::TBHCAllReuse || (Options::TBHCStoreReuse && !gepIsLoad(gep->getId()));
280  changed = init(gep->getId(), q, tildet, reuse, true);
281  }
282 
283  if (!gep->getPAGEdge()->isPTAEdge())
284  {
285  return changed;
286  }
287 
288  const PointsTo& qPts = getPts(q);
289  PointsTo &filterSet = getFilterSet(gep->getId());
290  PointsTo tmpDstPts;
291  for (NodeID oq : qPts)
292  {
293  if (filterSet.test(oq)) continue;
294 
296  {
297  tmpDstPts.set(oq);
298  }
299  else
300  {
301  if (SVFUtil::isa<VariantGepPE>(gep->getPAGEdge()))
302  {
304  tmpDstPts.set(oq);
305  const DIType *t = getType(oq);
306  if (t && (t->getTag() == dwarf::DW_TAG_array_type || t->getTag() == dwarf::DW_TAG_pointer_type))
307  {
308  const NodeBS fieldClones = getGepObjClones(oq, 1);
309  for (NodeID fc : fieldClones)
310  {
311  gepToSVFGRetrievers[getOriginalObj(fc)].set(gep->getId());
312  tmpDstPts.set(fc);
313  }
314  }
315  }
316  else if (const NormalGepPE* normalGep = SVFUtil::dyn_cast<NormalGepPE>(gep->getPAGEdge()))
317  {
318  const DIType *baseType = getType(oq);
319 
320  // Drop down to field insensitive.
321  if (baseType == nullptr)
322  {
324  NodeID fiObj = oq;
325  tmpDstPts.set(fiObj);
326  continue;
327  }
328 
329  if (DCHGraph::isAgg(baseType) && baseType->getTag() != dwarf::DW_TAG_array_type
330  && normalGep->getLocationSet().getOffset() >= dchg->getNumFields(baseType))
331  {
332  // If the field offset is too high for this object, it is killed. It seems that a
333  // clone was made on this GEP but this is not the base (e.g. base->f1->f2), and SVF
334  // expects to operate on the base (hence the large offset). The base will have been
335  // cloned at another GEP and back-propagated, thus it'll reach here safe and sound.
336  // We ignore arrays/pointers because those are array accesses/pointer arithmetic we
337  // assume are correct.
338  // Obviously, non-aggregates cannot have their fields taken so they are spurious.
339  filterSet.set(oq);
340  }
341  else
342  {
343  // Operate on the field and all its clones.
344  const NodeBS fieldClones = getGepObjClones(oq, normalGep->getLocationSet().getOffset());
345  for (NodeID fc : fieldClones)
346  {
347  gepToSVFGRetrievers[getOriginalObj(fc)].set(gep->getId());
348  tmpDstPts.set(fc);
349  }
350  }
351  }
352  else
353  {
354  assert(false && "FSTBHC: new gep edge?");
355  }
356  }
357  }
358 
359  double end = stat->getClk();
360  gepTime += (end - start) / TIMEINTERVAL;
361 
362  changed = unionPts(gep->getPAGDstNodeID(), tmpDstPts) || changed;
363  return changed;
364 }
365 
367 {
368  double start = stat->getClk();
369 
370  bool changed = false;
371  const DIType *tildet = getTypeFromCTirMetadata(load);
372  if (tildet != undefType)
373  {
374  changed = init(load->getId(), load->getPAGSrcNodeID(), tildet, Options::TBHCAllReuse);
375  }
376 
377  // We want to perform the initialisation for non-pointer nodes but not process the load.
378  if (!load->getPAGEdge()->isPTAEdge())
379  {
380  return changed;
381  }
382 
383  NodeID dstVar = load->getPAGDstNodeID();
384 
385  const PointsTo& srcPts = getPts(load->getPAGSrcNodeID());
386  const PointsTo &filterSet = getFilterSet(load->getId());
387  // unionPtsFromIn is going to call getOriginalObj on ptd anyway.
388  // This results in fewer loop iterations. o_t, o_s --> o.
389  PointsTo srcOriginalObjs;
390  for (NodeID s : srcPts)
391  {
392  if (filterSet.test(s)) continue;
393  if (pag->isConstantObj(s) || pag->isNonPointerObj(s)) continue;
394  srcOriginalObjs.set(getOriginalObj(s));
395  }
396 
397  for (NodeID ptd : srcOriginalObjs)
398  {
399  // filterSet tests happened while building srcOriginalObjs.
400  if (unionPtsFromIn(load, ptd, dstVar))
401  changed = true;
402 
403  if (isFIObjNode(ptd))
404  {
407  const NodeBS &allFields = getAllFieldsObjNode(ptd);
408  for (NodeID f : allFields)
409  {
410  if (unionPtsFromIn(load, f, dstVar))
411  changed = true;
412  }
413  }
414  }
415 
416  double end = stat->getClk();
417  loadTime += (end - start) / TIMEINTERVAL;
418  return changed;
419 }
420 
422 {
423  double start = stat->getClk();
424 
425  bool changed = false;
426  const DIType *tildet = getTypeFromCTirMetadata(store);
427  if (tildet != undefType)
428  {
429  changed = init(store->getId(), store->getPAGDstNodeID(), tildet, Options::TBHCAllReuse || Options::TBHCStoreReuse);
430  }
431 
432  // Like processLoad: we want to perform initialisation for non-pointers but not the store.
433  if (!store->getPAGEdge()->isPTAEdge())
434  {
435  // Pass through and return because there may be some pointer nodes
436  // relying on this node's parents.
437  changed = getDFPTDataTy()->updateAllDFOutFromIn(store->getId(), 0, false);
438  return changed;
439  }
440 
441  const PointsTo & dstPts = getPts(store->getPAGDstNodeID());
442 
449  if (dstPts.empty())
450  {
451  return changed;
452  }
453 
454  changed = false;
455  const PointsTo &filterSet = getFilterSet(store->getId());
456  if(getPts(store->getPAGSrcNodeID()).empty() == false)
457  {
458  for (NodeID ptd : dstPts)
459  {
460  if (filterSet.test(ptd)) continue;
461 
462  if (pag->isConstantObj(ptd) || pag->isNonPointerObj(ptd))
463  continue;
464 
465  if (unionPtsFromTop(store, store->getPAGSrcNodeID(), ptd))
466  changed = true;
467  }
468  }
469 
470  double end = stat->getClk();
471  storeTime += (end - start) / TIMEINTERVAL;
472 
473  double updateStart = stat->getClk();
474  // also merge the DFInSet to DFOutSet.
476  NodeID singleton;
477  bool isSU = isStrongUpdate(store, singleton);
478  if (isSU)
479  {
480  svfgHasSU.set(store->getId());
481  if (strongUpdateOutFromIn(store, singleton))
482  changed = true;
483  }
484  else
485  {
486  svfgHasSU.reset(store->getId());
487  if (weakUpdateOutFromIn(store))
488  changed = true;
489  }
490  double updateEnd = stat->getClk();
491  updateTime += (updateEnd - updateStart) / TIMEINTERVAL;
492 
493  return changed;
494 }
495 
497 {
498  if (!phi->isPTANode()) return false;
499  return FlowSensitive::processPhi(phi);
500 }
501 
505 static const DIType *getVTInitType(const CopySVFGNode *copy, DCHGraph *dchg)
506 {
507  if (copy->getInst() == nullptr) return nullptr;
508  const Instruction *inst = copy->getInst();
509 
510  const MDNode *mdNode = inst->getMetadata(cppUtil::ctir::vtInitMDName);
511  if (mdNode == nullptr) return nullptr;
512 
513  const DIType *type = SVFUtil::dyn_cast<DIType>(mdNode);
514  assert(type != nullptr && "TBHC: bad ctir.vt.init metadata");
515  return dchg->getCanonicalType(type);
516 }
517 
519 {
520  const DIType *vtInitType = getVTInitType(copy, dchg);
521  bool changed = false;
522  if (vtInitType != nullptr)
523  {
524  // Setting the virtual table pointer.
525  changed = init(copy->getId(), copy->getPAGSrcNodeID(), vtInitType, true);
526  }
527 
528  return FlowSensitive::processCopy(copy) || changed;
529 }
530 
532 {
533  return getGepObjs(id);
534 }
535 
536 bool FlowSensitiveTBHC::updateInFromIn(const SVFGNode* srcStmt, NodeID srcVar, const SVFGNode* dstStmt, NodeID dstVar)
537 {
538  // IN sets are only based on the original object.
539  return getDFPTDataTy()->updateDFInFromIn(srcStmt->getId(), getOriginalObj(srcVar),
540  dstStmt->getId(), getOriginalObj(dstVar));
541 }
542 
543 bool FlowSensitiveTBHC::updateInFromOut(const SVFGNode* srcStmt, NodeID srcVar, const SVFGNode* dstStmt, NodeID dstVar)
544 {
545  // OUT/IN sets only have original objects.
546  return getDFPTDataTy()->updateDFInFromOut(srcStmt->getId(), getOriginalObj(srcVar),
547  dstStmt->getId(), getOriginalObj(dstVar));
548 }
549 
550 bool FlowSensitiveTBHC::unionPtsFromIn(const SVFGNode* stmt, NodeID srcVar, NodeID dstVar)
551 {
552  // IN sets only have original objects.
553  return getDFPTDataTy()->updateTLVPts(stmt->getId(), getOriginalObj(srcVar), dstVar);
554 }
555 
556 bool FlowSensitiveTBHC::unionPtsFromTop(const SVFGNode* stmt, NodeID srcVar, NodeID dstVar)
557 {
558  // OUT sets only have original objects.
559  return getDFPTDataTy()->updateATVPts(srcVar, stmt->getId(), getOriginalObj(dstVar));
560 }
561 
562 bool FlowSensitiveTBHC::propDFInToIn(const SVFGNode* srcStmt, NodeID srcVar, const SVFGNode* dstStmt, NodeID dstVar)
563 {
564  // IN sets are only based on the original object.
565  return getDFPTDataTy()->updateAllDFInFromIn(srcStmt->getId(), getOriginalObj(srcVar),
566  dstStmt->getId(), getOriginalObj(dstVar));
567 }
568 
569 bool FlowSensitiveTBHC::propDFOutToIn(const SVFGNode* srcStmt, NodeID srcVar, const SVFGNode* dstStmt, NodeID dstVar)
570 {
571  // OUT/IN sets only have original objects.
572  return getDFPTDataTy()->updateAllDFInFromOut(srcStmt->getId(), getOriginalObj(srcVar),
573  dstStmt->getId(), getOriginalObj(dstVar));
574 }
575 
577 {
578  for (SVFG::iterator nI = svfg->begin(); nI != svfg->end(); ++nI)
579  {
580  SVFGNode *svfgNode = nI->second;
581  if (const StmtSVFGNode *gep = SVFUtil::dyn_cast<GepSVFGNode>(svfgNode))
582  {
583  // Only care about ctir nodes - they have the reuse problem.
584  if (getTypeFromCTirMetadata(gep))
585  {
586  bool isLoad = true;
587  for (const SVFGEdge *e : gep->getOutEdges())
588  {
589  SVFGNode *dst = e->getDstNode();
590 
591  // Loop on itself - don't care.
592  if (gep == dst) continue;
593 
594  if (!SVFUtil::isa<LoadSVFGNode>(dst))
595  {
596  isLoad = false;
597  break;
598  }
599  }
600 
601  if (isLoad)
602  {
603  loadGeps.set(gep->getId());
604  }
605  }
606  }
607  }
608 }
609 
611 {
612  // Handles when gep is not even a GEP; loadGeps only contains GEPs.
613  return loadGeps.test(gep);
614 }
615 
617 {
618  if (const StmtSVFGNode *stmt = SVFUtil::dyn_cast<StmtSVFGNode>(s))
619  {
620  const Value *v = stmt->getInst() ? stmt->getInst() : stmt->getPAGEdge()->getValue();
621  if (v != nullptr)
622  {
624  }
625  }
626 
627  return nullptr;
628 }
629 
631 {
632  if (const StmtSVFGNode *stmt = SVFUtil::dyn_cast<StmtSVFGNode>(s))
633  {
634  const Value *v = stmt->getInst();
635  if (v != nullptr)
636  {
638  }
639  }
640 
641  return nullptr;
642 }
643 
644 void FlowSensitiveTBHC::expandFIObjs(const PointsTo& pts, PointsTo& expandedPts)
645 {
646  expandedPts = pts;
647  for (NodeID o : pts)
648  {
649  expandedPts |= getAllFieldsObjNode(o);
650  while (const GepObjPN *gepObj = SVFUtil::dyn_cast<GepObjPN>(pag->getPAGNode(o)))
651  {
652  expandedPts |= getAllFieldsObjNode(o);
653  o = gepObj->getBaseNode();
654  }
655  }
656 }
657 
658 void FlowSensitiveTBHC::countAliases(Set<std::pair<NodeID, NodeID>> cmp, unsigned *mayAliases, unsigned *noAliases)
659 {
661  for (std::pair<NodeID, NodeID> locP : cmp)
662  {
663  const PointsTo &filterSet = getFilterSet(locP.first);
664  const PointsTo &pts = getPts(locP.second);
665  PointsTo &ptsFiltered = filteredPts[locP];
666 
667  for (NodeID o : pts)
668  {
669  if (filterSet.test(o)) continue;
670  ptsFiltered.set(o);
671  }
672  }
673 
674  for (std::pair<NodeID, NodeID> locPA : cmp)
675  {
676  const PointsTo &aPts = filteredPts[locPA];
677  for (std::pair<NodeID, NodeID> locPB : cmp)
678  {
679  if (locPB == locPA) continue;
680  const PointsTo &bPts = filteredPts[locPB];
681 
682  switch (alias(aPts, bPts))
683  {
684  case llvm::NoAlias:
685  ++(*noAliases);
686  break;
687  case llvm::MayAlias:
688  ++(*mayAliases);
689  break;
690  default:
691  assert("Not May/NoAlias?");
692  }
693  }
694  }
695 
696 }
virtual void finalize() override
Finalize analysis.
unsigned getNumFields(const DIType *base)
Definition: DCHG.h:335
iterator begin()
Iterators.
Definition: GenericGraph.h:365
virtual bool propagateFromAPToFP(const ActualParmSVFGNode *ap, const SVFGNode *dst)
const std::string vtInitMDName
Definition: CPPUtil.h:119
virtual void pushIntoWorklist(NodeID id)
Definition: WPASolver.h:163
NodeID getPAGDstNodeID() const
Definition: VFGNode.h:139
double loadTime
time of load edges
virtual bool processPhi(const PHISVFGNode *phi) override
const Instruction * getInst() const
Definition: VFGNode.h:178
u32_t NodeID
Definition: SVFBasicTypes.h:80
double addrTime
time of handling address edges
virtual bool processCopy(const CopySVFGNode *copy)
SVFG * buildFullSVFG(BVDataPTAImpl *pta)
Definition: SVFGBuilder.cpp:54
const NodeBS & getGepObjs(NodeID base)
virtual const NodeBS & getAllFieldsObjNode(NodeID id) override
#define assert(ex)
Definition: util.h:141
bool isNonPointerObj(NodeID id) const
Definition: PAG.h:627
bool isStrongUpdate(const SVFGNode *node, NodeID &singleton)
Return TRUE if this is a strong update STORE statement.
bool storeReuse
Whether to allow for reuse at stores.
void setType(NodeID o, const DIType *t)
Sets the type (in objToType) of o.
virtual bool processCopy(const CopySVFGNode *copy) override
bool isBlkObjOrConstantObj(NodeID o) const
virtual void analyze()
Flow sensitive analysis.
virtual void initialize() override
Initialize analysis.
Definition: PAG.h:47
Dwarf based CHG.
Definition: DCHG.h:208
virtual void finalize()
Finalize analysis.
SVFModule * svfMod
Module.
virtual bool unionPts(NodeID id, const PointsTo &target)
virtual bool updateDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar)=0
const PAGEdge * getPAGEdge() const
Definition: VFGNode.h:129
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: SVFBasicTypes.h:98
bool isPTAEdge() const
Whether src and dst nodes are both of pointer type.
Definition: PAG.cpp:1010
virtual bool propAlongDirectEdge(const DirectSVFGEdge *edge) override
Propagate points-to information along a DIRECT SVFG edge.
virtual void expandFIObjs(const PointsTo &pts, PointsTo &expandedPts) override
Expand FI objects.
friend class FlowSensitiveStat
Definition: FlowSensitive.h:49
static const DIType * undefType
The undefined type (•); void.
virtual void backPropagate(NodeID clone) override
virtual bool weakUpdateOutFromIn(const SVFGNode *node)
Handle weak updates.
NodeBS loadGeps
Maps whether a (SVFG) GEP node is a load or not.
bool isConstantObj(NodeID id) const
Definition: PAG.h:621
virtual bool processLoad(const LoadSVFGNode *load) override
virtual bool processStore(const StoreSVFGNode *store) override
static const llvm::cl::opt< bool > TBHCStoreReuse
Whether we allow reuse for TBHC.
Definition: Options.h:193
static bool isAgg(const DIType *t)
Definition: DCHG.cpp:342
virtual bool updateAllDFOutFromIn(LocID loc, const Key &singleton, bool strongUpdates)=0
For each variable var in IN at loc, do updateDFOutFromIn(loc, var, loc, var).
PAGNode * getPAGNode(NodeID id) const
Get PAGNode ID.
Definition: PAG.h:513
IDToNodeMapTy::iterator iterator
Node Iterators.
Definition: GenericGraph.h:337
static const llvm::cl::opt< bool > TBHCAllReuse
Definition: Options.h:194
virtual bool propAlongIndirectEdge(const IndirectSVFGEdge *edge) override
Propagate points-to information along an INDIRECT SVFG edge.
void setPAG(PAG *pag)
PAG must be set by extending class once the PAG is available.
NodeType * getDstNode() const
Definition: GenericGraph.h:89
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: SVFBasicTypes.h:93
virtual bool addPts(NodeID id, NodeID ptd)
virtual void countAliases(Set< std::pair< NodeID, NodeID >> cmp, unsigned *mayAliases, unsigned *noAliases) override
Fills may/noAliases for the location/pointer pairs in cmp.
virtual bool processGep(const GepSVFGNode *gep) override
void setGraph(GraphType g)
Definition: WPASolver.h:82
virtual bool updateTLVPts(LocID srcLoc, const Key &srcVar, const Key &dstVar)=0
Update points-to set of top-level pointers with IN[srcLoc:srcVar].
virtual bool processAddr(const AddrSVFGNode *addr)
virtual const PointsTo & getPts(NodeID id)
virtual void analyze() override
Flow sensitive analysis with FSTBHC.
llvm::Instruction Instruction
Definition: BasicTypes.h:79
const DIType * getTypeFromCTirMetadata(const SVFGNode *)
void setObjFieldInsensitive(NodeID id)
void setDCHG(DCHGraph *dchg)
DCHG must be set by extending class once the DCHG is available.
virtual bool unionPtsFromIn(const SVFGNode *stmt, NodeID srcVar, NodeID dstVar) override
void dumpStats(void)
Dump some statistics we tracked.
void validateTBHCTests(SVFModule *svfMod)
NodeID getPAGSrcNodeID() const
Definition: VFGNode.h:134
virtual bool processAddr(const AddrSVFGNode *addr) override
CommonCHGraph * getCHGraph() const
get CHGraph
static AndersenWaveDiff * createAndersenWaveDiff(PAG *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition: Andersen.h:429
const NodeBS & getGepObjsFromMemObj(const MemObj *memObj, unsigned offset)
const PointsTo & getPointsTo() const
Definition: SVFGEdge.h:61
PTAStat * stat
Statistics.
NodeID getAllocationSite(NodeID o) const
Returns the allocation site (from objToAllocation) of o. Asserts existence.
virtual bool propDFOutToIn(const SVFGNode *srcStmt, NodeID srcVar, const SVFGNode *dstStmt, NodeID dstVar) override
NodeType * getSrcNode() const
Definition: GenericGraph.h:85
static const MDNode * getRawCTirMetadata(const Value *)
Returns raw ctir metadata of a Value. Returns null if it doesn&#39;t exist.
#define TIMEINTERVAL
virtual bool updateATVPts(const Key &srcVar, LocID dstLoc, const Key &dstVar)=0
Update address-taken variables OUT[dstLoc:dstVar] with points-to of top-level pointers.
bool isBase(const DIType *a, const DIType *b) const
virtual bool updateDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar)=0
Union (IN[dstLoc:dstVar], OUT[srcLoc:srcVar]).
double directPropaTime
time of points-to propagation of address-taken objects
const DIType * getType(NodeID o) const
Returns the type (from objToType) of o. Asserts existence.
bool isHeapMemObj(NodeID id) const
Whether this object is heap or array.
void setAllocationSite(NodeID o, NodeID site)
Sets the allocation site (in objToAllocation) of o.
virtual bool processPhi(const PHISVFGNode *phi)
virtual bool unionPtsFromTop(const SVFGNode *stmt, NodeID srcVar, NodeID dstVar) override
const DIType * getCanonicalType(const DIType *t)
Definition: DCHG.cpp:713
llvm::MDNode MDNode
Definition: BasicTypes.h:138
virtual bool propDFInToIn(const SVFGNode *srcStmt, NodeID srcVar, const SVFGNode *dstStmt, NodeID dstVar) override
for isBitcode
Definition: ContextDDA.h:15
bool isPTANode() const
Whether this phi node is of pointer type (used for pointer analysis).
Definition: VFGNode.h:578
static const MDNode * getRawCTirMetadata(const SVFGNode *)
static double getClk(bool mark=false)
Definition: PTAStat.h:139
bool isFIObjNode(NodeID id) const
NodeID getId() const
Get ID.
Definition: GenericGraph.h:164
llvm::SparseBitVector NodeBS
Definition: SVFBasicTypes.h:87
FlowSensitiveTBHC(PAG *_pag, PTATY type=FSTBHC_WPA)
Constructor.
const NodeBS & getClones(NodeID o)
Returns all the clones of o.
Map< NodeID, NodeBS > gepToSVFGRetrievers
Maps GEP objects to the SVFG nodes that retrieved them with getGepObjClones.
PointsTo & getFilterSet(NodeID loc)
Returns the filter set of a location. Not const; could create empty PointsTo.
virtual bool updateInFromOut(const SVFGNode *srcStmt, NodeID srcVar, const SVFGNode *dstStmt, NodeID dstVar) override
virtual bool updateAllDFInFromIn(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar)=0
Union (IN[dstLoc::dstVar], IN[srcLoc:srcVar]. There is no flag check, unlike the above.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:343
virtual bool updateAllDFInFromOut(LocID srcLoc, const Key &srcVar, LocID dstLoc, const Key &dstVar)=0
Union (IN[dstLoc::dstVar], OUT[srcLoc:srcVar]. There is no flag check, unlike the above...
virtual bool propVarPtsFromSrcToDst(NodeID var, const SVFGNode *src, const SVFGNode *dst)
Propagate points-to information of a certain variable from src to dst.
const DIType * getTypeFromCTirMetadata(const Value *)
PTATY
Pointer analysis type list.
double storeTime
time of store edges
static const DIType * getVTInitType(const CopySVFGNode *copy, DCHGraph *dchg)
bool print_stat
User input flags.
const NodeBS getGepObjClones(NodeID base, unsigned offset)
double gepTime
time of handling gep edges
static DdNode * empty
Definition: cuddZddLin.c:94
virtual bool strongUpdateOutFromIn(const SVFGNode *node, NodeID singleton)
Handle strong updates.
bool init(NodeID loc, NodeID p, const DIType *tildet, bool reuse, bool gep=false)
AndersenWaveDiff * ander
SVFGBuilder memSSA
NodeID getOriginalObj(NodeID c) const
Returns the original object c is cloned from. If c is not a clone, returns itself.
virtual void initialize()
Initialization of a pointer analysis, including building symbol table and PAG etc.
llvm::Value Value
Definition: BasicTypes.h:78
NodeBS PointsTo
Definition: SVFBasicTypes.h:88
virtual bool updateInFromIn(const SVFGNode *srcStmt, NodeID srcVar, const SVFGNode *dstStmt, NodeID dstVar) override
DFPTDataTy * getDFPTDataTy() const
double updateTime
time of strong/weak updates.
virtual AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
Interface expose to users of our pointer analysis, given Location infos.
llvm::DIType DIType
Definition: BasicTypes.h:217
static PAG * pag
PAG.
virtual bool propagateFromFRToAR(const FormalRetSVFGNode *fr, const SVFGNode *dst)