clang API Documentation
00001 //===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-// 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 post order view of the blocks in a CFG. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_CLANG_POSTORDER_CFGVIEW 00015 #define LLVM_CLANG_POSTORDER_CFGVIEW 00016 00017 #include <vector> 00018 //#include <algorithm> 00019 00020 #include "llvm/ADT/PostOrderIterator.h" 00021 #include "llvm/ADT/DenseMap.h" 00022 #include "llvm/ADT/BitVector.h" 00023 00024 #include "clang/Analysis/AnalysisContext.h" 00025 #include "clang/Analysis/CFG.h" 00026 00027 namespace clang { 00028 00029 class PostOrderCFGView : public ManagedAnalysis { 00030 virtual void anchor(); 00031 public: 00032 /// \brief Implements a set of CFGBlocks using a BitVector. 00033 /// 00034 /// This class contains a minimal interface, primarily dictated by the SetType 00035 /// template parameter of the llvm::po_iterator template, as used with 00036 /// external storage. We also use this set to keep track of which CFGBlocks we 00037 /// visit during the analysis. 00038 class CFGBlockSet { 00039 llvm::BitVector VisitedBlockIDs; 00040 public: 00041 // po_iterator requires this iterator, but the only interface needed is the 00042 // value_type typedef. 00043 struct iterator { typedef const CFGBlock *value_type; }; 00044 00045 CFGBlockSet() {} 00046 CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {} 00047 00048 /// \brief Set the bit associated with a particular CFGBlock. 00049 /// This is the important method for the SetType template parameter. 00050 bool insert(const CFGBlock *Block) { 00051 // Note that insert() is called by po_iterator, which doesn't check to 00052 // make sure that Block is non-null. Moreover, the CFGBlock iterator will 00053 // occasionally hand out null pointers for pruned edges, so we catch those 00054 // here. 00055 if (Block == 0) 00056 return false; // if an edge is trivially false. 00057 if (VisitedBlockIDs.test(Block->getBlockID())) 00058 return false; 00059 VisitedBlockIDs.set(Block->getBlockID()); 00060 return true; 00061 } 00062 00063 /// \brief Check if the bit for a CFGBlock has been already set. 00064 /// This method is for tracking visited blocks in the main threadsafety 00065 /// loop. Block must not be null. 00066 bool alreadySet(const CFGBlock *Block) { 00067 return VisitedBlockIDs.test(Block->getBlockID()); 00068 } 00069 }; 00070 00071 private: 00072 typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator; 00073 std::vector<const CFGBlock*> Blocks; 00074 00075 typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy; 00076 BlockOrderTy BlockOrder; 00077 00078 public: 00079 typedef std::vector<const CFGBlock*>::reverse_iterator iterator; 00080 00081 PostOrderCFGView(const CFG *cfg); 00082 00083 iterator begin() { return Blocks.rbegin(); } 00084 iterator end() { return Blocks.rend(); } 00085 00086 bool empty() { return begin() == end(); } 00087 00088 struct BlockOrderCompare; 00089 friend struct BlockOrderCompare; 00090 00091 struct BlockOrderCompare { 00092 const PostOrderCFGView &POV; 00093 public: 00094 BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {} 00095 bool operator()(const CFGBlock *b1, const CFGBlock *b2) const; 00096 }; 00097 00098 BlockOrderCompare getComparator() const { 00099 return BlockOrderCompare(*this); 00100 } 00101 00102 // Used by AnalyisContext to construct this object. 00103 static const void *getTag(); 00104 00105 static PostOrderCFGView *create(AnalysisDeclContext &analysisContext); 00106 }; 00107 00108 } // end clang namespace 00109 00110 #endif 00111