Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:23

0001 //===- PostOrderCFGView.h - Post order view of CFG blocks -------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file implements post order view of the blocks in a CFG.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
0014 #define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
0015 
0016 #include "clang/Analysis/AnalysisDeclContext.h"
0017 #include "clang/Analysis/CFG.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "llvm/ADT/BitVector.h"
0020 #include "llvm/ADT/DenseMap.h"
0021 #include "llvm/ADT/PostOrderIterator.h"
0022 #include <utility>
0023 #include <vector>
0024 
0025 namespace clang {
0026 
0027 class PostOrderCFGView : public ManagedAnalysis {
0028   virtual void anchor();
0029 
0030 public:
0031   /// Implements a set of CFGBlocks using a BitVector.
0032   ///
0033   /// This class contains a minimal interface, primarily dictated by the SetType
0034   /// template parameter of the llvm::po_iterator template, as used with
0035   /// external storage. We also use this set to keep track of which CFGBlocks we
0036   /// visit during the analysis.
0037   class CFGBlockSet {
0038     llvm::BitVector VisitedBlockIDs;
0039 
0040   public:
0041     // po_iterator requires this iterator, but the only interface needed is the
0042     // value_type type.
0043     struct iterator { using value_type = const CFGBlock *; };
0044 
0045     CFGBlockSet() = default;
0046     CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {}
0047 
0048     /// Set the bit associated with a particular CFGBlock.
0049     /// This is the important method for the SetType template parameter.
0050     std::pair<std::nullopt_t, bool> insert(const CFGBlock *Block) {
0051       // Note that insert() is called by po_iterator, which doesn't check to
0052       // make sure that Block is non-null.  Moreover, the CFGBlock iterator will
0053       // occasionally hand out null pointers for pruned edges, so we catch those
0054       // here.
0055       if (!Block)
0056         return std::make_pair(std::nullopt,
0057                               false); // if an edge is trivially false.
0058       if (VisitedBlockIDs.test(Block->getBlockID()))
0059         return std::make_pair(std::nullopt, false);
0060       VisitedBlockIDs.set(Block->getBlockID());
0061       return std::make_pair(std::nullopt, true);
0062     }
0063 
0064     /// Check if the bit for a CFGBlock has been already set.
0065     /// This method is for tracking visited blocks in the main threadsafety
0066     /// loop. Block must not be null.
0067     bool alreadySet(const CFGBlock *Block) {
0068       return VisitedBlockIDs.test(Block->getBlockID());
0069     }
0070   };
0071 
0072 private:
0073   // The CFG orders the blocks of loop bodies before those of loop successors
0074   // (both numerically, and in the successor order of the loop condition
0075   // block). So, RPO necessarily reverses that order, placing the loop successor
0076   // *before* the loop body. For many analyses, particularly those that converge
0077   // to a fixpoint, this results in potentially significant extra work because
0078   // loop successors will necessarily need to be reconsidered once the algorithm
0079   // has reached a fixpoint on the loop body.
0080   //
0081   // This definition of CFG graph traits reverses the order of children, so that
0082   // loop bodies will come first in an RPO.
0083   struct CFGLoopBodyFirstTraits {
0084     using NodeRef = const ::clang::CFGBlock *;
0085     using ChildIteratorType = ::clang::CFGBlock::const_succ_reverse_iterator;
0086 
0087     static ChildIteratorType child_begin(NodeRef N) { return N->succ_rbegin(); }
0088     static ChildIteratorType child_end(NodeRef N) { return N->succ_rend(); }
0089 
0090     using nodes_iterator = ::clang::CFG::const_iterator;
0091 
0092     static NodeRef getEntryNode(const ::clang::CFG *F) {
0093       return &F->getEntry();
0094     }
0095 
0096     static nodes_iterator nodes_begin(const ::clang::CFG *F) {
0097       return F->nodes_begin();
0098     }
0099 
0100     static nodes_iterator nodes_end(const ::clang::CFG *F) {
0101       return F->nodes_end();
0102     }
0103 
0104     static unsigned size(const ::clang::CFG *F) { return F->size(); }
0105   };
0106   using po_iterator =
0107       llvm::po_iterator<const CFG *, CFGBlockSet, true, CFGLoopBodyFirstTraits>;
0108   std::vector<const CFGBlock *> Blocks;
0109 
0110   using BlockOrderTy = llvm::DenseMap<const CFGBlock *, unsigned>;
0111   BlockOrderTy BlockOrder;
0112 
0113 public:
0114   friend struct BlockOrderCompare;
0115 
0116   using iterator = std::vector<const CFGBlock *>::reverse_iterator;
0117   using const_iterator = std::vector<const CFGBlock *>::const_reverse_iterator;
0118 
0119   PostOrderCFGView(const CFG *cfg);
0120 
0121   iterator begin() { return Blocks.rbegin(); }
0122   iterator end() { return Blocks.rend(); }
0123 
0124   const_iterator begin() const { return Blocks.rbegin(); }
0125   const_iterator end() const { return Blocks.rend(); }
0126 
0127   bool empty() const { return begin() == end(); }
0128 
0129   struct BlockOrderCompare {
0130     const PostOrderCFGView &POV;
0131 
0132   public:
0133     BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {}
0134 
0135     bool operator()(const CFGBlock *b1, const CFGBlock *b2) const;
0136   };
0137 
0138   BlockOrderCompare getComparator() const {
0139     return BlockOrderCompare(*this);
0140   }
0141 
0142   // Used by AnalyisContext to construct this object.
0143   static const void *getTag();
0144 
0145   static std::unique_ptr<PostOrderCFGView>
0146   create(AnalysisDeclContext &analysisContext);
0147 };
0148 
0149 } // namespace clang
0150 
0151 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H