Static Value-Flow Analysis
AndersenSCD.cpp
Go to the documentation of this file.
1 //===- AndersenSCD.cpp -- SCD based field-sensitive Andersen's analysis-------//
2 //
3 // SVF: Static Value-Flow Analysis
4 //
5 // Copyright (C) <2013-2017> <Yulei Sui>
6 //
7 
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as published by
10 // the Free Software Foundation, either version 3 of the License, or
11 // (at your option) any later version.
12 
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
17 
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 /*
24  * AndersenSCD.cpp
25  *
26  * Created on: 09, Feb, 2019
27  * Author: Yuxiang Lei
28  */
29 
30 #include "WPA/AndersenPWC.h"
31 #include "MemoryModel/PointsTo.h"
32 #include "Util/Options.h"
33 
34 using namespace SVF;
35 using namespace SVFUtil;
36 using namespace std;
37 
39 
40 
45 {
46  // Initialize the nodeStack via a whole SCC detection
47  // Nodes in nodeStack are in topological order by default.
48  NodeStack& nodeStack = SCCDetect();
49 
50  for (NodeID nId : sccCandidates)
51  pushIntoWorklist(nId);
52  sccCandidates.clear();
53 
54  // propagate point-to sets
55  while (!nodeStack.empty())
56  {
57  NodeID nodeId = nodeStack.top();
58  nodeStack.pop();
59 
60  if (sccRepNode(nodeId) == nodeId)
61  {
62  collapsePWCNode(nodeId);
63 
64  if (isInWorklist(nodeId))
65  // push the rep of node into worklist
66  pushIntoWorklist(nodeId);
67 
68  double propStart = stat->getClk();
69  // propagate pts through copy and gep edges
70  ConstraintNode* node = consCG->getConstraintNode(nodeId);
71  handleCopyGep(node);
72  double propEnd = stat->getClk();
73  timeOfProcessCopyGep += (propEnd - propStart) / TIMEINTERVAL;
74 
75  collapseFields();
76  }
77  }
78 
79  // New nodes will be inserted into workList during processing.
80  while (!isWorklistEmpty())
81  {
82  NodeID nodeId = popFromWorklist();
83 
84  double insertStart = stat->getClk();
85  // add copy edges via processing load or store edges
86  ConstraintNode* node = consCG->getConstraintNode(nodeId);
87  handleLoadStore(node);
88  double insertEnd = stat->getClk();
89  timeOfProcessLoadStore += (insertEnd - insertStart) / TIMEINTERVAL;
90  }
91 }
92 
93 
98 {
99  numOfSCCDetection++;
100 
101  double sccStart = stat->getClk();
102  getSCCDetector()->find(sccCandidates);
103  double sccEnd = stat->getClk();
104  timeOfSCCDetection += (sccEnd - sccStart)/TIMEINTERVAL;
105 
106  double mergeStart = stat->getClk();
107  mergeSccCycle();
108  double mergeEnd = stat->getClk();
109  timeOfSCCMerges += (mergeEnd - mergeStart)/TIMEINTERVAL;
110 
111  if (!Options::DetectPWC())
112  {
113  sccStart = stat->getClk();
114  PWCDetect();
115  sccEnd = stat->getClk();
116  timeOfSCCDetection += (sccEnd - sccStart) / TIMEINTERVAL;
117  }
118 
119  return getSCCDetector()->topoNodeStack();
120 }
121 
122 
127 {
128  // replace scc candidates by their reps
129  NodeSet tmpSccCandidates = sccCandidates;
130  sccCandidates.clear();
131  for (NodeID candidate : tmpSccCandidates)
132  sccCandidates.insert(sccRepNode(candidate));
133  tmpSccCandidates.clear();
134 
135  // set scc edge type as direct edge
136  bool pwcFlag = Options::DetectPWC();
137  setDetectPWC(true);
138 
139  getSCCDetector()->find(sccCandidates);
140 
141  // reset scc edge type
142  setDetectPWC(pwcFlag);
143 }
144 
145 
150 {
151  NodeID nodeId = node->getId();
152 
153  if (!Options::DetectPWC() && getSCCDetector()->subNodes(nodeId).count() > 1)
154  processPWC(node);
155  else if(isInWorklist(nodeId))
157 }
158 
159 
164 {
165  NodeID repId = rep->getId();
166 
167  NodeSet pwcNodes;
168  for (NodeID nId : getSCCDetector()->subNodes(repId))
169  pwcNodes.insert(nId);
170 
171  WorkList tmpWorkList;
172  for (NodeID subId : pwcNodes)
173  if (isInWorklist(subId))
174  tmpWorkList.push(subId);
175 
176  while (!tmpWorkList.empty())
177  {
178  NodeID nodeId = tmpWorkList.pop();
179  computeDiffPts(nodeId);
180 
181  if (!getDiffPts(nodeId).empty())
182  {
183  ConstraintNode *node = consCG->getConstraintNode(nodeId);
184  for (ConstraintEdge* edge : node->getCopyOutEdges())
185  {
186  bool changed = processCopy(nodeId, edge);
187  if (changed && pwcNodes.find(edge->getDstID()) != pwcNodes.end())
188  tmpWorkList.push(edge->getDstID());
189  }
190  for (ConstraintEdge* edge : node->getGepOutEdges())
191  {
192  if (GepCGEdge *gepEdge = SVFUtil::dyn_cast<GepCGEdge>(edge))
193  {
194  bool changed = processGep(nodeId, gepEdge);
195  if (changed && pwcNodes.find(edge->getDstID()) != pwcNodes.end())
196  tmpWorkList.push(edge->getDstID());
197  }
198  }
199  }
200  }
201 }
202 
203 
209 {
210  double insertStart = stat->getClk();
211 
212  NodeID nodeId = node->getId();
213  // handle load
215  eit = node->outgoingLoadsEnd(); it != eit; ++it)
216  for (PointsTo::iterator piter = getPts(nodeId).begin(), epiter =
217  getPts(nodeId).end(); piter != epiter; ++piter)
218  {
219  NodeID ptd = *piter;
220  if (processLoad(ptd, *it))
221  {
222  reanalyze = true;
223  }
224  }
225 
226  // handle store
228  eit = node->incomingStoresEnd(); it != eit; ++it)
229  for (PointsTo::iterator piter = getPts(nodeId).begin(), epiter =
230  getPts(nodeId).end(); piter != epiter; ++piter)
231  {
232  NodeID ptd = *piter;
233  if (processStore(ptd, *it))
234  {
235  reanalyze = true;
236  }
237  }
238 
239  double insertEnd = stat->getClk();
240  timeOfProcessLoadStore += (insertEnd - insertStart) / TIMEINTERVAL;
241 }
242 
243 
248 {
249  numOfProcessedAddr++;
250 
251  NodeID dst = addr->getDstID();
252  NodeID src = addr->getSrcID();
253  addPts(dst,src);
254  addSccCandidate(dst);
255 }
256 
257 
262 {
263  if (Andersen::addCopyEdge(src, dst))
264  {
265  addSccCandidate(src);
266  return true;
267  }
268  return false;
269 }
270 
271 
276 {
277  double cgUpdateStart = stat->getClk();
278 
279  CallEdgeMap newEdges;
280  onTheFlyCallGraphSolve(callsites,newEdges);
281  NodePairSet cpySrcNodes;
282  for(CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end(); it!=eit; ++it )
283  {
284  for(FunctionSet::iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
285  {
286  connectCaller2CalleeParams(it->first,*cit,cpySrcNodes);
287  }
288  }
289 
290  double cgUpdateEnd = stat->getClk();
291  timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
292 
293  return (!newEdges.empty());
294 }
#define TIMEINTERVAL
Definition: SVFType.h:512
int count
Definition: cJSON.h:216
virtual bool addCopyEdge(NodeID src, NodeID dst)
static AndersenSCD * scdAndersen
Definition: AndersenPWC.h:50
virtual bool updateCallGraph(const CallSiteToFunPtrMap &callsites)
virtual void processAddr(const AddrCGEdge *addr)
virtual NodeStack & SCCDetect()
Definition: AndersenSCD.cpp:97
virtual void handleLoadStore(ConstraintNode *node)
virtual void solveWorklist()
Definition: AndersenSCD.cpp:44
virtual void handleCopyGep(ConstraintNode *node)
virtual void processPWC(ConstraintNode *rep)
virtual void PWCDetect()
virtual bool addCopyEdge(NodeID src, NodeID dst)
Add copy edge on constraint graph.
Definition: Andersen.h:323
virtual void handleCopyGep(ConstraintNode *node)
Definition: Andersen.cpp:476
const_iterator outgoingLoadsEnd() const
Definition: ConsGNode.h:194
const ConstraintEdge::ConstraintEdgeSetTy & getGepOutEdges() const
Definition: ConsGNode.h:123
const_iterator incomingStoresBegin() const
Definition: ConsGNode.h:215
const_iterator incomingStoresEnd() const
Definition: ConsGNode.h:219
ConstraintEdge::ConstraintEdgeSetTy::const_iterator const_iterator
Definition: ConsGNode.h:45
const ConstraintEdge::ConstraintEdgeSetTy & getCopyOutEdges() const
Definition: ConsGNode.h:115
const_iterator outgoingLoadsBegin() const
Definition: ConsGNode.h:190
bool push(const Data &data)
Definition: WorkList.h:165
bool empty() const
Definition: WorkList.h:146
NodeID getDstID() const
Definition: GenericGraph.h:85
NodeID getSrcID() const
get methods of the components
Definition: GenericGraph.h:81
static Option< bool > DetectPWC
Definition: Options.h:216
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
SVFIR::CallSiteToFunPtrMap CallSiteToFunPtrMap
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
for isBitcode
Definition: BasicTypes.h:68
std::stack< NodeID > NodeStack
Definition: GeneralType.h:118
Set< NodeID > NodeSet
Definition: GeneralType.h:113
u32_t NodeID
Definition: GeneralType.h:55
Set< NodePair > NodePairSet
Definition: GeneralType.h:114