blob: fb4f3a681f57995a037f3ed98c34f6996c4204e2 [file] [log] [blame]
Ted Kremenek11de5cb2007-09-20 21:42:55 +00001//=- LiveVariables.cpp - Live Variable Analysis for Source CFGs -*- C++ --*-==//
Ted Kremeneke4e63342007-09-06 00:17:54 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek and is distributed under
Ted Kremenekfdd225e2007-09-25 04:31:27 +00006// the University of Illinois Open Source License. See LICENSE.TXT for
7// details.
Ted Kremeneke4e63342007-09-06 00:17:54 +00008//
9//===----------------------------------------------------------------------===//
10//
11// This file implements Live Variables analysis for source-level CFGs.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/LiveVariables.h"
Ted Kremenek27b07c52007-09-06 21:26:58 +000016#include "clang/Basic/SourceManager.h"
Ted Kremeneke4e63342007-09-06 00:17:54 +000017#include "clang/AST/Expr.h"
18#include "clang/AST/CFG.h"
Ted Kremenekfdd225e2007-09-25 04:31:27 +000019#include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
20#include "DataflowSolver.h"
Ted Kremeneke4e63342007-09-06 00:17:54 +000021#include "clang/Lex/IdentifierTable.h"
22#include "llvm/ADT/SmallPtrSet.h"
23
Ted Kremenek27b07c52007-09-06 21:26:58 +000024#include <string.h>
25#include <stdio.h>
Ted Kremeneke4e63342007-09-06 00:17:54 +000026
27using namespace clang;
28
29//===----------------------------------------------------------------------===//
Ted Kremenekfdd225e2007-09-25 04:31:27 +000030// Dataflow initialization logic.
31//===----------------------------------------------------------------------===//
Ted Kremeneke4e63342007-09-06 00:17:54 +000032
33namespace {
Ted Kremenekfdd225e2007-09-25 04:31:27 +000034struct RegisterDecls : public CFGRecStmtDeclVisitor<RegisterDecls> {
35 LiveVariables::AnalysisDataTy& AD;
36 void VisitVarDecl(VarDecl* VD) { AD.RegisterDecl(VD); }
Ted Kremeneke4e63342007-09-06 00:17:54 +000037
Ted Kremenekfdd225e2007-09-25 04:31:27 +000038 RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
39};
Ted Kremeneke4e63342007-09-06 00:17:54 +000040} // end anonymous namespace
41
Ted Kremenekfdd225e2007-09-25 04:31:27 +000042void LiveVariables::InitializeValues(const CFG& cfg) {
43 RegisterDecls R(getAnalysisData());
44 cfg.VisitBlockStmts(R);
45}
Ted Kremeneke4e63342007-09-06 00:17:54 +000046
47//===----------------------------------------------------------------------===//
Ted Kremenekfdd225e2007-09-25 04:31:27 +000048// Transfer functions.
49//===----------------------------------------------------------------------===//
Ted Kremeneke4e63342007-09-06 00:17:54 +000050
51namespace {
Ted Kremenekfdd225e2007-09-25 04:31:27 +000052class TransferFuncs : public CFGStmtVisitor<TransferFuncs> {
53 LiveVariables::AnalysisDataTy& AD;
54 LiveVariables::ValTy Live;
Ted Kremeneke4e63342007-09-06 00:17:54 +000055public:
Ted Kremenekfdd225e2007-09-25 04:31:27 +000056 TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
57
58 LiveVariables::ValTy& getVal() { return Live; }
Ted Kremenekf1758052007-09-12 19:10:52 +000059
Ted Kremeneke4e63342007-09-06 00:17:54 +000060 void VisitDeclRefExpr(DeclRefExpr* DR);
61 void VisitBinaryOperator(BinaryOperator* B);
62 void VisitAssign(BinaryOperator* B);
Ted Kremenek27b07c52007-09-06 21:26:58 +000063 void VisitDeclStmt(DeclStmt* DS);
64 void VisitUnaryOperator(UnaryOperator* U);
Ted Kremenekfdd225e2007-09-25 04:31:27 +000065 void VisitStmt(Stmt* S) { VisitChildren(S); }
66 void Visit(Stmt *S) {
67 if (AD.Observer) AD.Observer->ObserveStmt(S,AD,Live);
68 static_cast<CFGStmtVisitor<TransferFuncs>*>(this)->Visit(S);
Ted Kremeneke4e63342007-09-06 00:17:54 +000069 }
Ted Kremeneke4e63342007-09-06 00:17:54 +000070};
71
Ted Kremenekfdd225e2007-09-25 04:31:27 +000072void TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
73 if (VarDecl* V = dyn_cast<VarDecl>(DR->getDecl()))
74 Live.set(AD[V]); // Register a use of the variable.
Ted Kremeneke4e63342007-09-06 00:17:54 +000075}
Ted Kremeneke4e63342007-09-06 00:17:54 +000076
Ted Kremenekfdd225e2007-09-25 04:31:27 +000077void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
Ted Kremenekf1758052007-09-12 19:10:52 +000078 if (B->isAssignmentOp()) VisitAssign(B);
79 else VisitStmt(B);
Ted Kremeneke4e63342007-09-06 00:17:54 +000080}
81
Ted Kremenekfdd225e2007-09-25 04:31:27 +000082void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
Ted Kremenek27b07c52007-09-06 21:26:58 +000083 switch (U->getOpcode()) {
Ted Kremenekfdd225e2007-09-25 04:31:27 +000084 case UnaryOperator::PostInc:
85 case UnaryOperator::PostDec:
86 case UnaryOperator::PreInc:
87 case UnaryOperator::PreDec:
88 case UnaryOperator::AddrOf:
89 // Walk through the subexpressions, blasting through ParenExprs
90 // until we either find a DeclRefExpr or some non-DeclRefExpr
91 // expression.
92 for (Stmt* S = U->getSubExpr() ;;) {
93 if (ParenExpr* P = dyn_cast<ParenExpr>(S)) { S=P->getSubExpr(); continue;}
94 else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
95 // Treat the --/++/& operator as a kill.
96 Live.reset(AD[DR->getDecl()]);
97 if (AD.Observer) AD.Observer->ObserverKill(DR);
98 VisitDeclRefExpr(DR);
99 }
100 else Visit(S);
Ted Kremenek27b07c52007-09-06 21:26:58 +0000101
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000102 break;
103 }
104 break;
105
106 default:
107 Visit(U->getSubExpr());
108 break;
Ted Kremenek27b07c52007-09-06 21:26:58 +0000109 }
110}
111
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000112void TransferFuncs::VisitAssign(BinaryOperator* B) {
Ted Kremeneke4e63342007-09-06 00:17:54 +0000113 Stmt* LHS = B->getLHS();
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000114
115 if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS)) { // Assigning to a var?
116 Live.reset(AD[DR->getDecl()]);
117 if (AD.Observer) AD.Observer->ObserverKill(DR);
118 // Handle things like +=, etc., which also generate "uses"
119 // of a variable. Do this just by visiting the subexpression.
120 if (B->getOpcode() != BinaryOperator::Assign) Visit(LHS);
Ted Kremeneke4e63342007-09-06 00:17:54 +0000121 }
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000122 else // Not assigning to a variable. Process LHS as usual.
Ted Kremenek27b07c52007-09-06 21:26:58 +0000123 Visit(LHS);
Ted Kremeneke4e63342007-09-06 00:17:54 +0000124
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000125 Visit(B->getRHS());
Ted Kremeneke4e63342007-09-06 00:17:54 +0000126}
127
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000128void TransferFuncs::VisitDeclStmt(DeclStmt* DS) {
129 // Declarations effectively "kill" a variable since they cannot
130 // possibly be live before they are declared.
Steve Naroff94745042007-09-13 23:52:58 +0000131 for (ScopedDecl* D = DS->getDecl(); D != NULL ; D = D->getNextDeclarator())
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000132 Live.reset(AD[D]);
Ted Kremenek27b07c52007-09-06 21:26:58 +0000133}
Ted Kremeneke4e63342007-09-06 00:17:54 +0000134} // end anonymous namespace
135
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000136namespace {
137struct Merge {
138 void operator()(LiveVariables::ValTy& Dst, LiveVariables::ValTy& Src) {
139 Src |= Dst;
140 }
141};
142} // end anonymous namespace
Ted Kremeneke4e63342007-09-06 00:17:54 +0000143
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000144namespace {
145typedef DataflowSolver<LiveVariables,TransferFuncs,Merge> Solver;
Ted Kremeneke4e63342007-09-06 00:17:54 +0000146}
147
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000148void LiveVariables::runOnCFG(const CFG& cfg) {
149 Solver S(*this);
150 S.runOnCFG(cfg);
151}
Ted Kremenek27b07c52007-09-06 21:26:58 +0000152
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000153void LiveVariables::runOnAllBlocks(const CFG& cfg,
154 LiveVariables::ObserverTy& Obs) {
155 Solver S(*this);
156 ObserverTy* OldObserver = getAnalysisData().Observer;
157 getAnalysisData().Observer = &Obs;
158 S.runOnAllBlocks(cfg);
159 getAnalysisData().Observer = OldObserver;
Ted Kremenek27b07c52007-09-06 21:26:58 +0000160}
161
162//===----------------------------------------------------------------------===//
163// liveness queries
164//
165
Ted Kremenekc0576ca2007-09-10 17:36:42 +0000166bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const {
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000167 return getBlockData(B)[ getAnalysisData()[D] ];
Ted Kremenek27b07c52007-09-06 21:26:58 +0000168}
169
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000170bool LiveVariables::isLive(const ValTy& Live, const VarDecl* D) const {
171 return Live[ getAnalysisData()[D] ];
Ted Kremenek055c2752007-09-06 23:00:42 +0000172}
173
Ted Kremenek055c2752007-09-06 23:00:42 +0000174//===----------------------------------------------------------------------===//
Ted Kremeneke4e63342007-09-06 00:17:54 +0000175// printing liveness state for debugging
176//
177
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000178void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {
179 const AnalysisDataTy& AD = getAnalysisData();
180
181 for (AnalysisDataTy::iterator I = AD.begin(), E = AD.end(); I!=E; ++I)
182 if (V[I->second]) {
Ted Kremenek27b07c52007-09-06 21:26:58 +0000183 SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation());
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000184
Ted Kremenek27b07c52007-09-06 21:26:58 +0000185 fprintf(stderr, " %s <%s:%u:%u>\n",
186 I->first->getIdentifier()->getName(),
187 SM.getSourceName(PhysLoc),
188 SM.getLineNumber(PhysLoc),
189 SM.getColumnNumber(PhysLoc));
Ted Kremeneke4e63342007-09-06 00:17:54 +0000190 }
Ted Kremeneke4e63342007-09-06 00:17:54 +0000191}
192
Ted Kremenek27b07c52007-09-06 21:26:58 +0000193void LiveVariables::dumpBlockLiveness(SourceManager& M) const {
Ted Kremenekfdd225e2007-09-25 04:31:27 +0000194 for (BlockDataMapTy::iterator I = getBlockDataMap().begin(),
195 E = getBlockDataMap().end(); I!=E; ++I) {
196 fprintf(stderr, "\n[ B%d (live variables at block exit) ]\n",
Ted Kremenek27b07c52007-09-06 21:26:58 +0000197 I->first->getBlockID());
198
199 dumpLiveness(I->second,M);
200 }
Ted Kremenekc0576ca2007-09-10 17:36:42 +0000201
202 fprintf(stderr,"\n");
203}