1f4a2713aSLionel Sambuc //=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file implements Live Variables analysis for source-level CFGs.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc #include "clang/Analysis/Analyses/LiveVariables.h"
15f4a2713aSLionel Sambuc #include "clang/AST/Stmt.h"
16f4a2713aSLionel Sambuc #include "clang/AST/StmtVisitor.h"
17f4a2713aSLionel Sambuc #include "clang/Analysis/Analyses/PostOrderCFGView.h"
18f4a2713aSLionel Sambuc #include "clang/Analysis/AnalysisContext.h"
19f4a2713aSLionel Sambuc #include "clang/Analysis/CFG.h"
20f4a2713aSLionel Sambuc #include "llvm/ADT/DenseMap.h"
21f4a2713aSLionel Sambuc #include "llvm/ADT/PostOrderIterator.h"
22f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
23f4a2713aSLionel Sambuc #include <algorithm>
24f4a2713aSLionel Sambuc #include <vector>
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambuc using namespace clang;
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc namespace {
29f4a2713aSLionel Sambuc
30f4a2713aSLionel Sambuc class DataflowWorklist {
31f4a2713aSLionel Sambuc SmallVector<const CFGBlock *, 20> worklist;
32f4a2713aSLionel Sambuc llvm::BitVector enqueuedBlocks;
33f4a2713aSLionel Sambuc PostOrderCFGView *POV;
34f4a2713aSLionel Sambuc public:
DataflowWorklist(const CFG & cfg,AnalysisDeclContext & Ctx)35f4a2713aSLionel Sambuc DataflowWorklist(const CFG &cfg, AnalysisDeclContext &Ctx)
36f4a2713aSLionel Sambuc : enqueuedBlocks(cfg.getNumBlockIDs()),
37f4a2713aSLionel Sambuc POV(Ctx.getAnalysis<PostOrderCFGView>()) {}
38f4a2713aSLionel Sambuc
39f4a2713aSLionel Sambuc void enqueueBlock(const CFGBlock *block);
40f4a2713aSLionel Sambuc void enqueuePredecessors(const CFGBlock *block);
41f4a2713aSLionel Sambuc
42f4a2713aSLionel Sambuc const CFGBlock *dequeue();
43f4a2713aSLionel Sambuc
44f4a2713aSLionel Sambuc void sortWorklist();
45f4a2713aSLionel Sambuc };
46f4a2713aSLionel Sambuc
47f4a2713aSLionel Sambuc }
48f4a2713aSLionel Sambuc
enqueueBlock(const clang::CFGBlock * block)49f4a2713aSLionel Sambuc void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) {
50f4a2713aSLionel Sambuc if (block && !enqueuedBlocks[block->getBlockID()]) {
51f4a2713aSLionel Sambuc enqueuedBlocks[block->getBlockID()] = true;
52f4a2713aSLionel Sambuc worklist.push_back(block);
53f4a2713aSLionel Sambuc }
54f4a2713aSLionel Sambuc }
55f4a2713aSLionel Sambuc
enqueuePredecessors(const clang::CFGBlock * block)56f4a2713aSLionel Sambuc void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) {
57f4a2713aSLionel Sambuc const unsigned OldWorklistSize = worklist.size();
58f4a2713aSLionel Sambuc for (CFGBlock::const_pred_iterator I = block->pred_begin(),
59f4a2713aSLionel Sambuc E = block->pred_end(); I != E; ++I) {
60f4a2713aSLionel Sambuc enqueueBlock(*I);
61f4a2713aSLionel Sambuc }
62f4a2713aSLionel Sambuc
63f4a2713aSLionel Sambuc if (OldWorklistSize == 0 || OldWorklistSize == worklist.size())
64f4a2713aSLionel Sambuc return;
65f4a2713aSLionel Sambuc
66f4a2713aSLionel Sambuc sortWorklist();
67f4a2713aSLionel Sambuc }
68f4a2713aSLionel Sambuc
sortWorklist()69f4a2713aSLionel Sambuc void DataflowWorklist::sortWorklist() {
70f4a2713aSLionel Sambuc std::sort(worklist.begin(), worklist.end(), POV->getComparator());
71f4a2713aSLionel Sambuc }
72f4a2713aSLionel Sambuc
dequeue()73f4a2713aSLionel Sambuc const CFGBlock *DataflowWorklist::dequeue() {
74f4a2713aSLionel Sambuc if (worklist.empty())
75*0a6a1f1dSLionel Sambuc return nullptr;
76f4a2713aSLionel Sambuc const CFGBlock *b = worklist.pop_back_val();
77f4a2713aSLionel Sambuc enqueuedBlocks[b->getBlockID()] = false;
78f4a2713aSLionel Sambuc return b;
79f4a2713aSLionel Sambuc }
80f4a2713aSLionel Sambuc
81f4a2713aSLionel Sambuc namespace {
82f4a2713aSLionel Sambuc class LiveVariablesImpl {
83f4a2713aSLionel Sambuc public:
84f4a2713aSLionel Sambuc AnalysisDeclContext &analysisContext;
85f4a2713aSLionel Sambuc llvm::ImmutableSet<const Stmt *>::Factory SSetFact;
86f4a2713aSLionel Sambuc llvm::ImmutableSet<const VarDecl *>::Factory DSetFact;
87f4a2713aSLionel Sambuc llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness;
88f4a2713aSLionel Sambuc llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness;
89f4a2713aSLionel Sambuc llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness;
90f4a2713aSLionel Sambuc llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment;
91f4a2713aSLionel Sambuc const bool killAtAssign;
92f4a2713aSLionel Sambuc
93f4a2713aSLionel Sambuc LiveVariables::LivenessValues
94f4a2713aSLionel Sambuc merge(LiveVariables::LivenessValues valsA,
95f4a2713aSLionel Sambuc LiveVariables::LivenessValues valsB);
96f4a2713aSLionel Sambuc
97*0a6a1f1dSLionel Sambuc LiveVariables::LivenessValues
98*0a6a1f1dSLionel Sambuc runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val,
99*0a6a1f1dSLionel Sambuc LiveVariables::Observer *obs = nullptr);
100f4a2713aSLionel Sambuc
101f4a2713aSLionel Sambuc void dumpBlockLiveness(const SourceManager& M);
102f4a2713aSLionel Sambuc
LiveVariablesImpl(AnalysisDeclContext & ac,bool KillAtAssign)103f4a2713aSLionel Sambuc LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign)
104f4a2713aSLionel Sambuc : analysisContext(ac),
105f4a2713aSLionel Sambuc SSetFact(false), // Do not canonicalize ImmutableSets by default.
106f4a2713aSLionel Sambuc DSetFact(false), // This is a *major* performance win.
107f4a2713aSLionel Sambuc killAtAssign(KillAtAssign) {}
108f4a2713aSLionel Sambuc };
109f4a2713aSLionel Sambuc }
110f4a2713aSLionel Sambuc
getImpl(void * x)111f4a2713aSLionel Sambuc static LiveVariablesImpl &getImpl(void *x) {
112f4a2713aSLionel Sambuc return *((LiveVariablesImpl *) x);
113f4a2713aSLionel Sambuc }
114f4a2713aSLionel Sambuc
115f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
116f4a2713aSLionel Sambuc // Operations and queries on LivenessValues.
117f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
118f4a2713aSLionel Sambuc
isLive(const Stmt * S) const119f4a2713aSLionel Sambuc bool LiveVariables::LivenessValues::isLive(const Stmt *S) const {
120f4a2713aSLionel Sambuc return liveStmts.contains(S);
121f4a2713aSLionel Sambuc }
122f4a2713aSLionel Sambuc
isLive(const VarDecl * D) const123f4a2713aSLionel Sambuc bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const {
124f4a2713aSLionel Sambuc return liveDecls.contains(D);
125f4a2713aSLionel Sambuc }
126f4a2713aSLionel Sambuc
127f4a2713aSLionel Sambuc namespace {
128f4a2713aSLionel Sambuc template <typename SET>
mergeSets(SET A,SET B)129f4a2713aSLionel Sambuc SET mergeSets(SET A, SET B) {
130f4a2713aSLionel Sambuc if (A.isEmpty())
131f4a2713aSLionel Sambuc return B;
132f4a2713aSLionel Sambuc
133f4a2713aSLionel Sambuc for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) {
134f4a2713aSLionel Sambuc A = A.add(*it);
135f4a2713aSLionel Sambuc }
136f4a2713aSLionel Sambuc return A;
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc }
139f4a2713aSLionel Sambuc
anchor()140f4a2713aSLionel Sambuc void LiveVariables::Observer::anchor() { }
141f4a2713aSLionel Sambuc
142f4a2713aSLionel Sambuc LiveVariables::LivenessValues
merge(LiveVariables::LivenessValues valsA,LiveVariables::LivenessValues valsB)143f4a2713aSLionel Sambuc LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA,
144f4a2713aSLionel Sambuc LiveVariables::LivenessValues valsB) {
145f4a2713aSLionel Sambuc
146f4a2713aSLionel Sambuc llvm::ImmutableSetRef<const Stmt *>
147f4a2713aSLionel Sambuc SSetRefA(valsA.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()),
148f4a2713aSLionel Sambuc SSetRefB(valsB.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory());
149f4a2713aSLionel Sambuc
150f4a2713aSLionel Sambuc
151f4a2713aSLionel Sambuc llvm::ImmutableSetRef<const VarDecl *>
152f4a2713aSLionel Sambuc DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()),
153f4a2713aSLionel Sambuc DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory());
154f4a2713aSLionel Sambuc
155f4a2713aSLionel Sambuc
156f4a2713aSLionel Sambuc SSetRefA = mergeSets(SSetRefA, SSetRefB);
157f4a2713aSLionel Sambuc DSetRefA = mergeSets(DSetRefA, DSetRefB);
158f4a2713aSLionel Sambuc
159f4a2713aSLionel Sambuc // asImmutableSet() canonicalizes the tree, allowing us to do an easy
160f4a2713aSLionel Sambuc // comparison afterwards.
161f4a2713aSLionel Sambuc return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(),
162f4a2713aSLionel Sambuc DSetRefA.asImmutableSet());
163f4a2713aSLionel Sambuc }
164f4a2713aSLionel Sambuc
equals(const LivenessValues & V) const165f4a2713aSLionel Sambuc bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const {
166f4a2713aSLionel Sambuc return liveStmts == V.liveStmts && liveDecls == V.liveDecls;
167f4a2713aSLionel Sambuc }
168f4a2713aSLionel Sambuc
169f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
170f4a2713aSLionel Sambuc // Query methods.
171f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
172f4a2713aSLionel Sambuc
isAlwaysAlive(const VarDecl * D)173f4a2713aSLionel Sambuc static bool isAlwaysAlive(const VarDecl *D) {
174f4a2713aSLionel Sambuc return D->hasGlobalStorage();
175f4a2713aSLionel Sambuc }
176f4a2713aSLionel Sambuc
isLive(const CFGBlock * B,const VarDecl * D)177f4a2713aSLionel Sambuc bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) {
178f4a2713aSLionel Sambuc return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D);
179f4a2713aSLionel Sambuc }
180f4a2713aSLionel Sambuc
isLive(const Stmt * S,const VarDecl * D)181f4a2713aSLionel Sambuc bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) {
182f4a2713aSLionel Sambuc return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D);
183f4a2713aSLionel Sambuc }
184f4a2713aSLionel Sambuc
isLive(const Stmt * Loc,const Stmt * S)185f4a2713aSLionel Sambuc bool LiveVariables::isLive(const Stmt *Loc, const Stmt *S) {
186f4a2713aSLionel Sambuc return getImpl(impl).stmtsToLiveness[Loc].isLive(S);
187f4a2713aSLionel Sambuc }
188f4a2713aSLionel Sambuc
189f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
190f4a2713aSLionel Sambuc // Dataflow computation.
191f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
192f4a2713aSLionel Sambuc
193f4a2713aSLionel Sambuc namespace {
194f4a2713aSLionel Sambuc class TransferFunctions : public StmtVisitor<TransferFunctions> {
195f4a2713aSLionel Sambuc LiveVariablesImpl &LV;
196f4a2713aSLionel Sambuc LiveVariables::LivenessValues &val;
197f4a2713aSLionel Sambuc LiveVariables::Observer *observer;
198f4a2713aSLionel Sambuc const CFGBlock *currentBlock;
199f4a2713aSLionel Sambuc public:
TransferFunctions(LiveVariablesImpl & im,LiveVariables::LivenessValues & Val,LiveVariables::Observer * Observer,const CFGBlock * CurrentBlock)200f4a2713aSLionel Sambuc TransferFunctions(LiveVariablesImpl &im,
201f4a2713aSLionel Sambuc LiveVariables::LivenessValues &Val,
202f4a2713aSLionel Sambuc LiveVariables::Observer *Observer,
203f4a2713aSLionel Sambuc const CFGBlock *CurrentBlock)
204f4a2713aSLionel Sambuc : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {}
205f4a2713aSLionel Sambuc
206f4a2713aSLionel Sambuc void VisitBinaryOperator(BinaryOperator *BO);
207f4a2713aSLionel Sambuc void VisitBlockExpr(BlockExpr *BE);
208f4a2713aSLionel Sambuc void VisitDeclRefExpr(DeclRefExpr *DR);
209f4a2713aSLionel Sambuc void VisitDeclStmt(DeclStmt *DS);
210f4a2713aSLionel Sambuc void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS);
211f4a2713aSLionel Sambuc void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE);
212f4a2713aSLionel Sambuc void VisitUnaryOperator(UnaryOperator *UO);
213f4a2713aSLionel Sambuc void Visit(Stmt *S);
214f4a2713aSLionel Sambuc };
215f4a2713aSLionel Sambuc }
216f4a2713aSLionel Sambuc
FindVA(QualType Ty)217f4a2713aSLionel Sambuc static const VariableArrayType *FindVA(QualType Ty) {
218f4a2713aSLionel Sambuc const Type *ty = Ty.getTypePtr();
219f4a2713aSLionel Sambuc while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) {
220f4a2713aSLionel Sambuc if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT))
221f4a2713aSLionel Sambuc if (VAT->getSizeExpr())
222f4a2713aSLionel Sambuc return VAT;
223f4a2713aSLionel Sambuc
224f4a2713aSLionel Sambuc ty = VT->getElementType().getTypePtr();
225f4a2713aSLionel Sambuc }
226f4a2713aSLionel Sambuc
227*0a6a1f1dSLionel Sambuc return nullptr;
228f4a2713aSLionel Sambuc }
229f4a2713aSLionel Sambuc
LookThroughStmt(const Stmt * S)230f4a2713aSLionel Sambuc static const Stmt *LookThroughStmt(const Stmt *S) {
231f4a2713aSLionel Sambuc while (S) {
232f4a2713aSLionel Sambuc if (const Expr *Ex = dyn_cast<Expr>(S))
233f4a2713aSLionel Sambuc S = Ex->IgnoreParens();
234f4a2713aSLionel Sambuc if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) {
235f4a2713aSLionel Sambuc S = EWC->getSubExpr();
236f4a2713aSLionel Sambuc continue;
237f4a2713aSLionel Sambuc }
238f4a2713aSLionel Sambuc if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
239f4a2713aSLionel Sambuc S = OVE->getSourceExpr();
240f4a2713aSLionel Sambuc continue;
241f4a2713aSLionel Sambuc }
242f4a2713aSLionel Sambuc break;
243f4a2713aSLionel Sambuc }
244f4a2713aSLionel Sambuc return S;
245f4a2713aSLionel Sambuc }
246f4a2713aSLionel Sambuc
AddLiveStmt(llvm::ImmutableSet<const Stmt * > & Set,llvm::ImmutableSet<const Stmt * >::Factory & F,const Stmt * S)247f4a2713aSLionel Sambuc static void AddLiveStmt(llvm::ImmutableSet<const Stmt *> &Set,
248f4a2713aSLionel Sambuc llvm::ImmutableSet<const Stmt *>::Factory &F,
249f4a2713aSLionel Sambuc const Stmt *S) {
250f4a2713aSLionel Sambuc Set = F.add(Set, LookThroughStmt(S));
251f4a2713aSLionel Sambuc }
252f4a2713aSLionel Sambuc
Visit(Stmt * S)253f4a2713aSLionel Sambuc void TransferFunctions::Visit(Stmt *S) {
254f4a2713aSLionel Sambuc if (observer)
255f4a2713aSLionel Sambuc observer->observeStmt(S, currentBlock, val);
256f4a2713aSLionel Sambuc
257f4a2713aSLionel Sambuc StmtVisitor<TransferFunctions>::Visit(S);
258f4a2713aSLionel Sambuc
259f4a2713aSLionel Sambuc if (isa<Expr>(S)) {
260f4a2713aSLionel Sambuc val.liveStmts = LV.SSetFact.remove(val.liveStmts, S);
261f4a2713aSLionel Sambuc }
262f4a2713aSLionel Sambuc
263f4a2713aSLionel Sambuc // Mark all children expressions live.
264f4a2713aSLionel Sambuc
265f4a2713aSLionel Sambuc switch (S->getStmtClass()) {
266f4a2713aSLionel Sambuc default:
267f4a2713aSLionel Sambuc break;
268f4a2713aSLionel Sambuc case Stmt::StmtExprClass: {
269f4a2713aSLionel Sambuc // For statement expressions, look through the compound statement.
270f4a2713aSLionel Sambuc S = cast<StmtExpr>(S)->getSubStmt();
271f4a2713aSLionel Sambuc break;
272f4a2713aSLionel Sambuc }
273f4a2713aSLionel Sambuc case Stmt::CXXMemberCallExprClass: {
274f4a2713aSLionel Sambuc // Include the implicit "this" pointer as being live.
275f4a2713aSLionel Sambuc CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S);
276f4a2713aSLionel Sambuc if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) {
277f4a2713aSLionel Sambuc AddLiveStmt(val.liveStmts, LV.SSetFact, ImplicitObj);
278f4a2713aSLionel Sambuc }
279f4a2713aSLionel Sambuc break;
280f4a2713aSLionel Sambuc }
281f4a2713aSLionel Sambuc case Stmt::ObjCMessageExprClass: {
282f4a2713aSLionel Sambuc // In calls to super, include the implicit "self" pointer as being live.
283f4a2713aSLionel Sambuc ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S);
284f4a2713aSLionel Sambuc if (CE->getReceiverKind() == ObjCMessageExpr::SuperInstance)
285f4a2713aSLionel Sambuc val.liveDecls = LV.DSetFact.add(val.liveDecls,
286f4a2713aSLionel Sambuc LV.analysisContext.getSelfDecl());
287f4a2713aSLionel Sambuc break;
288f4a2713aSLionel Sambuc }
289f4a2713aSLionel Sambuc case Stmt::DeclStmtClass: {
290f4a2713aSLionel Sambuc const DeclStmt *DS = cast<DeclStmt>(S);
291f4a2713aSLionel Sambuc if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) {
292f4a2713aSLionel Sambuc for (const VariableArrayType* VA = FindVA(VD->getType());
293*0a6a1f1dSLionel Sambuc VA != nullptr; VA = FindVA(VA->getElementType())) {
294f4a2713aSLionel Sambuc AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr());
295f4a2713aSLionel Sambuc }
296f4a2713aSLionel Sambuc }
297f4a2713aSLionel Sambuc break;
298f4a2713aSLionel Sambuc }
299f4a2713aSLionel Sambuc case Stmt::PseudoObjectExprClass: {
300f4a2713aSLionel Sambuc // A pseudo-object operation only directly consumes its result
301f4a2713aSLionel Sambuc // expression.
302f4a2713aSLionel Sambuc Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr();
303f4a2713aSLionel Sambuc if (!child) return;
304f4a2713aSLionel Sambuc if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child))
305f4a2713aSLionel Sambuc child = OV->getSourceExpr();
306f4a2713aSLionel Sambuc child = child->IgnoreParens();
307f4a2713aSLionel Sambuc val.liveStmts = LV.SSetFact.add(val.liveStmts, child);
308f4a2713aSLionel Sambuc return;
309f4a2713aSLionel Sambuc }
310f4a2713aSLionel Sambuc
311f4a2713aSLionel Sambuc // FIXME: These cases eventually shouldn't be needed.
312f4a2713aSLionel Sambuc case Stmt::ExprWithCleanupsClass: {
313f4a2713aSLionel Sambuc S = cast<ExprWithCleanups>(S)->getSubExpr();
314f4a2713aSLionel Sambuc break;
315f4a2713aSLionel Sambuc }
316f4a2713aSLionel Sambuc case Stmt::CXXBindTemporaryExprClass: {
317f4a2713aSLionel Sambuc S = cast<CXXBindTemporaryExpr>(S)->getSubExpr();
318f4a2713aSLionel Sambuc break;
319f4a2713aSLionel Sambuc }
320f4a2713aSLionel Sambuc case Stmt::UnaryExprOrTypeTraitExprClass: {
321f4a2713aSLionel Sambuc // No need to unconditionally visit subexpressions.
322f4a2713aSLionel Sambuc return;
323f4a2713aSLionel Sambuc }
324f4a2713aSLionel Sambuc }
325f4a2713aSLionel Sambuc
326f4a2713aSLionel Sambuc for (Stmt::child_iterator it = S->child_begin(), ei = S->child_end();
327f4a2713aSLionel Sambuc it != ei; ++it) {
328f4a2713aSLionel Sambuc if (Stmt *child = *it)
329f4a2713aSLionel Sambuc AddLiveStmt(val.liveStmts, LV.SSetFact, child);
330f4a2713aSLionel Sambuc }
331f4a2713aSLionel Sambuc }
332f4a2713aSLionel Sambuc
VisitBinaryOperator(BinaryOperator * B)333f4a2713aSLionel Sambuc void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) {
334f4a2713aSLionel Sambuc if (B->isAssignmentOp()) {
335f4a2713aSLionel Sambuc if (!LV.killAtAssign)
336f4a2713aSLionel Sambuc return;
337f4a2713aSLionel Sambuc
338f4a2713aSLionel Sambuc // Assigning to a variable?
339f4a2713aSLionel Sambuc Expr *LHS = B->getLHS()->IgnoreParens();
340f4a2713aSLionel Sambuc
341f4a2713aSLionel Sambuc if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS))
342f4a2713aSLionel Sambuc if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
343f4a2713aSLionel Sambuc // Assignments to references don't kill the ref's address
344f4a2713aSLionel Sambuc if (VD->getType()->isReferenceType())
345f4a2713aSLionel Sambuc return;
346f4a2713aSLionel Sambuc
347f4a2713aSLionel Sambuc if (!isAlwaysAlive(VD)) {
348f4a2713aSLionel Sambuc // The variable is now dead.
349f4a2713aSLionel Sambuc val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
350f4a2713aSLionel Sambuc }
351f4a2713aSLionel Sambuc
352f4a2713aSLionel Sambuc if (observer)
353f4a2713aSLionel Sambuc observer->observerKill(DR);
354f4a2713aSLionel Sambuc }
355f4a2713aSLionel Sambuc }
356f4a2713aSLionel Sambuc }
357f4a2713aSLionel Sambuc
VisitBlockExpr(BlockExpr * BE)358f4a2713aSLionel Sambuc void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
359f4a2713aSLionel Sambuc AnalysisDeclContext::referenced_decls_iterator I, E;
360*0a6a1f1dSLionel Sambuc std::tie(I, E) =
361f4a2713aSLionel Sambuc LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl());
362f4a2713aSLionel Sambuc for ( ; I != E ; ++I) {
363f4a2713aSLionel Sambuc const VarDecl *VD = *I;
364f4a2713aSLionel Sambuc if (isAlwaysAlive(VD))
365f4a2713aSLionel Sambuc continue;
366f4a2713aSLionel Sambuc val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
367f4a2713aSLionel Sambuc }
368f4a2713aSLionel Sambuc }
369f4a2713aSLionel Sambuc
VisitDeclRefExpr(DeclRefExpr * DR)370f4a2713aSLionel Sambuc void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) {
371f4a2713aSLionel Sambuc if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl()))
372f4a2713aSLionel Sambuc if (!isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end())
373f4a2713aSLionel Sambuc val.liveDecls = LV.DSetFact.add(val.liveDecls, D);
374f4a2713aSLionel Sambuc }
375f4a2713aSLionel Sambuc
VisitDeclStmt(DeclStmt * DS)376f4a2713aSLionel Sambuc void TransferFunctions::VisitDeclStmt(DeclStmt *DS) {
377*0a6a1f1dSLionel Sambuc for (const auto *DI : DS->decls())
378*0a6a1f1dSLionel Sambuc if (const auto *VD = dyn_cast<VarDecl>(DI)) {
379f4a2713aSLionel Sambuc if (!isAlwaysAlive(VD))
380f4a2713aSLionel Sambuc val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
381f4a2713aSLionel Sambuc }
382f4a2713aSLionel Sambuc }
383f4a2713aSLionel Sambuc
VisitObjCForCollectionStmt(ObjCForCollectionStmt * OS)384f4a2713aSLionel Sambuc void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) {
385f4a2713aSLionel Sambuc // Kill the iteration variable.
386*0a6a1f1dSLionel Sambuc DeclRefExpr *DR = nullptr;
387*0a6a1f1dSLionel Sambuc const VarDecl *VD = nullptr;
388f4a2713aSLionel Sambuc
389f4a2713aSLionel Sambuc Stmt *element = OS->getElement();
390f4a2713aSLionel Sambuc if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) {
391f4a2713aSLionel Sambuc VD = cast<VarDecl>(DS->getSingleDecl());
392f4a2713aSLionel Sambuc }
393f4a2713aSLionel Sambuc else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) {
394f4a2713aSLionel Sambuc VD = cast<VarDecl>(DR->getDecl());
395f4a2713aSLionel Sambuc }
396f4a2713aSLionel Sambuc
397f4a2713aSLionel Sambuc if (VD) {
398f4a2713aSLionel Sambuc val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD);
399f4a2713aSLionel Sambuc if (observer && DR)
400f4a2713aSLionel Sambuc observer->observerKill(DR);
401f4a2713aSLionel Sambuc }
402f4a2713aSLionel Sambuc }
403f4a2713aSLionel Sambuc
404f4a2713aSLionel Sambuc void TransferFunctions::
VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr * UE)405f4a2713aSLionel Sambuc VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE)
406f4a2713aSLionel Sambuc {
407f4a2713aSLionel Sambuc // While sizeof(var) doesn't technically extend the liveness of 'var', it
408f4a2713aSLionel Sambuc // does extent the liveness of metadata if 'var' is a VariableArrayType.
409f4a2713aSLionel Sambuc // We handle that special case here.
410f4a2713aSLionel Sambuc if (UE->getKind() != UETT_SizeOf || UE->isArgumentType())
411f4a2713aSLionel Sambuc return;
412f4a2713aSLionel Sambuc
413f4a2713aSLionel Sambuc const Expr *subEx = UE->getArgumentExpr();
414f4a2713aSLionel Sambuc if (subEx->getType()->isVariableArrayType()) {
415f4a2713aSLionel Sambuc assert(subEx->isLValue());
416f4a2713aSLionel Sambuc val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->IgnoreParens());
417f4a2713aSLionel Sambuc }
418f4a2713aSLionel Sambuc }
419f4a2713aSLionel Sambuc
VisitUnaryOperator(UnaryOperator * UO)420f4a2713aSLionel Sambuc void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) {
421f4a2713aSLionel Sambuc // Treat ++/-- as a kill.
422f4a2713aSLionel Sambuc // Note we don't actually have to do anything if we don't have an observer,
423f4a2713aSLionel Sambuc // since a ++/-- acts as both a kill and a "use".
424f4a2713aSLionel Sambuc if (!observer)
425f4a2713aSLionel Sambuc return;
426f4a2713aSLionel Sambuc
427f4a2713aSLionel Sambuc switch (UO->getOpcode()) {
428f4a2713aSLionel Sambuc default:
429f4a2713aSLionel Sambuc return;
430f4a2713aSLionel Sambuc case UO_PostInc:
431f4a2713aSLionel Sambuc case UO_PostDec:
432f4a2713aSLionel Sambuc case UO_PreInc:
433f4a2713aSLionel Sambuc case UO_PreDec:
434f4a2713aSLionel Sambuc break;
435f4a2713aSLionel Sambuc }
436f4a2713aSLionel Sambuc
437f4a2713aSLionel Sambuc if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens()))
438f4a2713aSLionel Sambuc if (isa<VarDecl>(DR->getDecl())) {
439f4a2713aSLionel Sambuc // Treat ++/-- as a kill.
440f4a2713aSLionel Sambuc observer->observerKill(DR);
441f4a2713aSLionel Sambuc }
442f4a2713aSLionel Sambuc }
443f4a2713aSLionel Sambuc
444f4a2713aSLionel Sambuc LiveVariables::LivenessValues
runOnBlock(const CFGBlock * block,LiveVariables::LivenessValues val,LiveVariables::Observer * obs)445f4a2713aSLionel Sambuc LiveVariablesImpl::runOnBlock(const CFGBlock *block,
446f4a2713aSLionel Sambuc LiveVariables::LivenessValues val,
447f4a2713aSLionel Sambuc LiveVariables::Observer *obs) {
448f4a2713aSLionel Sambuc
449f4a2713aSLionel Sambuc TransferFunctions TF(*this, val, obs, block);
450f4a2713aSLionel Sambuc
451f4a2713aSLionel Sambuc // Visit the terminator (if any).
452f4a2713aSLionel Sambuc if (const Stmt *term = block->getTerminator())
453f4a2713aSLionel Sambuc TF.Visit(const_cast<Stmt*>(term));
454f4a2713aSLionel Sambuc
455f4a2713aSLionel Sambuc // Apply the transfer function for all Stmts in the block.
456f4a2713aSLionel Sambuc for (CFGBlock::const_reverse_iterator it = block->rbegin(),
457f4a2713aSLionel Sambuc ei = block->rend(); it != ei; ++it) {
458f4a2713aSLionel Sambuc const CFGElement &elem = *it;
459f4a2713aSLionel Sambuc
460f4a2713aSLionel Sambuc if (Optional<CFGAutomaticObjDtor> Dtor =
461f4a2713aSLionel Sambuc elem.getAs<CFGAutomaticObjDtor>()) {
462f4a2713aSLionel Sambuc val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl());
463f4a2713aSLionel Sambuc continue;
464f4a2713aSLionel Sambuc }
465f4a2713aSLionel Sambuc
466f4a2713aSLionel Sambuc if (!elem.getAs<CFGStmt>())
467f4a2713aSLionel Sambuc continue;
468f4a2713aSLionel Sambuc
469f4a2713aSLionel Sambuc const Stmt *S = elem.castAs<CFGStmt>().getStmt();
470f4a2713aSLionel Sambuc TF.Visit(const_cast<Stmt*>(S));
471f4a2713aSLionel Sambuc stmtsToLiveness[S] = val;
472f4a2713aSLionel Sambuc }
473f4a2713aSLionel Sambuc return val;
474f4a2713aSLionel Sambuc }
475f4a2713aSLionel Sambuc
runOnAllBlocks(LiveVariables::Observer & obs)476f4a2713aSLionel Sambuc void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) {
477f4a2713aSLionel Sambuc const CFG *cfg = getImpl(impl).analysisContext.getCFG();
478f4a2713aSLionel Sambuc for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it)
479f4a2713aSLionel Sambuc getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs);
480f4a2713aSLionel Sambuc }
481f4a2713aSLionel Sambuc
LiveVariables(void * im)482f4a2713aSLionel Sambuc LiveVariables::LiveVariables(void *im) : impl(im) {}
483f4a2713aSLionel Sambuc
~LiveVariables()484f4a2713aSLionel Sambuc LiveVariables::~LiveVariables() {
485f4a2713aSLionel Sambuc delete (LiveVariablesImpl*) impl;
486f4a2713aSLionel Sambuc }
487f4a2713aSLionel Sambuc
488f4a2713aSLionel Sambuc LiveVariables *
computeLiveness(AnalysisDeclContext & AC,bool killAtAssign)489f4a2713aSLionel Sambuc LiveVariables::computeLiveness(AnalysisDeclContext &AC,
490f4a2713aSLionel Sambuc bool killAtAssign) {
491f4a2713aSLionel Sambuc
492f4a2713aSLionel Sambuc // No CFG? Bail out.
493f4a2713aSLionel Sambuc CFG *cfg = AC.getCFG();
494f4a2713aSLionel Sambuc if (!cfg)
495*0a6a1f1dSLionel Sambuc return nullptr;
496f4a2713aSLionel Sambuc
497f4a2713aSLionel Sambuc // The analysis currently has scalability issues for very large CFGs.
498f4a2713aSLionel Sambuc // Bail out if it looks too large.
499f4a2713aSLionel Sambuc if (cfg->getNumBlockIDs() > 300000)
500*0a6a1f1dSLionel Sambuc return nullptr;
501f4a2713aSLionel Sambuc
502f4a2713aSLionel Sambuc LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign);
503f4a2713aSLionel Sambuc
504f4a2713aSLionel Sambuc // Construct the dataflow worklist. Enqueue the exit block as the
505f4a2713aSLionel Sambuc // start of the analysis.
506f4a2713aSLionel Sambuc DataflowWorklist worklist(*cfg, AC);
507f4a2713aSLionel Sambuc llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs());
508f4a2713aSLionel Sambuc
509f4a2713aSLionel Sambuc // FIXME: we should enqueue using post order.
510f4a2713aSLionel Sambuc for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) {
511f4a2713aSLionel Sambuc const CFGBlock *block = *it;
512f4a2713aSLionel Sambuc worklist.enqueueBlock(block);
513f4a2713aSLionel Sambuc
514f4a2713aSLionel Sambuc // FIXME: Scan for DeclRefExprs using in the LHS of an assignment.
515f4a2713aSLionel Sambuc // We need to do this because we lack context in the reverse analysis
516f4a2713aSLionel Sambuc // to determine if a DeclRefExpr appears in such a context, and thus
517f4a2713aSLionel Sambuc // doesn't constitute a "use".
518f4a2713aSLionel Sambuc if (killAtAssign)
519f4a2713aSLionel Sambuc for (CFGBlock::const_iterator bi = block->begin(), be = block->end();
520f4a2713aSLionel Sambuc bi != be; ++bi) {
521f4a2713aSLionel Sambuc if (Optional<CFGStmt> cs = bi->getAs<CFGStmt>()) {
522f4a2713aSLionel Sambuc if (const BinaryOperator *BO =
523f4a2713aSLionel Sambuc dyn_cast<BinaryOperator>(cs->getStmt())) {
524f4a2713aSLionel Sambuc if (BO->getOpcode() == BO_Assign) {
525f4a2713aSLionel Sambuc if (const DeclRefExpr *DR =
526f4a2713aSLionel Sambuc dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) {
527f4a2713aSLionel Sambuc LV->inAssignment[DR] = 1;
528f4a2713aSLionel Sambuc }
529f4a2713aSLionel Sambuc }
530f4a2713aSLionel Sambuc }
531f4a2713aSLionel Sambuc }
532f4a2713aSLionel Sambuc }
533f4a2713aSLionel Sambuc }
534f4a2713aSLionel Sambuc
535f4a2713aSLionel Sambuc worklist.sortWorklist();
536f4a2713aSLionel Sambuc
537f4a2713aSLionel Sambuc while (const CFGBlock *block = worklist.dequeue()) {
538f4a2713aSLionel Sambuc // Determine if the block's end value has changed. If not, we
539f4a2713aSLionel Sambuc // have nothing left to do for this block.
540f4a2713aSLionel Sambuc LivenessValues &prevVal = LV->blocksEndToLiveness[block];
541f4a2713aSLionel Sambuc
542f4a2713aSLionel Sambuc // Merge the values of all successor blocks.
543f4a2713aSLionel Sambuc LivenessValues val;
544f4a2713aSLionel Sambuc for (CFGBlock::const_succ_iterator it = block->succ_begin(),
545f4a2713aSLionel Sambuc ei = block->succ_end(); it != ei; ++it) {
546f4a2713aSLionel Sambuc if (const CFGBlock *succ = *it) {
547f4a2713aSLionel Sambuc val = LV->merge(val, LV->blocksBeginToLiveness[succ]);
548f4a2713aSLionel Sambuc }
549f4a2713aSLionel Sambuc }
550f4a2713aSLionel Sambuc
551f4a2713aSLionel Sambuc if (!everAnalyzedBlock[block->getBlockID()])
552f4a2713aSLionel Sambuc everAnalyzedBlock[block->getBlockID()] = true;
553f4a2713aSLionel Sambuc else if (prevVal.equals(val))
554f4a2713aSLionel Sambuc continue;
555f4a2713aSLionel Sambuc
556f4a2713aSLionel Sambuc prevVal = val;
557f4a2713aSLionel Sambuc
558f4a2713aSLionel Sambuc // Update the dataflow value for the start of this block.
559f4a2713aSLionel Sambuc LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val);
560f4a2713aSLionel Sambuc
561f4a2713aSLionel Sambuc // Enqueue the value to the predecessors.
562f4a2713aSLionel Sambuc worklist.enqueuePredecessors(block);
563f4a2713aSLionel Sambuc }
564f4a2713aSLionel Sambuc
565f4a2713aSLionel Sambuc return new LiveVariables(LV);
566f4a2713aSLionel Sambuc }
567f4a2713aSLionel Sambuc
dumpBlockLiveness(const SourceManager & M)568f4a2713aSLionel Sambuc void LiveVariables::dumpBlockLiveness(const SourceManager &M) {
569f4a2713aSLionel Sambuc getImpl(impl).dumpBlockLiveness(M);
570f4a2713aSLionel Sambuc }
571f4a2713aSLionel Sambuc
dumpBlockLiveness(const SourceManager & M)572f4a2713aSLionel Sambuc void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) {
573f4a2713aSLionel Sambuc std::vector<const CFGBlock *> vec;
574f4a2713aSLionel Sambuc for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator
575f4a2713aSLionel Sambuc it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end();
576f4a2713aSLionel Sambuc it != ei; ++it) {
577f4a2713aSLionel Sambuc vec.push_back(it->first);
578f4a2713aSLionel Sambuc }
579*0a6a1f1dSLionel Sambuc std::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) {
580*0a6a1f1dSLionel Sambuc return A->getBlockID() < B->getBlockID();
581*0a6a1f1dSLionel Sambuc });
582f4a2713aSLionel Sambuc
583f4a2713aSLionel Sambuc std::vector<const VarDecl*> declVec;
584f4a2713aSLionel Sambuc
585f4a2713aSLionel Sambuc for (std::vector<const CFGBlock *>::iterator
586f4a2713aSLionel Sambuc it = vec.begin(), ei = vec.end(); it != ei; ++it) {
587f4a2713aSLionel Sambuc llvm::errs() << "\n[ B" << (*it)->getBlockID()
588f4a2713aSLionel Sambuc << " (live variables at block exit) ]\n";
589f4a2713aSLionel Sambuc
590f4a2713aSLionel Sambuc LiveVariables::LivenessValues vals = blocksEndToLiveness[*it];
591f4a2713aSLionel Sambuc declVec.clear();
592f4a2713aSLionel Sambuc
593f4a2713aSLionel Sambuc for (llvm::ImmutableSet<const VarDecl *>::iterator si =
594f4a2713aSLionel Sambuc vals.liveDecls.begin(),
595f4a2713aSLionel Sambuc se = vals.liveDecls.end(); si != se; ++si) {
596f4a2713aSLionel Sambuc declVec.push_back(*si);
597f4a2713aSLionel Sambuc }
598f4a2713aSLionel Sambuc
599*0a6a1f1dSLionel Sambuc std::sort(declVec.begin(), declVec.end(), [](const Decl *A, const Decl *B) {
600*0a6a1f1dSLionel Sambuc return A->getLocStart() < B->getLocStart();
601*0a6a1f1dSLionel Sambuc });
602f4a2713aSLionel Sambuc
603f4a2713aSLionel Sambuc for (std::vector<const VarDecl*>::iterator di = declVec.begin(),
604f4a2713aSLionel Sambuc de = declVec.end(); di != de; ++di) {
605f4a2713aSLionel Sambuc llvm::errs() << " " << (*di)->getDeclName().getAsString()
606f4a2713aSLionel Sambuc << " <";
607f4a2713aSLionel Sambuc (*di)->getLocation().dump(M);
608f4a2713aSLionel Sambuc llvm::errs() << ">\n";
609f4a2713aSLionel Sambuc }
610f4a2713aSLionel Sambuc }
611f4a2713aSLionel Sambuc llvm::errs() << "\n";
612f4a2713aSLionel Sambuc }
613f4a2713aSLionel Sambuc
getTag()614f4a2713aSLionel Sambuc const void *LiveVariables::getTag() { static int x; return &x; }
getTag()615f4a2713aSLionel Sambuc const void *RelaxedLiveVariables::getTag() { static int x; return &x; }
616