Static Value-Flow Analysis
SVFGOPT.h
Go to the documentation of this file.
1 //===- SVFGOPT.h -- SVFG optimizer--------------------------------------------//
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  * @file: SVFGOPT.h
25  * @author: yesen
26  * @date: 20/03/2014
27  * @version: 1.0
28  *
29  * @section LICENSE
30  *
31  * @section DESCRIPTION
32  *
33  */
34 
35 
36 #ifndef SVFGOPT_H_
37 #define SVFGOPT_H_
38 
39 
40 #include "Graphs/SVFG.h"
41 #include "Util/WorkList.h"
42 
43 namespace SVF
44 {
45 
56 class SVFGOPT : public SVFG
57 {
61 
62 public:
64  SVFGOPT(std::unique_ptr<MemSSA> mssa, VFGK kind) : SVFG(std::move(mssa), kind)
65  {
67  }
69  ~SVFGOPT() override = default;
70 
72  {
73  keepActualOutFormalIn = true;
74  }
75  inline void setTokeepAllSelfCycle()
76  {
77  keepAllSelfCycle = true;
78  }
80  {
81  keepContextSelfCycle = true;
82  }
83 
84 protected:
85  void buildSVFG() override;
86 
88 
89  inline void connectAParamAndFParam(const PAGNode* cs_arg, const PAGNode* fun_arg, const CallICFGNode*, CallSiteID csId, SVFGEdgeSetTy& edges) override
90  {
91  NodeID phiId = getDef(fun_arg);
92  SVFGEdge* edge = addCallEdge(getDef(cs_arg), phiId, csId);
93  if (edge != nullptr)
94  {
95  PHISVFGNode* phi = SVFUtil::cast<PHISVFGNode>(getSVFGNode(phiId));
96  addInterPHIOperands(phi, cs_arg);
97  edges.insert(edge);
98  }
99  }
101  inline void connectFRetAndARet(const PAGNode* fun_ret, const PAGNode* cs_ret, CallSiteID csId, SVFGEdgeSetTy& edges) override
102  {
103  NodeID phiId = getDef(cs_ret);
104  NodeID retdef = getDef(fun_ret);
108  if (pag->isPhiNode(fun_ret)==false)
109  return;
110 
111  SVFGEdge* edge = addRetEdge(retdef, phiId, csId);
112  if (edge != nullptr)
113  {
114  PHISVFGNode* phi = SVFUtil::cast<PHISVFGNode>(getSVFGNode(phiId));
115  addInterPHIOperands(phi, fun_ret);
116  edges.insert(edge);
117  }
118  }
120  inline void connectAInAndFIn(const ActualINSVFGNode* actualIn, const FormalINSVFGNode* formalIn, CallSiteID csId, SVFGEdgeSetTy& edges) override
121  {
122  NodeBS intersection = actualIn->getPointsTo();
123  intersection &= formalIn->getPointsTo();
124  if (intersection.empty() == false)
125  {
126  NodeID aiDef = getActualINDef(actualIn->getId());
127  SVFGEdge* edge = addCallIndirectSVFGEdge(aiDef,formalIn->getId(),csId,intersection);
128  if (edge != nullptr)
129  edges.insert(edge);
130  }
131  }
133  inline void connectFOutAndAOut(const FormalOUTSVFGNode* formalOut, const ActualOUTSVFGNode* actualOut, CallSiteID csId, SVFGEdgeSetTy& edges) override
134  {
135  NodeBS intersection = formalOut->getPointsTo();
136  intersection &= actualOut->getPointsTo();
137  if (intersection.empty() == false)
138  {
139  NodeID foDef = getFormalOUTDef(formalOut->getId());
140  SVFGEdge* edge = addRetIndirectSVFGEdge(foDef,actualOut->getId(),csId,intersection);
141  if (edge != nullptr)
142  edges.insert(edge);
143  }
144  }
146 
148 
149  inline NodeID getActualINDef(NodeID ai) const
150  {
151  NodeIDToNodeIDMap::const_iterator it = actualInToDefMap.find(ai);
152  assert(it != actualInToDefMap.end() && "can not find actual-in's def");
153  return it->second;
154  }
155  inline NodeID getFormalOUTDef(NodeID fo) const
156  {
157  NodeIDToNodeIDMap::const_iterator it = formalOutToDefMap.find(fo);
158  assert(it != formalOutToDefMap.end() && "can not find formal-out's def");
159  return it->second;
160  }
162 
163 private:
165 
167 
168  SVFGEdge* addCallIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS& cpts);
171  SVFGEdge* addRetIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS& cpts);
173 
182  void handleInterValueFlow();
183 
185 
186  void replaceFParamARetWithPHI(PHISVFGNode* phi, SVFGNode* svfgNode);
188 
190 
191  void retargetEdgesOfAInFOut(SVFGNode* node);
195  void retargetEdgesOfAOutFIn(SVFGNode* node);
197 
199  void handleIntraValueFlow();
200 
202  inline void initialWorkList()
203  {
204  for (SVFG::const_iterator it = begin(), eit = end(); it != eit; ++it)
205  addIntoWorklist(it->second);
206  }
207 
211  inline bool addIntoWorklist(const SVFGNode* node)
212  {
213  if (const MSSAPHISVFGNode* phi = SVFUtil::dyn_cast<MSSAPHISVFGNode>(node))
214  {
215  if (isConnectingTwoCallSites(phi) == false && isDefOfAInFOut(phi) == false)
216  return worklist.push(phi);
217  }
218  return false;
219  }
220 
222  void bypassMSSAPHINode(const MSSAPHISVFGNode* node);
223 
225  bool checkSelfCycleEdges(const MSSAPHISVFGNode* node);
226 
228  bool addNewSVFGEdge(NodeID srcId, NodeID dstId, const SVFGEdge* preEdge, const SVFGEdge* succEdge);
229 
231  inline bool bothInterEdges(const SVFGEdge* edge1, const SVFGEdge* edge2) const
232  {
233  bool inter1 = SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(edge1);
234  bool inter2 = SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(edge2);
235  return (inter1 && inter2);
236  }
237 
238  inline void addInterPHIOperands(PHISVFGNode* phi, const PAGNode* operand)
239  {
240  phi->setOpVer(phi->getOpVerNum(), operand);
241  }
242 
245  {
247  addSVFGNode(sNode, pag->getICFG()->getFunEntryICFGNode(fp->getFun()));
248  resetDef(fp->getParam(),sNode);
249  return sNode;
250  }
253  {
255  addSVFGNode(sNode, const_cast<RetICFGNode*>(
256  ar->getCallSite()->getRetICFGNode()));
257  resetDef(ar->getRev(),sNode);
258  return sNode;
259  }
260 
261  inline void resetDef(const PAGNode* pagNode, const SVFGNode* node)
262  {
263  PAGNodeToDefMapTy::iterator it = PAGNodeToDefMap.find(pagNode);
264  assert(it != PAGNodeToDefMap.end() && "a SVFIR node doesn't have definition before");
265  it->second = node->getId();
266  }
267 
270  inline void setActualINDef(NodeID ai, NodeID def)
271  {
272  bool inserted = actualInToDefMap.emplace(ai, def).second;
273  (void)inserted; // Suppress warning of unused variable under release build
274  assert(inserted && "can not set actual-in's def twice");
275  defNodes.set(def);
276  }
277  inline void setFormalOUTDef(NodeID fo, NodeID def)
278  {
279  bool inserted = formalOutToDefMap.emplace(fo, def).second;
280  (void) inserted;
281  assert(inserted && "can not set formal-out's def twice");
282  defNodes.set(def);
283  }
285 
286  inline bool isDefOfAInFOut(const SVFGNode* node)
287  {
288  return defNodes.test(node->getId());
289  }
290 
292 
293  inline bool actualInOfIndCS(const ActualINSVFGNode* ai) const
294  {
295  return (SVFIR::getPAG()->isIndirectCallSites(ai->getCallSite()));
296  }
297  inline bool actualOutOfIndCS(const ActualOUTSVFGNode* ao) const
298  {
299  return (SVFIR::getPAG()->isIndirectCallSites(ao->getCallSite()));
300  }
302 
304 
305  inline bool formalInOfAddressTakenFunc(const FormalINSVFGNode* fi) const
306  {
307  return (fi->getFun()->hasAddressTaken());
308  }
309  inline bool formalOutOfAddressTakenFunc(const FormalOUTSVFGNode* fo) const
310  {
311  return (fo->getFun()->hasAddressTaken());
312  }
314 
316  bool isConnectingTwoCallSites(const SVFGNode* node) const;
317 
327  bool canBeRemoved(const SVFGNode * node);
328 
330 
331  inline void removeAllEdges(const SVFGNode* node)
332  {
333  removeInEdges(node);
334  removeOutEdges(node);
335  }
336  inline void removeInEdges(const SVFGNode* node)
337  {
339  while (node->hasIncomingEdge())
340  removeSVFGEdge(*(node->InEdgeBegin()));
341  }
342  inline void removeOutEdges(const SVFGNode* node)
343  {
344  while (node->hasOutgoingEdge())
345  removeSVFGEdge(*(node->OutEdgeBegin()));
346  }
348 
349 
353 
355 
359 };
360 
361 } // End namespace SVF
362 
363 #endif /* SVFGOPT_H_ */
const CallICFGNode * getCallSite() const
Callsite.
Definition: SVFGNode.h:182
const CallICFGNode * getCallSite() const
Callsite.
Definition: SVFGNode.h:232
const CallICFGNode * getCallSite() const
Return callsite.
Definition: VFGNode.h:1034
const PAGNode * getRev() const
Receive parameter at callsite.
Definition: VFGNode.h:1044
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition: ICFGNode.h:457
bool push(const Data &data)
Definition: WorkList.h:165
const PAGNode * getParam() const
Return parameter.
Definition: VFGNode.h:959
const SVFFunction * getFun() const override
Return function.
Definition: VFGNode.h:965
iterator begin()
Iterators.
Definition: GenericGraph.h:627
IDToNodeMapTy::const_iterator const_iterator
Definition: GenericGraph.h:607
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
Definition: GenericGraph.h:442
bool hasOutgoingEdge() const
Definition: GenericGraph.h:446
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
iterator InEdgeBegin()
Definition: GenericGraph.h:462
FunEntryICFGNode * getFunEntryICFGNode(const SVFFunction *fun)
Add a function entry node.
Definition: ICFG.cpp:234
const NodeBS & getPointsTo() const
Return points-to of the MR.
Definition: SVFGNode.h:52
void setOpVer(u32_t pos, const PAGNode *node)
Definition: VFGNode.h:695
u32_t getOpVerNum() const
Definition: VFGNode.h:703
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
bool hasAddressTaken() const
Definition: SVFValue.h:376
Set< SVFGNode * > SVFGNodeSet
Definition: SVFGOPT.h:58
bool isDefOfAInFOut(const SVFGNode *node)
Definition: SVFGOPT.h:286
SVFGEdge * addCallIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add inter-procedural value flow edge.
Definition: SVFGOPT.cpp:68
void replaceFParamARetWithPHI(PHISVFGNode *phi, SVFGNode *svfgNode)
Replace FormalParam/ActualRet node with PHI node.
Definition: SVFGOPT.cpp:151
void handleIntraValueFlow()
Remove MSSAPHI SVFG nodes.
Definition: SVFGOPT.cpp:391
void retargetEdgesOfAOutFIn(SVFGNode *node)
Connect actual-out/formal-in's predecessors to their successors directly.
Definition: SVFGOPT.cpp:250
void addInterPHIOperands(PHISVFGNode *phi, const PAGNode *operand)
Definition: SVFGOPT.h:238
InterPHISVFGNode * addInterPHIForFP(const FormalParmSVFGNode *fp)
Add inter PHI SVFG node for formal parameter.
Definition: SVFGOPT.h:244
void setFormalOUTDef(NodeID fo, NodeID def)
Definition: SVFGOPT.h:277
FIFOWorkList< const MSSAPHISVFGNode * > WorkList
Definition: SVFGOPT.h:60
void setActualINDef(NodeID ai, NodeID def)
Definition: SVFGOPT.h:270
void handleInterValueFlow()
Definition: SVFGOPT.cpp:90
void bypassMSSAPHINode(const MSSAPHISVFGNode *node)
Remove MSSAPHI node if possible.
Definition: SVFGOPT.cpp:480
NodeID getActualINDef(NodeID ai) const
Get def-site of actual-in/formal-out.
Definition: SVFGOPT.h:149
Map< NodeID, NodeID > NodeIDToNodeIDMap
Definition: SVFGOPT.h:59
void removeInEdges(const SVFGNode *node)
Definition: SVFGOPT.h:336
void connectAInAndFIn(const ActualINSVFGNode *actualIn, const FormalINSVFGNode *formalIn, CallSiteID csId, SVFGEdgeSetTy &edges) override
Connect actual-in and formal-in.
Definition: SVFGOPT.h:120
SVFGOPT(std::unique_ptr< MemSSA > mssa, VFGK kind)
Constructor.
Definition: SVFGOPT.h:64
bool keepAllSelfCycle
Definition: SVFGOPT.h:357
bool addNewSVFGEdge(NodeID srcId, NodeID dstId, const SVFGEdge *preEdge, const SVFGEdge *succEdge)
Add new SVFG edge from src to dst.
Definition: SVFGOPT.cpp:523
bool bothInterEdges(const SVFGEdge *edge1, const SVFGEdge *edge2) const
Return TRUE if both edges are indirect call/ret edges.
Definition: SVFGOPT.h:231
bool formalInOfAddressTakenFunc(const FormalINSVFGNode *fi) const
Check if formal-in/formal-out reside in address-taken function.
Definition: SVFGOPT.h:305
bool addIntoWorklist(const SVFGNode *node)
Definition: SVFGOPT.h:211
void buildSVFG() override
Start building SVFG.
Definition: SVFGOPT.cpp:47
bool actualOutOfIndCS(const ActualOUTSVFGNode *ao) const
Definition: SVFGOPT.h:297
bool keepActualOutFormalIn
Definition: SVFGOPT.h:356
void connectAParamAndFParam(const PAGNode *cs_arg, const PAGNode *fun_arg, const CallICFGNode *, CallSiteID csId, SVFGEdgeSetTy &edges) override
Connect SVFG nodes between caller and callee for indirect call sites.
Definition: SVFGOPT.h:89
bool formalOutOfAddressTakenFunc(const FormalOUTSVFGNode *fo) const
Definition: SVFGOPT.h:309
NodeID getFormalOUTDef(NodeID fo) const
Definition: SVFGOPT.h:155
WorkList worklist
storing MSSAPHI nodes which may be removed.
Definition: SVFGOPT.h:354
NodeIDToNodeIDMap actualInToDefMap
map actual-in to its def-site node
Definition: SVFGOPT.h:350
void setTokeepAllSelfCycle()
Definition: SVFGOPT.h:75
bool isConnectingTwoCallSites(const SVFGNode *node) const
Return TRUE if this node has both incoming call/ret and outgoing call/ret edges.
Definition: SVFGOPT.cpp:292
bool canBeRemoved(const SVFGNode *node)
Definition: SVFGOPT.cpp:334
NodeIDToNodeIDMap formalOutToDefMap
map formal-out to its def-site node
Definition: SVFGOPT.h:351
NodeBS defNodes
preserved def nodes of formal-in/actual-out
Definition: SVFGOPT.h:352
void setTokeepContextSelfCycle()
Definition: SVFGOPT.h:79
void retargetEdgesOfAInFOut(SVFGNode *node)
Retarget edges related to actual-in/-out and formal-in/-out.
Definition: SVFGOPT.cpp:204
void removeAllEdges(const SVFGNode *node)
Remove edges of a SVFG node.
Definition: SVFGOPT.h:331
void parseSelfCycleHandleOption()
Definition: SVFGOPT.cpp:372
bool keepContextSelfCycle
Definition: SVFGOPT.h:358
~SVFGOPT() override=default
Destructor.
InterPHISVFGNode * addInterPHIForAR(const ActualRetSVFGNode *ar)
Add inter PHI SVFG node for actual return.
Definition: SVFGOPT.h:252
void connectFOutAndAOut(const FormalOUTSVFGNode *formalOut, const ActualOUTSVFGNode *actualOut, CallSiteID csId, SVFGEdgeSetTy &edges) override
Connect formal-out and actual-out.
Definition: SVFGOPT.h:133
void connectFRetAndARet(const PAGNode *fun_ret, const PAGNode *cs_ret, CallSiteID csId, SVFGEdgeSetTy &edges) override
Connect formal-ret and actual ret.
Definition: SVFGOPT.h:101
void initialWorkList()
Initial work list with MSSAPHI nodes which may be removed.
Definition: SVFGOPT.h:202
void removeOutEdges(const SVFGNode *node)
Definition: SVFGOPT.h:342
void setTokeepActualOutFormalIn()
Definition: SVFGOPT.h:71
void resetDef(const PAGNode *pagNode, const SVFGNode *node)
Definition: SVFGOPT.h:261
bool actualInOfIndCS(const ActualINSVFGNode *ai) const
Check if actual-in/actual-out exist at indirect call site.
Definition: SVFGOPT.h:293
SVFGEdge * addRetIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add indirect ret edge from src to dst with one call site ID.
Definition: SVFGOPT.cpp:79
bool checkSelfCycleEdges(const MSSAPHISVFGNode *node)
Remove self cycle edges if needed. Return TRUE if some self cycle edges remained.
Definition: SVFGOPT.cpp:442
Definition: SVFG.h:66
SVFGNode * getSVFGNode(NodeID id) const
Get a SVFG node.
Definition: SVFG.h:150
virtual void addSVFGNode(SVFGNode *node, ICFGNode *icfgNode)
Add SVFG node.
Definition: SVFG.h:397
void removeSVFGEdge(SVFGEdge *edge)
Remove a SVFG edge.
Definition: SVFG.h:238
std::unique_ptr< MemSSA > mssa
Definition: SVFG.h:106
NodeID getDef(const PAGNode *pagNode) const
Definition: SVFG.h:356
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition: SVFIR.h:115
bool isPhiNode(const SVFVar *node) const
Whether this SVFVar is a result operand a of phi node.
Definition: SVFIR.h:259
ICFG * getICFG() const
Definition: SVFIR.h:171
bool test(unsigned Idx) const
void set(unsigned Idx)
virtual const SVFFunction * getFun() const
Get the function of this SVFGNode.
Definition: VFGNode.h:79
SVFIR * pag
Definition: VFG.h:104
VFGEdge * addRetEdge(NodeID srcId, NodeID dstId, CallSiteID csId)
Definition: VFG.cpp:721
VFGK kind
Definition: VFG.h:105
VFGEdge * addCallEdge(NodeID srcId, NodeID dstId, CallSiteID csId)
Definition: VFG.cpp:701
VFGK
VFG kind.
Definition: VFG.h:56
PAGNodeToDefMapTy PAGNodeToDefMap
map a pag node to its definition SVG node
Definition: VFG.h:89
VFGEdge::SVFGEdgeSetTy SVFGEdgeSetTy
Definition: VFG.h:78
NodeID totalVFGNode
Definition: VFG.h:88
constexpr std::remove_reference< T >::type && move(T &&t) noexcept
Definition: SVFUtil.h:447
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
InterPHIVFGNode InterPHISVFGNode
Definition: SVFG.h:58
u32_t NodeID
Definition: GeneralType.h:55
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96