Static Value-Flow Analysis
Loading...
Searching...
No Matches
AEWTO.cpp
Go to the documentation of this file.
1//===- AEWTO.cpp -- WTO + pointer-analysis prep for Abstract Interpretation ---//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-> <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 * AEWTO.cpp
25 *
26 * Created on: Feb 25, 2026
27 * Author: Jiawei Wang
28 */
29
30#include "AE/Svfexe/AEWTO.h"
32#include "Util/Options.h"
33#include "Util/WorkList.h"
34
35using namespace SVF;
36
38 : svfir(pag), icfg(icfg), pta(nullptr), callGraph(nullptr), callGraphSCC(nullptr)
39{
43}
44
46{
47 for (auto& [func, wto] : funcToWTO)
48 delete wto;
49}
50
52{
53 callGraphSCC->find();
54
55 for (auto it = callGraph->begin(); it != callGraph->end(); it++)
56 {
57 const FunObjVar *fun = it->second->getFunction();
58 if (fun->isDeclaration())
59 continue;
60
61 NodeID repNodeId = callGraphSCC->repNode(it->second->getId());
62 auto cgSCCNodes = callGraphSCC->subNodes(repNodeId);
63
64 bool isEntry = false;
65 if (it->second->getInEdges().empty())
66 isEntry = true;
67 for (auto inEdge: it->second->getInEdges())
68 {
69 NodeID srcNodeId = inEdge->getSrcID();
70 if (!cgSCCNodes.test(srcNodeId))
71 isEntry = true;
72 }
73
74 if (isEntry)
75 {
77 for (const auto& node: cgSCCNodes)
78 {
79 funcScc.insert(callGraph->getGNode(node)->getFunction());
80 }
82 iwto->init();
83 funcToWTO[it->second->getFunction()] = iwto;
84 }
85 }
86
87}
88
89// ---------------------------------------------------------------------------
90// Semi-sparse cycle ValVar set precomputation
91// ---------------------------------------------------------------------------
92//
93// In semi-sparse mode, ValVars live at their def-sites and do not flow
94// through the cycle-head merge. handleLoopOrRecursion uses the cycle's
95// ValVar set to gather/scatter ValVars around each widening iteration.
96// We precompute the set once per cycle here so the main loop does no work.
97
99{
100 // Step 1: Collect all cycles in top-down order using a stack-based DFS,
101 // then reverse to get bottom-up order (inner cycles before outer ones).
102 std::vector<const ICFGCycleWTO*> cycles;
103 {
104 std::vector<const ICFGWTOComp*> stack;
105 for (const auto& kv : funcToWTO)
106 {
107 if (!kv.second) continue;
108 for (const ICFGWTOComp* comp : kv.second->getWTOComponents())
109 stack.push_back(comp);
110 }
111 while (!stack.empty())
112 {
113 const ICFGWTOComp* comp = stack.back();
114 stack.pop_back();
115 if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(comp))
116 {
117 for (const ICFGWTOComp* sub : cycle->getWTOComponents())
118 stack.push_back(sub);
119 cycles.push_back(cycle);
120 }
121 }
122 std::reverse(cycles.begin(), cycles.end());
123 }
124
125 // Step 2: Build ValVar sets bottom-up. Inner cycles are already in the
126 // map when we reach their enclosing cycle.
127 for (const ICFGCycleWTO* cycle : cycles)
128 {
130
131 // Gather every ICFG node in this cycle (head + body singletons).
132 // For nested sub-cycles, merge their already-computed sets instead.
133 std::vector<const ICFGNode*> nodes;
134 nodes.push_back(cycle->head()->getICFGNode());
135 for (const ICFGWTOComp* comp : cycle->getWTOComponents())
136 {
137 if (const ICFGSingletonWTO* s = SVFUtil::dyn_cast<ICFGSingletonWTO>(comp))
138 nodes.push_back(s->getICFGNode());
139 else if (const ICFGCycleWTO* sub = SVFUtil::dyn_cast<ICFGCycleWTO>(comp))
140 out.insert(cycleToValVars[sub].begin(), cycleToValVars[sub].end());
141 }
142
143 // For each node, collect LHS ValVar IDs from its statements.
144 for (const ICFGNode* node : nodes)
145 {
146 for (const SVFStmt* stmt : node->getSVFStmts())
147 {
148 const ValVar* lhs = nullptr;
149 if (const AssignStmt* a = SVFUtil::dyn_cast<AssignStmt>(stmt))
150 lhs = SVFUtil::dyn_cast<ValVar>(a->getLHSVar());
151 else if (const MultiOpndStmt* m = SVFUtil::dyn_cast<MultiOpndStmt>(stmt))
152 lhs = m->getRes();
153 if (lhs)
154 out.insert(lhs);
155 }
156 // FunEntryICFGNode owns ArgValVars (formal parameters) that have
157 // no defining stmt at the entry — the CallPE lives on the caller
158 // side. For recursive cycles whose head is a FunEntry, we need
159 // these IDs so widening/narrowing observes them across iterations.
160 if (const FunEntryICFGNode* fe = SVFUtil::dyn_cast<FunEntryICFGNode>(node))
161 {
162 for (const SVFVar* fp : fe->getFormalParms())
163 if (const ValVar* v = SVFUtil::dyn_cast<ValVar>(fp))
164 out.insert(v);
165 }
166 }
167 }
168}
cJSON * a
Definition cJSON.cpp:2560
ICFG * icfg
Definition AEWTO.h:91
AEWTO(SVFIR *pag, ICFG *icfg)
Definition AEWTO.cpp:37
void initCycleValVars()
Definition AEWTO.cpp:98
SVFIR * svfir
Definition AEWTO.h:90
AndersenWaveDiff * pta
Definition AEWTO.h:92
virtual ~AEWTO()
Definition AEWTO.cpp:45
CallGraph * callGraph
Definition AEWTO.h:93
Map< const ICFGCycleWTO *, Set< const ValVar * > > cycleToValVars
Definition AEWTO.h:101
CallGraphSCC * callGraphSCC
Definition AEWTO.h:94
Map< const FunObjVar *, const ICFGWTO * > funcToWTO
Definition AEWTO.h:96
void initWTO()
Build WTO for each function using call graph SCC.
Definition AEWTO.cpp:51
static AndersenWaveDiff * createAndersenWaveDiff(SVFIR *_pag)
Create an singleton instance directly instead of invoking llvm pass manager.
Definition Andersen.h:407
virtual const FunObjVar * getFunction() const
Get containing function, or null for globals/constants.
bool isDeclaration() const
iterator begin()
Iterators.
NodeType * getGNode(NodeID id) const
Get a node.
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:242
CallGraph * getCallGraph() const
Return call graph.
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
for isBitcode
Definition BasicTypes.h:70
u32_t NodeID
Definition GeneralType.h:56
WTONode< ICFG > ICFGSingletonWTO
Definition ICFGWTO.h:45
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
iter_range< typename GenericGraphTraits< GraphType >::nodes_iterator > nodes(const GraphType &G)
WTOComponent< ICFG > ICFGWTOComp
Definition ICFGWTO.h:44