Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVFGOPT.cpp
Go to the documentation of this file.
1//===- SVFGOPT.cpp -- 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.cpp
25 * @author: yesen
26 * @date: 31/03/2014
27 * @version: 1.0
28 *
29 * @section LICENSE
30 *
31 * @section DESCRIPTION
32 *
33 */
34
35#include "Util/Options.h"
36#include "Graphs/SVFGOPT.h"
37#include "Graphs/SVFGStat.h"
38
39using namespace SVF;
40using namespace SVFUtil;
41
42static std::string KeepAllSelfCycle = "all";
43static std::string KeepContextSelfCycle = "context";
44static std::string KeepNoneSelfCycle = "none";
45
47void SVFGOPT::readAndOptSVFG(const std::string &filename)
48{
51}
52
60
66
69{
71 dump("SVFG_before_opt");
72
73 DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("\tSVFG Optimisation\n"));
74
76
79
82
83}
84
95
106
111{
112 SVFGNodeSet candidates;
113 for (SVFGNodeIDToNodeMapTy::iterator it = SVFG::begin(), eit = SVFG::end();
114 it!=eit; ++it)
115 {
116 SVFGNode* node = it->second;
120 candidates.insert(node);
121 }
122
124 for (SVFGNodeSet::const_iterator it = candidates.begin(), eit = candidates.end();
125 it!=eit; ++it)
126 {
127 SVFGNode* node = *it;
128 if (FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(node))
129 {
131 nodesToBeDeleted.insert(fp);
132 }
133 else if (ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(node))
134 {
136 nodesToBeDeleted.insert(ar);
137 }
138 else if (SVFUtil::isa<ActualParmSVFGNode, FormalRetSVFGNode>(node))
139 {
140 nodesToBeDeleted.insert(node);
141 }
142 else if (SVFUtil::isa<ActualINSVFGNode, FormalOUTSVFGNode>(node))
143 {
145 nodesToBeDeleted.insert(node);
146 }
147 else if (SVFUtil::isa<ActualOUTSVFGNode, FormalINSVFGNode>(node))
148 {
149 if(keepActualOutFormalIn == false)
150 nodesToBeDeleted.insert(node);
151 }
152 }
153
154 for (SVFGNodeSet::iterator it = nodesToBeDeleted.begin(), eit = nodesToBeDeleted.end(); it != eit; ++it)
155 {
156 SVFGNode* node = *it;
157 if (canBeRemoved(node))
158 {
159 if (SVFUtil::isa<ActualOUTSVFGNode, FormalINSVFGNode>(node))
161
162 removeAllEdges(node);
163 removeSVFGNode(node);
164 }
165 }
166}
167
172{
173 assert((SVFUtil::isa<FormalParmSVFGNode, ActualRetSVFGNode>(svfgNode))
174 && "expecting a formal param or actual ret svfg node");
175
177 NodeID phiId = phi->getId();
179 for (SVFGNode::const_iterator it = svfgNode->OutEdgeBegin(), eit = svfgNode->OutEdgeEnd();
180 it != eit; ++it)
181 {
182 const SVFGEdge* outEdge = *it;
183 SVFGNode* dstNode = outEdge->getDstNode();
185 if (const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(outEdge))
186 addCallEdge(phiId, dstId, callEdge->getCallSiteId());
187 else if (const RetDirSVFGEdge* retEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(outEdge))
188 addRetEdge(phiId, dstId, retEdge->getCallSiteId());
189 else
191 }
192
194 if (FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(svfgNode))
195 {
196 for (SVFGNode::iterator it = svfgNode->InEdgeBegin(), eit = svfgNode->InEdgeEnd();
197 it != eit; ++it)
198 {
199 ActualParmSVFGNode* ap = SVFUtil::cast<ActualParmSVFGNode>((*it)->getSrcNode());
201 // connect actual param's def node to phi node
203 }
204 }
205 else if (ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(svfgNode))
206 {
207 for (SVFGNode::iterator it = svfgNode->InEdgeBegin(), eit = svfgNode->InEdgeEnd();
208 it != eit; ++it)
209 {
210 FormalRetSVFGNode* fr = SVFUtil::cast<FormalRetSVFGNode>((*it)->getSrcNode());
211 addInterPHIOperands(phi, fr->getRet());
212 // connect formal return's def node to phi node
213 addRetEdge(getDef(fr->getRet()), phiId, getCallSiteID(ar->getCallSite(), fr->getFun()));
214 }
215 }
216
218}
219
225{
226 assert(node->getInEdges().size() == 1 && "actual-in/formal-out can only have one incoming edge as its def size");
227
228 SVFGNode* def = nullptr;
230
233 for (; it != eit; ++it)
234 {
235 const IndirectSVFGEdge* inEdge = SVFUtil::cast<IndirectSVFGEdge>(*it);
236 inPointsTo = inEdge->getPointsTo();
237
238 def = inEdge->getSrcNode();
239 if (SVFUtil::isa<ActualINSVFGNode>(node))
240 setActualINDef(node->getId(), def->getId());
241 else if (SVFUtil::isa<FormalOUTSVFGNode>(node))
242 setFormalOUTDef(node->getId(), def->getId());
243 }
244
245 it = node->OutEdgeBegin(), eit = node->OutEdgeEnd();
246 for (; it != eit; ++it)
247 {
248 const IndirectSVFGEdge* outEdge = SVFUtil::cast<IndirectSVFGEdge>(*it);
250 intersection &= outEdge->getPointsTo();
251
252 if (intersection.empty())
253 continue;
254
255 SVFGNode* dstNode = outEdge->getDstNode();
256 if (const CallIndSVFGEdge* callEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(outEdge))
257 addCallIndirectSVFGEdge(def->getId(), dstNode->getId(), callEdge->getCallSiteId(), intersection);
258 else if (const RetIndSVFGEdge* retEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(outEdge))
259 addRetIndirectSVFGEdge(def->getId(), dstNode->getId(), retEdge->getCallSiteId(), intersection);
260 else
261 assert(false && "expecting an inter-procedural SVFG edge");
262 }
263
264 removeAllEdges(node);
265}
266
271{
274 for (; inIt != inEit; ++inIt)
275 {
276 const IndirectSVFGEdge* inEdge = SVFUtil::cast<IndirectSVFGEdge>(*inIt);
277 NodeID srcId = inEdge->getSrcID();
278
281 for (; outIt != outEit; ++outIt)
282 {
283 const IndirectSVFGEdge* outEdge = SVFUtil::cast<IndirectSVFGEdge>(*outIt);
284
285 NodeBS intersection = inEdge->getPointsTo();
286 intersection &= outEdge->getPointsTo();
287 if (intersection.empty())
288 continue;
289
290 NodeID dstId = outEdge->getDstID();
291 if (const RetIndSVFGEdge* retEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(inEdge))
292 {
294 }
295 else if (const CallIndSVFGEdge* callEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(inEdge))
296 {
298 }
299 else
300 {
302 }
303 }
304 }
305
306 removeAllEdges(node);
307}
308
313{
314 bool hasInCallRet = false;
315 bool hasOutCallRet = false;
316
319 for (; edgeIt != edgeEit; ++edgeIt)
320 {
321 if (SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(*edgeIt))
322 {
323 hasInCallRet = true;
324 break;
325 }
326 }
327
328 edgeIt = node->OutEdgeBegin();
329 edgeEit = node->OutEdgeEnd();
330 for (; edgeIt != edgeEit; ++edgeIt)
331 {
332 if (SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(*edgeIt))
333 {
334 hasOutCallRet = true;
335 break;
336 }
337 }
338
340 return true;
341 else
342 return false;
343}
344
355{
358 return true;
361 {
365 if (isConnectingTwoCallSites(node))
366 return false;
367
368 if (const ActualINSVFGNode* ai = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
369 {
370 return (actualInOfIndCS(ai) == false);
371 }
372 else if (const ActualOUTSVFGNode* ao = SVFUtil::dyn_cast<ActualOUTSVFGNode>(node))
373 {
374 return (actualOutOfIndCS(ao) == false && isDefOfAInFOut(node) == false);
375 }
376 else if (const FormalINSVFGNode* fi = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
377 {
378 return (formalInOfAddressTakenFunc(fi) == false && isDefOfAInFOut(node) == false);
379 }
380 else if (const FormalOUTSVFGNode* fo = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
381 {
382 return (formalOutOfAddressTakenFunc(fo) == false);
383 }
384 }
385
386 return false;
387}
388
393{
394 std::string choice = (Options::SelfCycle().empty()) ? "" : Options::SelfCycle();
395 if (choice.empty() || choice == KeepAllSelfCycle)
396 keepAllSelfCycle = true;
397 else if (choice == KeepContextSelfCycle)
399 else if (choice == KeepNoneSelfCycle)
401 else
402 {
403 SVFUtil::writeWrnMsg("Unrecognised option. All self cycle edges will be kept.");
404 keepAllSelfCycle = true;
405 }
406}
407
412{
414
416
417 while (!worklist.empty())
418 {
419 const MSSAPHISVFGNode* node = worklist.pop();
420
422 if (checkSelfCycleEdges(node))
423 continue;
424
425 if (node->hasOutgoingEdge() && node->hasIncomingEdge())
426 bypassMSSAPHINode(node);
427
429 if (node->hasIncomingEdge() && node->hasOutgoingEdge() == false)
430 {
434 for (; edgeIt != edgeEit; ++edgeIt)
435 addIntoWorklist((*edgeIt)->getSrcNode());
436
437 removeInEdges(node);
438 }
439 else if (node->hasOutgoingEdge() && node->hasIncomingEdge() == false)
440 {
444 for (; edgeIt != edgeEit; ++edgeIt)
445 addIntoWorklist((*edgeIt)->getDstNode());
446
447 removeOutEdges(node);
448 }
449
451 if (node->hasIncomingEdge() == false && node->hasOutgoingEdge() == false)
452 removeSVFGNode(const_cast<MSSAPHISVFGNode*>(node));
453 }
454}
455
456
463{
464 bool hasSelfCycle = false;
465
469 for (; inEdgeIt != inEdgeEit; ++inEdgeIt)
470 {
472
473 if (preEdge->getSrcID() == preEdge->getDstID())
474 {
476 {
477 hasSelfCycle = true;
478 break;
479 }
480 else if (keepContextSelfCycle &&
481 SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(preEdge))
482 {
483 hasSelfCycle = true;
484 continue;
485 }
486 else
487 {
488 assert(SVFUtil::isa<IndirectSVFGEdge>(preEdge) && "can only remove indirect SVFG edge");
490 }
491 }
492 }
493
494 return hasSelfCycle;
495}
496
501{
504 for (; inEdgeIt != inEdgeEit; ++inEdgeIt)
505 {
506 const SVFGEdge* preEdge = *inEdgeIt;
507 const SVFGNode* srcNode = preEdge->getSrcNode();
508
509 bool added = false;
513 for (; outEdgeIt != outEdgeEit; ++outEdgeIt)
514 {
515 const SVFGEdge* succEdge = *outEdgeIt;
516 const SVFGNode* dstNode = (*outEdgeIt)->getDstNode();
517 if (srcNode->getId() != dstNode->getId()
518 && addNewSVFGEdge(srcNode->getId(), dstNode->getId(), preEdge, succEdge))
519 added = true;
520 else
521 {
525 }
526 }
527
528 if (added == false)
529 {
533 }
534 }
535
536 removeAllEdges(node);
537}
538
544{
545 assert(SVFUtil::isa<IndirectSVFGEdge>(preEdge) && SVFUtil::isa<IndirectSVFGEdge>(succEdge)
546 && "either pre or succ edge is not indirect SVFG edge");
547
548 const IndirectSVFGEdge* preIndEdge = SVFUtil::cast<IndirectSVFGEdge>(preEdge);
549 const IndirectSVFGEdge* succIndEdge = SVFUtil::cast<IndirectSVFGEdge>(succEdge);
550
551 NodeBS intersection = preIndEdge->getPointsTo();
552 intersection &= succIndEdge->getPointsTo();
553
554 if (intersection.empty())
555 return false;
556
557 assert(bothInterEdges(preEdge, succEdge) == false && "both edges are inter edges");
558
559 if (const CallIndSVFGEdge* preCallEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(preEdge))
560 {
561 return addCallIndirectSVFGEdge(srcId, dstId, preCallEdge->getCallSiteId(), intersection);
562 }
563 else if (const CallIndSVFGEdge* succCallEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(succEdge))
564 {
565 return addCallIndirectSVFGEdge(srcId, dstId, succCallEdge->getCallSiteId(), intersection);
566 }
567 else if (const RetIndSVFGEdge* preRetEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(preEdge))
568 {
569 return addRetIndirectSVFGEdge(srcId, dstId, preRetEdge->getCallSiteId(), intersection);
570 }
571 else if (const RetIndSVFGEdge* succRetEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(succEdge))
572 {
573 return addRetIndirectSVFGEdge(srcId, dstId, succRetEdge->getCallSiteId(), intersection);
574 }
575 else
576 {
578 }
579
580 return false;
581}
static std::string KeepNoneSelfCycle
Definition SVFGOPT.cpp:44
static std::string KeepContextSelfCycle
Definition SVFGOPT.cpp:43
static std::string KeepAllSelfCycle
Definition SVFGOPT.cpp:42
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:498
#define DGENERAL
Definition SVFType.h:504
const PAGNode * getParam() const
Return parameter.
Definition VFGNode.h:909
const CallICFGNode * getCallSite() const
Return callsite.
Definition VFGNode.h:903
bool empty() const
Definition WorkList.h:146
iterator begin()
Iterators.
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
iterator OutEdgeEnd()
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:76
static const Option< bool > KeepAOFI
Definition Options.h:108
static const Option< std::string > SelfCycle
Definition Options.h:109
static const Option< bool > DumpVFG
Definition Options.h:112
static const Option< bool > ContextInsensitive
Definition Options.h:107
Set< SVFGNode * > SVFGNodeSet
Definition SVFGOPT.h:58
bool isDefOfAInFOut(const SVFGNode *node)
Definition SVFGOPT.h:295
SVFGEdge * addCallIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add inter-procedural value flow edge.
Definition SVFGOPT.cpp:88
void buildAndWriteSVFG(const std::string &filename)
Optimised SVFG's shouldn't be written in their optimised form; writes the full SVFG to file before op...
Definition SVFGOPT.cpp:54
void replaceFParamARetWithPHI(PHISVFGNode *phi, SVFGNode *svfgNode)
Replace FormalParam/ActualRet node with PHI node.
Definition SVFGOPT.cpp:171
void handleIntraValueFlow()
Remove MSSAPHI SVFG nodes.
Definition SVFGOPT.cpp:411
void retargetEdgesOfAOutFIn(SVFGNode *node)
Connect actual-out/formal-in's predecessors to their successors directly.
Definition SVFGOPT.cpp:270
void addInterPHIOperands(PHISVFGNode *phi, const PAGNode *operand)
Definition SVFGOPT.h:247
void setFormalOUTDef(NodeID fo, NodeID def)
Definition SVFGOPT.h:286
void setActualINDef(NodeID ai, NodeID def)
Definition SVFGOPT.h:279
void handleInterValueFlow()
Definition SVFGOPT.cpp:110
void bypassMSSAPHINode(const MSSAPHISVFGNode *node)
Remove MSSAPHI node if possible.
Definition SVFGOPT.cpp:500
void removeInEdges(const SVFGNode *node)
Definition SVFGOPT.h:345
bool keepAllSelfCycle
Definition SVFGOPT.h:366
bool addNewSVFGEdge(NodeID srcId, NodeID dstId, const SVFGEdge *preEdge, const SVFGEdge *succEdge)
Add new SVFG edge from src to dst.
Definition SVFGOPT.cpp:543
bool bothInterEdges(const SVFGEdge *edge1, const SVFGEdge *edge2) const
Return TRUE if both edges are indirect call/ret edges.
Definition SVFGOPT.h:240
bool formalInOfAddressTakenFunc(const FormalINSVFGNode *fi) const
Check if formal-in/formal-out reside in address-taken function.
Definition SVFGOPT.h:314
bool addIntoWorklist(const SVFGNode *node)
Definition SVFGOPT.h:220
void buildSVFG() override
Start building SVFG.
Definition SVFGOPT.cpp:61
bool actualOutOfIndCS(const ActualOUTSVFGNode *ao) const
Definition SVFGOPT.h:306
bool keepActualOutFormalIn
Definition SVFGOPT.h:365
InterPHISVFGNode * addInterPHIForAR(const ActualRetSVFGNode *ar)
Add inter PHI SVFG node for actual return.
Definition SVFGOPT.h:261
bool formalOutOfAddressTakenFunc(const FormalOUTSVFGNode *fo) const
Definition SVFGOPT.h:318
WorkList worklist
storing MSSAPHI nodes which may be removed.
Definition SVFGOPT.h:363
InterPHISVFGNode * addInterPHIForFP(const FormalParmSVFGNode *fp)
Add inter PHI SVFG node for formal parameter.
Definition SVFGOPT.h:253
bool isConnectingTwoCallSites(const SVFGNode *node) const
Return TRUE if this node has both incoming call/ret and outgoing call/ret edges.
Definition SVFGOPT.cpp:312
void readAndOptSVFG(const std::string &filename)
Optimised SVFG's aren't written in their optimised form; read full SVFG and optimise it.
Definition SVFGOPT.cpp:47
bool canBeRemoved(const SVFGNode *node)
Definition SVFGOPT.cpp:354
void retargetEdgesOfAInFOut(SVFGNode *node)
Retarget edges related to actual-in/-out and formal-in/-out.
Definition SVFGOPT.cpp:224
void removeAllEdges(const SVFGNode *node)
Remove edges of a SVFG node.
Definition SVFGOPT.h:340
void parseSelfCycleHandleOption()
Definition SVFGOPT.cpp:392
bool keepContextSelfCycle
Definition SVFGOPT.h:367
void optimiseSVFG()
Separate optimisation function to avoid duplicate code.
Definition SVFGOPT.cpp:68
void initialWorkList()
Initial work list with MSSAPHI nodes which may be removed.
Definition SVFGOPT.h:211
void removeOutEdges(const SVFGNode *node)
Definition SVFGOPT.h:351
bool actualInOfIndCS(const ActualINSVFGNode *ai) const
Check if actual-in/actual-out exist at indirect call site.
Definition SVFGOPT.h:302
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:99
bool checkSelfCycleEdges(const MSSAPHISVFGNode *node)
Remove self cycle edges if needed. Return TRUE if some self cycle edges remained.
Definition SVFGOPT.cpp:462
void sfvgOptEnd()
Definition SVFGStat.h:154
void sfvgOptStart()
Definition SVFGStat.h:149
virtual void buildSVFG()
Start building SVFG.
Definition SVFG.cpp:228
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition SVFG.cpp:576
void removeSVFGNode(SVFGNode *node)
Remove a SVFGNode.
Definition SVFG.h:243
virtual void writeToFile(const std::string &filename)
SVFGEdge * addRetIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts, CallSiteID csId)
Definition SVFG.cpp:525
void removeSVFGEdge(SVFGEdge *edge)
Remove a SVFG edge.
Definition SVFG.h:238
virtual void readFile(const std::string &filename)
NodeID getDef(const PAGNode *pagNode) const
Definition SVFG.h:356
SVFGEdge * addIntraIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts)
Add indirect def-use edges of a memory region between two statements,.
Definition SVFG.cpp:463
SVFGStat * stat
Definition SVFG.h:105
SVFGEdge * addCallIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts, CallSiteID csId)
Definition SVFG.cpp:505
NodeID getId() const
Get ID.
Definition SVFValue.h:158
VFGEdgeSetTy SVFGEdgeSetTy
Definition VFGEdge.h:118
VFGEdge::VFGEdgeSetTy::const_iterator const_iterator
Definition VFGNode.h:55
VFGEdge::VFGEdgeSetTy::iterator iterator
Definition VFGNode.h:54
VFGEdge * addRetEdge(NodeID srcId, NodeID dstId, CallSiteID csId)
Definition VFG.cpp:705
CallSiteID getCallSiteID(const CallICFGNode *cs, const FunObjVar *func) const
Get callsite given a callsiteID.
Definition VFG.h:178
VFGEdge * addIntraDirectVFEdge(NodeID srcId, NodeID dstId)
Definition VFG.cpp:659
VFGEdge * addCallEdge(NodeID srcId, NodeID dstId, CallSiteID csId)
Definition VFG.cpp:685
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:101
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:68
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
u32_t NodeID
Definition GeneralType.h:56
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74