| Ted Kremenek | 11de5cb | 2007-09-20 21:42:55 +0000 | [diff] [blame] | 1 | //=- LiveVariables.cpp - Live Variable Analysis for Source CFGs -*- C++ --*-==// | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file was developed by Ted Kremenek and is distributed under | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for | 
 | 7 | // details. | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 8 | // | 
 | 9 | //===----------------------------------------------------------------------===// | 
 | 10 | // | 
 | 11 | // This file implements Live Variables analysis for source-level CFGs. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
 | 15 | #include "clang/Analysis/LiveVariables.h" | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 16 | #include "clang/Basic/SourceManager.h" | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 17 | #include "clang/AST/Expr.h" | 
 | 18 | #include "clang/AST/CFG.h" | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 19 | #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" | 
 | 20 | #include "DataflowSolver.h" | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 21 | #include "clang/Lex/IdentifierTable.h" | 
 | 22 | #include "llvm/ADT/SmallPtrSet.h" | 
 | 23 |  | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 24 | #include <string.h> | 
 | 25 | #include <stdio.h> | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 26 |  | 
 | 27 | using namespace clang; | 
 | 28 |  | 
 | 29 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 30 | // Dataflow initialization logic. | 
 | 31 | //===----------------------------------------------------------------------===//       | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 32 |  | 
 | 33 | namespace { | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 34 | struct RegisterDecls : public CFGRecStmtDeclVisitor<RegisterDecls> { | 
 | 35 |   LiveVariables::AnalysisDataTy& AD; | 
 | 36 |   void VisitVarDecl(VarDecl* VD) { AD.RegisterDecl(VD); } | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 37 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 38 |   RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {} | 
 | 39 | };   | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 40 | } // end anonymous namespace | 
 | 41 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 42 | void LiveVariables::InitializeValues(const CFG& cfg) { | 
 | 43 |   RegisterDecls R(getAnalysisData()); | 
 | 44 |   cfg.VisitBlockStmts(R); | 
 | 45 | } | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 46 |  | 
 | 47 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 48 | // Transfer functions. | 
 | 49 | //===----------------------------------------------------------------------===//       | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 50 |  | 
 | 51 | namespace { | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 52 | class TransferFuncs : public CFGStmtVisitor<TransferFuncs> { | 
 | 53 |   LiveVariables::AnalysisDataTy& AD; | 
 | 54 |   LiveVariables::ValTy Live; | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 55 | public: | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 56 |   TransferFuncs(LiveVariables::AnalysisDataTy& ad) : AD(ad) {} | 
 | 57 |  | 
 | 58 |   LiveVariables::ValTy& getVal() { return Live; } | 
| Ted Kremenek | f175805 | 2007-09-12 19:10:52 +0000 | [diff] [blame] | 59 |    | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 60 |   void VisitDeclRefExpr(DeclRefExpr* DR); | 
 | 61 |   void VisitBinaryOperator(BinaryOperator* B); | 
 | 62 |   void VisitAssign(BinaryOperator* B); | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 63 |   void VisitDeclStmt(DeclStmt* DS); | 
 | 64 |   void VisitUnaryOperator(UnaryOperator* U); | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 65 |   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 Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 69 |   } | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 70 | }; | 
 | 71 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 72 | void 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 Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 75 | } | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 76 |    | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 77 | void TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {      | 
| Ted Kremenek | f175805 | 2007-09-12 19:10:52 +0000 | [diff] [blame] | 78 |   if (B->isAssignmentOp()) VisitAssign(B); | 
 | 79 |   else VisitStmt(B); | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 80 | } | 
 | 81 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 82 | void TransferFuncs::VisitUnaryOperator(UnaryOperator* U) { | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 83 |   switch (U->getOpcode()) { | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 84 |   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 Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 101 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 102 |       break;    | 
 | 103 |     }         | 
 | 104 |     break; | 
 | 105 |    | 
 | 106 |   default: | 
 | 107 |     Visit(U->getSubExpr()); | 
 | 108 |     break; | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 109 |   } | 
 | 110 | } | 
 | 111 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 112 | void TransferFuncs::VisitAssign(BinaryOperator* B) {     | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 113 |   Stmt* LHS = B->getLHS(); | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 114 |  | 
 | 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 Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 121 |   } | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 122 |   else // Not assigning to a variable.  Process LHS as usual. | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 123 |     Visit(LHS); | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 124 |    | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 125 |   Visit(B->getRHS()); | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 126 | } | 
 | 127 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 128 | void TransferFuncs::VisitDeclStmt(DeclStmt* DS) { | 
 | 129 |   // Declarations effectively "kill" a variable since they cannot | 
 | 130 |   // possibly be live before they are declared. | 
| Steve Naroff | 9474504 | 2007-09-13 23:52:58 +0000 | [diff] [blame] | 131 |   for (ScopedDecl* D = DS->getDecl(); D != NULL ; D = D->getNextDeclarator()) | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 132 |     Live.reset(AD[D]); | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 133 | } | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 134 | } // end anonymous namespace | 
 | 135 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 136 | namespace { | 
 | 137 | struct Merge { | 
 | 138 |   void operator()(LiveVariables::ValTy& Dst, LiveVariables::ValTy& Src) { | 
 | 139 |     Src |= Dst; | 
 | 140 |   } | 
 | 141 | }; | 
 | 142 | } // end anonymous namespace | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 143 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 144 | namespace { | 
 | 145 | typedef DataflowSolver<LiveVariables,TransferFuncs,Merge> Solver; | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 146 | } | 
 | 147 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 148 | void LiveVariables::runOnCFG(const CFG& cfg) { | 
 | 149 |   Solver S(*this); | 
 | 150 |   S.runOnCFG(cfg); | 
 | 151 | } | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 152 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 153 | void 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 Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 160 | } | 
 | 161 |  | 
 | 162 | //===----------------------------------------------------------------------===// | 
 | 163 | // liveness queries | 
 | 164 | // | 
 | 165 |  | 
| Ted Kremenek | c0576ca | 2007-09-10 17:36:42 +0000 | [diff] [blame] | 166 | bool LiveVariables::isLive(const CFGBlock* B, const VarDecl* D) const { | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 167 |   return getBlockData(B)[ getAnalysisData()[D] ]; | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 168 | } | 
 | 169 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 170 | bool LiveVariables::isLive(const ValTy& Live, const VarDecl* D) const { | 
 | 171 |   return Live[ getAnalysisData()[D] ]; | 
| Ted Kremenek | 055c275 | 2007-09-06 23:00:42 +0000 | [diff] [blame] | 172 | } | 
 | 173 |  | 
| Ted Kremenek | 055c275 | 2007-09-06 23:00:42 +0000 | [diff] [blame] | 174 | //===----------------------------------------------------------------------===// | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 175 | // printing liveness state for debugging | 
 | 176 | // | 
 | 177 |  | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 178 | void 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 Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 183 |       SourceLocation PhysLoc = SM.getPhysicalLoc(I->first->getLocation()); | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 184 |      | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 185 |       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 Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 190 |     } | 
| Ted Kremenek | e4e6334 | 2007-09-06 00:17:54 +0000 | [diff] [blame] | 191 | }                                   | 
 | 192 |  | 
| Ted Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 193 | void LiveVariables::dumpBlockLiveness(SourceManager& M) const { | 
| Ted Kremenek | fdd225e | 2007-09-25 04:31:27 +0000 | [diff] [blame^] | 194 |   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 Kremenek | 27b07c5 | 2007-09-06 21:26:58 +0000 | [diff] [blame] | 197 |             I->first->getBlockID()); | 
 | 198 |              | 
 | 199 |     dumpLiveness(I->second,M); | 
 | 200 |   } | 
| Ted Kremenek | c0576ca | 2007-09-10 17:36:42 +0000 | [diff] [blame] | 201 |  | 
 | 202 |   fprintf(stderr,"\n"); | 
 | 203 | } |