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