CFGReachabilityAnalysis.cpp 2.5 KB

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