clang API Documentation

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