Static Value-Flow Analysis
Classes | Static Public Member Functions | Private Types | Static Private Member Functions | List of all members
SVF::VersionedFlowSensitive::SCC Class Reference

Classes

struct  NodeData
 

Static Public Member Functions

static unsigned detectSCCs (VersionedFlowSensitive *vfs, const SVFG *svfg, const NodeID object, const std::vector< const SVFGNode * > &startingNodes, std::vector< int > &partOf, std::vector< const IndirectSVFGEdge * > &footprint)
 

Private Types

typedef struct SVF::VersionedFlowSensitive::SCC::NodeData NodeData
 

Static Private Member Functions

static void visit (VersionedFlowSensitive *vfs, const NodeID object, std::vector< int > &partOf, std::vector< const IndirectSVFGEdge * > &footprint, std::vector< NodeData > &nodeData, std::stack< const SVFGNode * > &stack, int &index, int &currentSCC, const SVFGNode *v)
 Called by detectSCCs then called recursively. More...
 

Detailed Description

Definition at line 251 of file VersionedFlowSensitive.h.

Member Typedef Documentation

◆ NodeData

Member Function Documentation

◆ detectSCCs()

unsigned VersionedFlowSensitive::SCC::detectSCCs ( VersionedFlowSensitive vfs,
const SVFG svfg,
const NodeID  object,
const std::vector< const SVFGNode * > &  startingNodes,
std::vector< int > &  partOf,
std::vector< const IndirectSVFGEdge * > &  footprint 
)
static

Determines the strongly connected components of svfg following only edges labelled with object. partOf[n] = scc means nodes n is part of SCC scc. startingNodes contains the nodes to begin the search from. After completion, footprint will contain all edges which object appears on (as reached through the algorithm described above) sorted.

This is not a general SCC detection but specifically for versioning, so edges to delta nodes are skipped as they are prelabelled. Edges to stores are also skipped to as they yield a new version (they cannot be part of an SCC containing more than themselves). Skipped edges still form part of the footprint.

Definition at line 1109 of file VersionedFlowSensitive.cpp.

1114 {
1115  partOf.resize(svfg->getTotalNodeNum());
1116  std::fill(partOf.begin(), partOf.end(), -1);
1117  footprint.clear();
1118 
1119  std::vector<NodeData> nodeData(svfg->getTotalNodeNum(), { -1, -1, false});
1120  std::stack<const SVFGNode *> stack;
1121 
1122  int index = 0;
1123  int currentSCC = 0;
1124 
1125  for (const SVFGNode *v : startingNodes)
1126  {
1127  if (nodeData[v->getId()].index == -1)
1128  {
1129  visit(vfs, object, partOf, footprint, nodeData, stack, index, currentSCC, v);
1130  }
1131  }
1132 
1133  // Make sure footprints with the same edges pass ==/hash the same.
1134  std::sort(footprint.begin(), footprint.end());
1135 
1136  return currentSCC;
1137 }
int index
Definition: cJSON.h:170
u32_t getTotalNodeNum() const
Get total number of node/edge.
Definition: GenericGraph.h:680
static void visit(VersionedFlowSensitive *vfs, const NodeID object, std::vector< int > &partOf, std::vector< const IndirectSVFGEdge * > &footprint, std::vector< NodeData > &nodeData, std::stack< const SVFGNode * > &stack, int &index, int &currentSCC, const SVFGNode *v)
Called by detectSCCs then called recursively.

◆ visit()

void VersionedFlowSensitive::SCC::visit ( VersionedFlowSensitive vfs,
const NodeID  object,
std::vector< int > &  partOf,
std::vector< const IndirectSVFGEdge * > &  footprint,
std::vector< NodeData > &  nodeData,
std::stack< const SVFGNode * > &  stack,
int &  index,
int &  currentSCC,
const SVFGNode v 
)
staticprivate

Called by detectSCCs then called recursively.

Definition at line 1139 of file VersionedFlowSensitive.cpp.

1148 {
1149  const NodeID vId = v->getId();
1150 
1151  nodeData[vId].index = index;
1152  nodeData[vId].lowlink = index;
1153  ++index;
1154 
1155  stack.push(v);
1156  nodeData[vId].onStack = true;
1157 
1158  for (const SVFGEdge *e : v->getOutEdges())
1159  {
1160  const IndirectSVFGEdge *ie = SVFUtil::dyn_cast<IndirectSVFGEdge>(e);
1161  if (!ie) continue;
1162 
1163  const SVFGNode *w = ie->getDstNode();
1164  const NodeID wId = w->getId();
1165 
1166  // If object is not part of the edge, there is no edge from v to w.
1167  if (!ie->getPointsTo().test(object)) continue;
1168 
1169  // Even if we don't count edges to stores and deltas for SCCs' sake, they
1170  // are relevant to the footprint as a propagation still occurs over such edges.
1171  footprint.push_back(ie);
1172 
1173  // Ignore edges to delta nodes because they are prelabeled so cannot
1174  // be part of the SCC v is in (already in nodesTodo from the prelabeled set).
1175  // Similarly, store nodes.
1176  if (vfs->delta(wId) || vfs->isStore(wId)) continue;
1177 
1178  if (nodeData[wId].index == -1)
1179  {
1180  visit(vfs, object, partOf, footprint, nodeData, stack, index, currentSCC, w);
1181  nodeData[vId].lowlink = std::min(nodeData[vId].lowlink, nodeData[wId].lowlink);
1182  }
1183  else if (nodeData[wId].onStack)
1184  {
1185  nodeData[vId].lowlink = std::min(nodeData[vId].lowlink, nodeData[wId].index);
1186  }
1187  }
1188 
1189  if (nodeData[vId].lowlink == nodeData[vId].index)
1190  {
1191  const SVFGNode *w = nullptr;
1192  do
1193  {
1194  w = stack.top();
1195  stack.pop();
1196  const NodeID wId = w->getId();
1197  nodeData[wId].onStack = false;
1198  partOf[wId] = currentSCC;
1199  }
1200  while (w != v);
1201 
1202  // For the next SCC.
1203  ++currentSCC;
1204  }
1205 }
NodeType * getDstNode() const
Definition: GenericGraph.h:101
const GEdgeSetTy & getOutEdges() const
Definition: GenericGraph.h:430
const NodeBS & getPointsTo() const
Definition: SVFGEdge.h:60
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
bool test(unsigned Idx) const
virtual bool delta(const NodeID l) const
virtual bool isStore(const NodeID l) const
Returns true if l is a store node.
u32_t NodeID
Definition: GeneralType.h:55

The documentation for this class was generated from the following files: