clang API Documentation
00001 //=- LiveVariables.cpp - Live Variable Analysis for Source CFGs ----------*-==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements Live Variables analysis for source-level CFGs. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Analysis/Analyses/LiveVariables.h" 00015 #include "clang/AST/Stmt.h" 00016 #include "clang/AST/StmtVisitor.h" 00017 #include "clang/Analysis/Analyses/PostOrderCFGView.h" 00018 #include "clang/Analysis/AnalysisContext.h" 00019 #include "clang/Analysis/CFG.h" 00020 #include "llvm/ADT/DenseMap.h" 00021 #include "llvm/ADT/PostOrderIterator.h" 00022 #include "llvm/Support/raw_ostream.h" 00023 #include <algorithm> 00024 #include <vector> 00025 00026 using namespace clang; 00027 00028 namespace { 00029 00030 class DataflowWorklist { 00031 SmallVector<const CFGBlock *, 20> worklist; 00032 llvm::BitVector enqueuedBlocks; 00033 PostOrderCFGView *POV; 00034 public: 00035 DataflowWorklist(const CFG &cfg, AnalysisDeclContext &Ctx) 00036 : enqueuedBlocks(cfg.getNumBlockIDs()), 00037 POV(Ctx.getAnalysis<PostOrderCFGView>()) {} 00038 00039 void enqueueBlock(const CFGBlock *block); 00040 void enqueuePredecessors(const CFGBlock *block); 00041 00042 const CFGBlock *dequeue(); 00043 00044 void sortWorklist(); 00045 }; 00046 00047 } 00048 00049 void DataflowWorklist::enqueueBlock(const clang::CFGBlock *block) { 00050 if (block && !enqueuedBlocks[block->getBlockID()]) { 00051 enqueuedBlocks[block->getBlockID()] = true; 00052 worklist.push_back(block); 00053 } 00054 } 00055 00056 void DataflowWorklist::enqueuePredecessors(const clang::CFGBlock *block) { 00057 const unsigned OldWorklistSize = worklist.size(); 00058 for (CFGBlock::const_pred_iterator I = block->pred_begin(), 00059 E = block->pred_end(); I != E; ++I) { 00060 enqueueBlock(*I); 00061 } 00062 00063 if (OldWorklistSize == 0 || OldWorklistSize == worklist.size()) 00064 return; 00065 00066 sortWorklist(); 00067 } 00068 00069 void DataflowWorklist::sortWorklist() { 00070 std::sort(worklist.begin(), worklist.end(), POV->getComparator()); 00071 } 00072 00073 const CFGBlock *DataflowWorklist::dequeue() { 00074 if (worklist.empty()) 00075 return nullptr; 00076 const CFGBlock *b = worklist.pop_back_val(); 00077 enqueuedBlocks[b->getBlockID()] = false; 00078 return b; 00079 } 00080 00081 namespace { 00082 class LiveVariablesImpl { 00083 public: 00084 AnalysisDeclContext &analysisContext; 00085 llvm::ImmutableSet<const Stmt *>::Factory SSetFact; 00086 llvm::ImmutableSet<const VarDecl *>::Factory DSetFact; 00087 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksEndToLiveness; 00088 llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues> blocksBeginToLiveness; 00089 llvm::DenseMap<const Stmt *, LiveVariables::LivenessValues> stmtsToLiveness; 00090 llvm::DenseMap<const DeclRefExpr *, unsigned> inAssignment; 00091 const bool killAtAssign; 00092 00093 LiveVariables::LivenessValues 00094 merge(LiveVariables::LivenessValues valsA, 00095 LiveVariables::LivenessValues valsB); 00096 00097 LiveVariables::LivenessValues 00098 runOnBlock(const CFGBlock *block, LiveVariables::LivenessValues val, 00099 LiveVariables::Observer *obs = nullptr); 00100 00101 void dumpBlockLiveness(const SourceManager& M); 00102 00103 LiveVariablesImpl(AnalysisDeclContext &ac, bool KillAtAssign) 00104 : analysisContext(ac), 00105 SSetFact(false), // Do not canonicalize ImmutableSets by default. 00106 DSetFact(false), // This is a *major* performance win. 00107 killAtAssign(KillAtAssign) {} 00108 }; 00109 } 00110 00111 static LiveVariablesImpl &getImpl(void *x) { 00112 return *((LiveVariablesImpl *) x); 00113 } 00114 00115 //===----------------------------------------------------------------------===// 00116 // Operations and queries on LivenessValues. 00117 //===----------------------------------------------------------------------===// 00118 00119 bool LiveVariables::LivenessValues::isLive(const Stmt *S) const { 00120 return liveStmts.contains(S); 00121 } 00122 00123 bool LiveVariables::LivenessValues::isLive(const VarDecl *D) const { 00124 return liveDecls.contains(D); 00125 } 00126 00127 namespace { 00128 template <typename SET> 00129 SET mergeSets(SET A, SET B) { 00130 if (A.isEmpty()) 00131 return B; 00132 00133 for (typename SET::iterator it = B.begin(), ei = B.end(); it != ei; ++it) { 00134 A = A.add(*it); 00135 } 00136 return A; 00137 } 00138 } 00139 00140 void LiveVariables::Observer::anchor() { } 00141 00142 LiveVariables::LivenessValues 00143 LiveVariablesImpl::merge(LiveVariables::LivenessValues valsA, 00144 LiveVariables::LivenessValues valsB) { 00145 00146 llvm::ImmutableSetRef<const Stmt *> 00147 SSetRefA(valsA.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()), 00148 SSetRefB(valsB.liveStmts.getRootWithoutRetain(), SSetFact.getTreeFactory()); 00149 00150 00151 llvm::ImmutableSetRef<const VarDecl *> 00152 DSetRefA(valsA.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()), 00153 DSetRefB(valsB.liveDecls.getRootWithoutRetain(), DSetFact.getTreeFactory()); 00154 00155 00156 SSetRefA = mergeSets(SSetRefA, SSetRefB); 00157 DSetRefA = mergeSets(DSetRefA, DSetRefB); 00158 00159 // asImmutableSet() canonicalizes the tree, allowing us to do an easy 00160 // comparison afterwards. 00161 return LiveVariables::LivenessValues(SSetRefA.asImmutableSet(), 00162 DSetRefA.asImmutableSet()); 00163 } 00164 00165 bool LiveVariables::LivenessValues::equals(const LivenessValues &V) const { 00166 return liveStmts == V.liveStmts && liveDecls == V.liveDecls; 00167 } 00168 00169 //===----------------------------------------------------------------------===// 00170 // Query methods. 00171 //===----------------------------------------------------------------------===// 00172 00173 static bool isAlwaysAlive(const VarDecl *D) { 00174 return D->hasGlobalStorage(); 00175 } 00176 00177 bool LiveVariables::isLive(const CFGBlock *B, const VarDecl *D) { 00178 return isAlwaysAlive(D) || getImpl(impl).blocksEndToLiveness[B].isLive(D); 00179 } 00180 00181 bool LiveVariables::isLive(const Stmt *S, const VarDecl *D) { 00182 return isAlwaysAlive(D) || getImpl(impl).stmtsToLiveness[S].isLive(D); 00183 } 00184 00185 bool LiveVariables::isLive(const Stmt *Loc, const Stmt *S) { 00186 return getImpl(impl).stmtsToLiveness[Loc].isLive(S); 00187 } 00188 00189 //===----------------------------------------------------------------------===// 00190 // Dataflow computation. 00191 //===----------------------------------------------------------------------===// 00192 00193 namespace { 00194 class TransferFunctions : public StmtVisitor<TransferFunctions> { 00195 LiveVariablesImpl &LV; 00196 LiveVariables::LivenessValues &val; 00197 LiveVariables::Observer *observer; 00198 const CFGBlock *currentBlock; 00199 public: 00200 TransferFunctions(LiveVariablesImpl &im, 00201 LiveVariables::LivenessValues &Val, 00202 LiveVariables::Observer *Observer, 00203 const CFGBlock *CurrentBlock) 00204 : LV(im), val(Val), observer(Observer), currentBlock(CurrentBlock) {} 00205 00206 void VisitBinaryOperator(BinaryOperator *BO); 00207 void VisitBlockExpr(BlockExpr *BE); 00208 void VisitDeclRefExpr(DeclRefExpr *DR); 00209 void VisitDeclStmt(DeclStmt *DS); 00210 void VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS); 00211 void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE); 00212 void VisitUnaryOperator(UnaryOperator *UO); 00213 void Visit(Stmt *S); 00214 }; 00215 } 00216 00217 static const VariableArrayType *FindVA(QualType Ty) { 00218 const Type *ty = Ty.getTypePtr(); 00219 while (const ArrayType *VT = dyn_cast<ArrayType>(ty)) { 00220 if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(VT)) 00221 if (VAT->getSizeExpr()) 00222 return VAT; 00223 00224 ty = VT->getElementType().getTypePtr(); 00225 } 00226 00227 return nullptr; 00228 } 00229 00230 static const Stmt *LookThroughStmt(const Stmt *S) { 00231 while (S) { 00232 if (const Expr *Ex = dyn_cast<Expr>(S)) 00233 S = Ex->IgnoreParens(); 00234 if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(S)) { 00235 S = EWC->getSubExpr(); 00236 continue; 00237 } 00238 if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) { 00239 S = OVE->getSourceExpr(); 00240 continue; 00241 } 00242 break; 00243 } 00244 return S; 00245 } 00246 00247 static void AddLiveStmt(llvm::ImmutableSet<const Stmt *> &Set, 00248 llvm::ImmutableSet<const Stmt *>::Factory &F, 00249 const Stmt *S) { 00250 Set = F.add(Set, LookThroughStmt(S)); 00251 } 00252 00253 void TransferFunctions::Visit(Stmt *S) { 00254 if (observer) 00255 observer->observeStmt(S, currentBlock, val); 00256 00257 StmtVisitor<TransferFunctions>::Visit(S); 00258 00259 if (isa<Expr>(S)) { 00260 val.liveStmts = LV.SSetFact.remove(val.liveStmts, S); 00261 } 00262 00263 // Mark all children expressions live. 00264 00265 switch (S->getStmtClass()) { 00266 default: 00267 break; 00268 case Stmt::StmtExprClass: { 00269 // For statement expressions, look through the compound statement. 00270 S = cast<StmtExpr>(S)->getSubStmt(); 00271 break; 00272 } 00273 case Stmt::CXXMemberCallExprClass: { 00274 // Include the implicit "this" pointer as being live. 00275 CXXMemberCallExpr *CE = cast<CXXMemberCallExpr>(S); 00276 if (Expr *ImplicitObj = CE->getImplicitObjectArgument()) { 00277 AddLiveStmt(val.liveStmts, LV.SSetFact, ImplicitObj); 00278 } 00279 break; 00280 } 00281 case Stmt::ObjCMessageExprClass: { 00282 // In calls to super, include the implicit "self" pointer as being live. 00283 ObjCMessageExpr *CE = cast<ObjCMessageExpr>(S); 00284 if (CE->getReceiverKind() == ObjCMessageExpr::SuperInstance) 00285 val.liveDecls = LV.DSetFact.add(val.liveDecls, 00286 LV.analysisContext.getSelfDecl()); 00287 break; 00288 } 00289 case Stmt::DeclStmtClass: { 00290 const DeclStmt *DS = cast<DeclStmt>(S); 00291 if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) { 00292 for (const VariableArrayType* VA = FindVA(VD->getType()); 00293 VA != nullptr; VA = FindVA(VA->getElementType())) { 00294 AddLiveStmt(val.liveStmts, LV.SSetFact, VA->getSizeExpr()); 00295 } 00296 } 00297 break; 00298 } 00299 case Stmt::PseudoObjectExprClass: { 00300 // A pseudo-object operation only directly consumes its result 00301 // expression. 00302 Expr *child = cast<PseudoObjectExpr>(S)->getResultExpr(); 00303 if (!child) return; 00304 if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(child)) 00305 child = OV->getSourceExpr(); 00306 child = child->IgnoreParens(); 00307 val.liveStmts = LV.SSetFact.add(val.liveStmts, child); 00308 return; 00309 } 00310 00311 // FIXME: These cases eventually shouldn't be needed. 00312 case Stmt::ExprWithCleanupsClass: { 00313 S = cast<ExprWithCleanups>(S)->getSubExpr(); 00314 break; 00315 } 00316 case Stmt::CXXBindTemporaryExprClass: { 00317 S = cast<CXXBindTemporaryExpr>(S)->getSubExpr(); 00318 break; 00319 } 00320 case Stmt::UnaryExprOrTypeTraitExprClass: { 00321 // No need to unconditionally visit subexpressions. 00322 return; 00323 } 00324 } 00325 00326 for (Stmt::child_iterator it = S->child_begin(), ei = S->child_end(); 00327 it != ei; ++it) { 00328 if (Stmt *child = *it) 00329 AddLiveStmt(val.liveStmts, LV.SSetFact, child); 00330 } 00331 } 00332 00333 void TransferFunctions::VisitBinaryOperator(BinaryOperator *B) { 00334 if (B->isAssignmentOp()) { 00335 if (!LV.killAtAssign) 00336 return; 00337 00338 // Assigning to a variable? 00339 Expr *LHS = B->getLHS()->IgnoreParens(); 00340 00341 if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(LHS)) 00342 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 00343 // Assignments to references don't kill the ref's address 00344 if (VD->getType()->isReferenceType()) 00345 return; 00346 00347 if (!isAlwaysAlive(VD)) { 00348 // The variable is now dead. 00349 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD); 00350 } 00351 00352 if (observer) 00353 observer->observerKill(DR); 00354 } 00355 } 00356 } 00357 00358 void TransferFunctions::VisitBlockExpr(BlockExpr *BE) { 00359 AnalysisDeclContext::referenced_decls_iterator I, E; 00360 std::tie(I, E) = 00361 LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl()); 00362 for ( ; I != E ; ++I) { 00363 const VarDecl *VD = *I; 00364 if (isAlwaysAlive(VD)) 00365 continue; 00366 val.liveDecls = LV.DSetFact.add(val.liveDecls, VD); 00367 } 00368 } 00369 00370 void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *DR) { 00371 if (const VarDecl *D = dyn_cast<VarDecl>(DR->getDecl())) 00372 if (!isAlwaysAlive(D) && LV.inAssignment.find(DR) == LV.inAssignment.end()) 00373 val.liveDecls = LV.DSetFact.add(val.liveDecls, D); 00374 } 00375 00376 void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { 00377 for (const auto *DI : DS->decls()) 00378 if (const auto *VD = dyn_cast<VarDecl>(DI)) { 00379 if (!isAlwaysAlive(VD)) 00380 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD); 00381 } 00382 } 00383 00384 void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) { 00385 // Kill the iteration variable. 00386 DeclRefExpr *DR = nullptr; 00387 const VarDecl *VD = nullptr; 00388 00389 Stmt *element = OS->getElement(); 00390 if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) { 00391 VD = cast<VarDecl>(DS->getSingleDecl()); 00392 } 00393 else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) { 00394 VD = cast<VarDecl>(DR->getDecl()); 00395 } 00396 00397 if (VD) { 00398 val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD); 00399 if (observer && DR) 00400 observer->observerKill(DR); 00401 } 00402 } 00403 00404 void TransferFunctions:: 00405 VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *UE) 00406 { 00407 // While sizeof(var) doesn't technically extend the liveness of 'var', it 00408 // does extent the liveness of metadata if 'var' is a VariableArrayType. 00409 // We handle that special case here. 00410 if (UE->getKind() != UETT_SizeOf || UE->isArgumentType()) 00411 return; 00412 00413 const Expr *subEx = UE->getArgumentExpr(); 00414 if (subEx->getType()->isVariableArrayType()) { 00415 assert(subEx->isLValue()); 00416 val.liveStmts = LV.SSetFact.add(val.liveStmts, subEx->IgnoreParens()); 00417 } 00418 } 00419 00420 void TransferFunctions::VisitUnaryOperator(UnaryOperator *UO) { 00421 // Treat ++/-- as a kill. 00422 // Note we don't actually have to do anything if we don't have an observer, 00423 // since a ++/-- acts as both a kill and a "use". 00424 if (!observer) 00425 return; 00426 00427 switch (UO->getOpcode()) { 00428 default: 00429 return; 00430 case UO_PostInc: 00431 case UO_PostDec: 00432 case UO_PreInc: 00433 case UO_PreDec: 00434 break; 00435 } 00436 00437 if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) 00438 if (isa<VarDecl>(DR->getDecl())) { 00439 // Treat ++/-- as a kill. 00440 observer->observerKill(DR); 00441 } 00442 } 00443 00444 LiveVariables::LivenessValues 00445 LiveVariablesImpl::runOnBlock(const CFGBlock *block, 00446 LiveVariables::LivenessValues val, 00447 LiveVariables::Observer *obs) { 00448 00449 TransferFunctions TF(*this, val, obs, block); 00450 00451 // Visit the terminator (if any). 00452 if (const Stmt *term = block->getTerminator()) 00453 TF.Visit(const_cast<Stmt*>(term)); 00454 00455 // Apply the transfer function for all Stmts in the block. 00456 for (CFGBlock::const_reverse_iterator it = block->rbegin(), 00457 ei = block->rend(); it != ei; ++it) { 00458 const CFGElement &elem = *it; 00459 00460 if (Optional<CFGAutomaticObjDtor> Dtor = 00461 elem.getAs<CFGAutomaticObjDtor>()) { 00462 val.liveDecls = DSetFact.add(val.liveDecls, Dtor->getVarDecl()); 00463 continue; 00464 } 00465 00466 if (!elem.getAs<CFGStmt>()) 00467 continue; 00468 00469 const Stmt *S = elem.castAs<CFGStmt>().getStmt(); 00470 TF.Visit(const_cast<Stmt*>(S)); 00471 stmtsToLiveness[S] = val; 00472 } 00473 return val; 00474 } 00475 00476 void LiveVariables::runOnAllBlocks(LiveVariables::Observer &obs) { 00477 const CFG *cfg = getImpl(impl).analysisContext.getCFG(); 00478 for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) 00479 getImpl(impl).runOnBlock(*it, getImpl(impl).blocksEndToLiveness[*it], &obs); 00480 } 00481 00482 LiveVariables::LiveVariables(void *im) : impl(im) {} 00483 00484 LiveVariables::~LiveVariables() { 00485 delete (LiveVariablesImpl*) impl; 00486 } 00487 00488 LiveVariables * 00489 LiveVariables::computeLiveness(AnalysisDeclContext &AC, 00490 bool killAtAssign) { 00491 00492 // No CFG? Bail out. 00493 CFG *cfg = AC.getCFG(); 00494 if (!cfg) 00495 return nullptr; 00496 00497 // The analysis currently has scalability issues for very large CFGs. 00498 // Bail out if it looks too large. 00499 if (cfg->getNumBlockIDs() > 300000) 00500 return nullptr; 00501 00502 LiveVariablesImpl *LV = new LiveVariablesImpl(AC, killAtAssign); 00503 00504 // Construct the dataflow worklist. Enqueue the exit block as the 00505 // start of the analysis. 00506 DataflowWorklist worklist(*cfg, AC); 00507 llvm::BitVector everAnalyzedBlock(cfg->getNumBlockIDs()); 00508 00509 // FIXME: we should enqueue using post order. 00510 for (CFG::const_iterator it = cfg->begin(), ei = cfg->end(); it != ei; ++it) { 00511 const CFGBlock *block = *it; 00512 worklist.enqueueBlock(block); 00513 00514 // FIXME: Scan for DeclRefExprs using in the LHS of an assignment. 00515 // We need to do this because we lack context in the reverse analysis 00516 // to determine if a DeclRefExpr appears in such a context, and thus 00517 // doesn't constitute a "use". 00518 if (killAtAssign) 00519 for (CFGBlock::const_iterator bi = block->begin(), be = block->end(); 00520 bi != be; ++bi) { 00521 if (Optional<CFGStmt> cs = bi->getAs<CFGStmt>()) { 00522 if (const BinaryOperator *BO = 00523 dyn_cast<BinaryOperator>(cs->getStmt())) { 00524 if (BO->getOpcode() == BO_Assign) { 00525 if (const DeclRefExpr *DR = 00526 dyn_cast<DeclRefExpr>(BO->getLHS()->IgnoreParens())) { 00527 LV->inAssignment[DR] = 1; 00528 } 00529 } 00530 } 00531 } 00532 } 00533 } 00534 00535 worklist.sortWorklist(); 00536 00537 while (const CFGBlock *block = worklist.dequeue()) { 00538 // Determine if the block's end value has changed. If not, we 00539 // have nothing left to do for this block. 00540 LivenessValues &prevVal = LV->blocksEndToLiveness[block]; 00541 00542 // Merge the values of all successor blocks. 00543 LivenessValues val; 00544 for (CFGBlock::const_succ_iterator it = block->succ_begin(), 00545 ei = block->succ_end(); it != ei; ++it) { 00546 if (const CFGBlock *succ = *it) { 00547 val = LV->merge(val, LV->blocksBeginToLiveness[succ]); 00548 } 00549 } 00550 00551 if (!everAnalyzedBlock[block->getBlockID()]) 00552 everAnalyzedBlock[block->getBlockID()] = true; 00553 else if (prevVal.equals(val)) 00554 continue; 00555 00556 prevVal = val; 00557 00558 // Update the dataflow value for the start of this block. 00559 LV->blocksBeginToLiveness[block] = LV->runOnBlock(block, val); 00560 00561 // Enqueue the value to the predecessors. 00562 worklist.enqueuePredecessors(block); 00563 } 00564 00565 return new LiveVariables(LV); 00566 } 00567 00568 void LiveVariables::dumpBlockLiveness(const SourceManager &M) { 00569 getImpl(impl).dumpBlockLiveness(M); 00570 } 00571 00572 void LiveVariablesImpl::dumpBlockLiveness(const SourceManager &M) { 00573 std::vector<const CFGBlock *> vec; 00574 for (llvm::DenseMap<const CFGBlock *, LiveVariables::LivenessValues>::iterator 00575 it = blocksEndToLiveness.begin(), ei = blocksEndToLiveness.end(); 00576 it != ei; ++it) { 00577 vec.push_back(it->first); 00578 } 00579 std::sort(vec.begin(), vec.end(), [](const CFGBlock *A, const CFGBlock *B) { 00580 return A->getBlockID() < B->getBlockID(); 00581 }); 00582 00583 std::vector<const VarDecl*> declVec; 00584 00585 for (std::vector<const CFGBlock *>::iterator 00586 it = vec.begin(), ei = vec.end(); it != ei; ++it) { 00587 llvm::errs() << "\n[ B" << (*it)->getBlockID() 00588 << " (live variables at block exit) ]\n"; 00589 00590 LiveVariables::LivenessValues vals = blocksEndToLiveness[*it]; 00591 declVec.clear(); 00592 00593 for (llvm::ImmutableSet<const VarDecl *>::iterator si = 00594 vals.liveDecls.begin(), 00595 se = vals.liveDecls.end(); si != se; ++si) { 00596 declVec.push_back(*si); 00597 } 00598 00599 std::sort(declVec.begin(), declVec.end(), [](const Decl *A, const Decl *B) { 00600 return A->getLocStart() < B->getLocStart(); 00601 }); 00602 00603 for (std::vector<const VarDecl*>::iterator di = declVec.begin(), 00604 de = declVec.end(); di != de; ++di) { 00605 llvm::errs() << " " << (*di)->getDeclName().getAsString() 00606 << " <"; 00607 (*di)->getLocation().dump(M); 00608 llvm::errs() << ">\n"; 00609 } 00610 } 00611 llvm::errs() << "\n"; 00612 } 00613 00614 const void *LiveVariables::getTag() { static int x; return &x; } 00615 const void *RelaxedLiveVariables::getTag() { static int x; return &x; }