Static Value-Flow Analysis
Loading...
Searching...
No Matches
PreAnalysis.cpp
Go to the documentation of this file.
1//===- PreAnalysis.cpp -- Pre-Analysis 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 * PreAnalysis.cpp
25 *
26 * Created on: Feb 25, 2026
27 * Author: Jiawei Wang
28 */
29
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{
101 return;
102
103 // Step 1: Collect all cycles in top-down order using a stack-based DFS,
104 // then reverse to get bottom-up order (inner cycles before outer ones).
105 std::vector<const ICFGCycleWTO*> cycles;
106 {
107 std::vector<const ICFGWTOComp*> stack;
108 for (const auto& kv : funcToWTO)
109 {
110 if (!kv.second) continue;
111 for (const ICFGWTOComp* comp : kv.second->getWTOComponents())
112 stack.push_back(comp);
113 }
114 while (!stack.empty())
115 {
116 const ICFGWTOComp* comp = stack.back();
117 stack.pop_back();
118 if (const ICFGCycleWTO* cycle = SVFUtil::dyn_cast<ICFGCycleWTO>(comp))
119 {
120 for (const ICFGWTOComp* sub : cycle->getWTOComponents())
121 stack.push_back(sub);
122 cycles.push_back(cycle);
123 }
124 }
125 std::reverse(cycles.begin(), cycles.end());
126 }
127
128 // Step 2: Build ValVar sets bottom-up. Inner cycles are already in the
129 // map when we reach their enclosing cycle.
130 for (const ICFGCycleWTO* cycle : cycles)
131 {
133
134 // Gather every ICFG node in this cycle (head + body singletons).
135 // For nested sub-cycles, merge their already-computed sets instead.
136 std::vector<const ICFGNode*> nodes;
137 nodes.push_back(cycle->head()->getICFGNode());
138 for (const ICFGWTOComp* comp : cycle->getWTOComponents())
139 {
140 if (const ICFGSingletonWTO* s = SVFUtil::dyn_cast<ICFGSingletonWTO>(comp))
141 nodes.push_back(s->getICFGNode());
142 else if (const ICFGCycleWTO* sub = SVFUtil::dyn_cast<ICFGCycleWTO>(comp))
143 out.insert(cycleToValVars[sub].begin(), cycleToValVars[sub].end());
144 }
145
146 // For each node, collect LHS ValVar IDs from its statements.
147 for (const ICFGNode* node : nodes)
148 {
149 for (const SVFStmt* stmt : node->getSVFStmts())
150 {
151 const ValVar* lhs = nullptr;
152 if (const AssignStmt* a = SVFUtil::dyn_cast<AssignStmt>(stmt))
153 lhs = SVFUtil::dyn_cast<ValVar>(a->getLHSVar());
154 else if (const MultiOpndStmt* m = SVFUtil::dyn_cast<MultiOpndStmt>(stmt))
155 lhs = m->getRes();
156 if (lhs)
157 out.insert(lhs);
158 }
159 // FunEntryICFGNode owns ArgValVars (formal parameters) that have
160 // no defining stmt at the entry — the CallPE lives on the caller
161 // side. For recursive cycles whose head is a FunEntry, we need
162 // these IDs so widening/narrowing observes them across iterations.
163 if (const FunEntryICFGNode* fe = SVFUtil::dyn_cast<FunEntryICFGNode>(node))
164 {
165 for (const SVFVar* fp : fe->getFormalParms())
166 if (const ValVar* v = SVFUtil::dyn_cast<ValVar>(fp))
167 out.insert(v);
168 }
169 }
170 }
171}
cJSON * a
Definition cJSON.cpp:2560
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
static const OptionMap< u32_t > AESparsity
Definition Options.h:243
CallGraph * getCallGraph() const
Return call graph.
CallGraphSCC * getCallGraphSCC() const
Return call graph SCC.
Map< const FunObjVar *, const ICFGWTO * > funcToWTO
Definition PreAnalysis.h:96
Map< const ICFGCycleWTO *, Set< const ValVar * > > cycleToValVars
CallGraphSCC * callGraphSCC
Definition PreAnalysis.h:94
AndersenWaveDiff * pta
Definition PreAnalysis.h:92
virtual ~PreAnalysis()
CallGraph * callGraph
Definition PreAnalysis.h:93
void initWTO()
Build WTO for each function using call graph SCC.
PreAnalysis(SVFIR *pag, ICFG *icfg)
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