1*67e74705SXin Li //==- CFGReachabilityAnalysis.cpp - Basic reachability analysis --*- C++ -*-==// 2*67e74705SXin Li // 3*67e74705SXin Li // The LLVM Compiler Infrastructure 4*67e74705SXin Li // 5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source 6*67e74705SXin Li // License. See LICENSE.TXT for details. 7*67e74705SXin Li // 8*67e74705SXin Li //===----------------------------------------------------------------------===// 9*67e74705SXin Li // 10*67e74705SXin Li // This file defines a flow-sensitive, (mostly) path-insensitive reachability 11*67e74705SXin Li // analysis based on Clang's CFGs. Clients can query if a given basic block 12*67e74705SXin Li // is reachable within the CFG. 13*67e74705SXin Li // 14*67e74705SXin Li //===----------------------------------------------------------------------===// 15*67e74705SXin Li 16*67e74705SXin Li #include "llvm/ADT/SmallVector.h" 17*67e74705SXin Li #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 18*67e74705SXin Li #include "clang/Analysis/CFG.h" 19*67e74705SXin Li 20*67e74705SXin Li using namespace clang; 21*67e74705SXin Li CFGReverseBlockReachabilityAnalysis(const CFG & cfg)22*67e74705SXin LiCFGReverseBlockReachabilityAnalysis::CFGReverseBlockReachabilityAnalysis(const CFG &cfg) 23*67e74705SXin Li : analyzed(cfg.getNumBlockIDs(), false) {} 24*67e74705SXin Li isReachable(const CFGBlock * Src,const CFGBlock * Dst)25*67e74705SXin Libool CFGReverseBlockReachabilityAnalysis::isReachable(const CFGBlock *Src, 26*67e74705SXin Li const CFGBlock *Dst) { 27*67e74705SXin Li 28*67e74705SXin Li const unsigned DstBlockID = Dst->getBlockID(); 29*67e74705SXin Li 30*67e74705SXin Li // If we haven't analyzed the destination node, run the analysis now 31*67e74705SXin Li if (!analyzed[DstBlockID]) { 32*67e74705SXin Li mapReachability(Dst); 33*67e74705SXin Li analyzed[DstBlockID] = true; 34*67e74705SXin Li } 35*67e74705SXin Li 36*67e74705SXin Li // Return the cached result 37*67e74705SXin Li return reachable[DstBlockID][Src->getBlockID()]; 38*67e74705SXin Li } 39*67e74705SXin Li 40*67e74705SXin Li // Maps reachability to a common node by walking the predecessors of the 41*67e74705SXin Li // destination node. mapReachability(const CFGBlock * Dst)42*67e74705SXin Livoid CFGReverseBlockReachabilityAnalysis::mapReachability(const CFGBlock *Dst) { 43*67e74705SXin Li SmallVector<const CFGBlock *, 11> worklist; 44*67e74705SXin Li llvm::BitVector visited(analyzed.size()); 45*67e74705SXin Li 46*67e74705SXin Li ReachableSet &DstReachability = reachable[Dst->getBlockID()]; 47*67e74705SXin Li DstReachability.resize(analyzed.size(), false); 48*67e74705SXin Li 49*67e74705SXin Li // Start searching from the destination node, since we commonly will perform 50*67e74705SXin Li // multiple queries relating to a destination node. 51*67e74705SXin Li worklist.push_back(Dst); 52*67e74705SXin Li bool firstRun = true; 53*67e74705SXin Li 54*67e74705SXin Li while (!worklist.empty()) { 55*67e74705SXin Li const CFGBlock *block = worklist.pop_back_val(); 56*67e74705SXin Li 57*67e74705SXin Li if (visited[block->getBlockID()]) 58*67e74705SXin Li continue; 59*67e74705SXin Li visited[block->getBlockID()] = true; 60*67e74705SXin Li 61*67e74705SXin Li // Update reachability information for this node -> Dst 62*67e74705SXin Li if (!firstRun) { 63*67e74705SXin Li // Don't insert Dst -> Dst unless it was a predecessor of itself 64*67e74705SXin Li DstReachability[block->getBlockID()] = true; 65*67e74705SXin Li } 66*67e74705SXin Li else 67*67e74705SXin Li firstRun = false; 68*67e74705SXin Li 69*67e74705SXin Li // Add the predecessors to the worklist. 70*67e74705SXin Li for (CFGBlock::const_pred_iterator i = block->pred_begin(), 71*67e74705SXin Li e = block->pred_end(); i != e; ++i) { 72*67e74705SXin Li if (*i) 73*67e74705SXin Li worklist.push_back(*i); 74*67e74705SXin Li } 75*67e74705SXin Li } 76*67e74705SXin Li } 77