- //===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Templates to create dotty viewer and printer passes for GraphTraits graphs. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H 
- #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H 
-   
- #include "llvm/Analysis/CFGPrinter.h" 
- #include "llvm/Support/FileSystem.h" 
- #include "llvm/Support/GraphWriter.h" 
-   
- namespace llvm { 
-   
- /// Default traits class for extracting a graph from an analysis pass. 
- /// 
- /// This assumes that 'GraphT' is 'AnalysisT::Result *', and pass it through 
- template <typename Result, typename GraphT = Result *> 
- struct DefaultAnalysisGraphTraits { 
-   static GraphT getGraph(Result R) { return &R; } 
- }; 
-   
- template <typename GraphT> 
- void viewGraphForFunction(Function &F, GraphT Graph, StringRef Name, 
-                           bool IsSimple) { 
-   std::string GraphName = DOTGraphTraits<GraphT *>::getGraphName(&Graph); 
-   
-   ViewGraph(Graph, Name, IsSimple, 
-             GraphName + " for '" + F.getName() + "' function"); 
- } 
-   
- template <typename AnalysisT, bool IsSimple, 
-           typename GraphT = typename AnalysisT::Result *, 
-           typename AnalysisGraphTraitsT = 
-               DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>> 
- struct DOTGraphTraitsViewer 
-     : PassInfoMixin<DOTGraphTraitsViewer<AnalysisT, IsSimple, GraphT, 
-                                          AnalysisGraphTraitsT>> { 
-   DOTGraphTraitsViewer(StringRef GraphName) : Name(GraphName) {} 
-   
-   /// Return true if this function should be processed. 
-   /// 
-   /// An implementation of this class my override this function to indicate that 
-   /// only certain functions should be viewed. 
-   /// 
-   /// @param Result The current analysis result for this function. 
-   virtual bool processFunction(Function &F, 
-                                const typename AnalysisT::Result &Result) { 
-     return true; 
-   } 
-   
-   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) { 
-     auto &Result = FAM.getResult<AnalysisT>(F); 
-     if (!processFunction(F, Result)) 
-       return PreservedAnalyses::all(); 
-   
-     GraphT Graph = AnalysisGraphTraitsT::getGraph(Result); 
-     viewGraphForFunction(F, Graph, Name, IsSimple); 
-   
-     return PreservedAnalyses::all(); 
-   }; 
-   
- protected: 
-   /// Avoid compiler warning "has virtual functions but non-virtual destructor 
-   /// [-Wnon-virtual-dtor]" in derived classes. 
-   /// 
-   /// DOTGraphTraitsViewer is also used as a mixin for avoiding repeated 
-   /// implementation of viewer passes, ie there should be no 
-   /// runtime-polymorphisms/downcasting involving this class and hence no 
-   /// virtual destructor needed. Making this dtor protected stops accidental 
-   /// invocation when the derived class destructor should have been called. 
-   /// Those derived classes sould be marked final to avoid the warning. 
-   ~DOTGraphTraitsViewer() {} 
-   
- private: 
-   StringRef Name; 
- }; 
-   
- template <typename GraphT> 
- void printGraphForFunction(Function &F, GraphT Graph, StringRef Name, 
-                            bool IsSimple) { 
-   std::string Filename = Name.str() + "." + F.getName().str() + ".dot"; 
-   std::error_code EC; 
-   
-   errs() << "Writing '" << Filename << "'..."; 
-   
-   raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF); 
-   std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); 
-   
-   if (!EC) 
-     WriteGraph(File, Graph, IsSimple, 
-                GraphName + " for '" + F.getName() + "' function"); 
-   else 
-     errs() << "  error opening file for writing!"; 
-   errs() << "\n"; 
- } 
-   
- template <typename AnalysisT, bool IsSimple, 
-           typename GraphT = typename AnalysisT::Result *, 
-           typename AnalysisGraphTraitsT = 
-               DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>> 
- struct DOTGraphTraitsPrinter 
-     : PassInfoMixin<DOTGraphTraitsPrinter<AnalysisT, IsSimple, GraphT, 
-                                           AnalysisGraphTraitsT>> { 
-   DOTGraphTraitsPrinter(StringRef GraphName) : Name(GraphName) {} 
-   
-   /// Return true if this function should be processed. 
-   /// 
-   /// An implementation of this class my override this function to indicate that 
-   /// only certain functions should be viewed. 
-   /// 
-   /// @param Result The current analysis result for this function. 
-   virtual bool processFunction(Function &F, 
-                                const typename AnalysisT::Result &Result) { 
-     return true; 
-   } 
-   
-   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) { 
-     auto &Result = FAM.getResult<AnalysisT>(F); 
-     if (!processFunction(F, Result)) 
-       return PreservedAnalyses::all(); 
-   
-     GraphT Graph = AnalysisGraphTraitsT::getGraph(Result); 
-   
-     printGraphForFunction(F, Graph, Name, IsSimple); 
-   
-     return PreservedAnalyses::all(); 
-   }; 
-   
- protected: 
-   /// Avoid compiler warning "has virtual functions but non-virtual destructor 
-   /// [-Wnon-virtual-dtor]" in derived classes. 
-   /// 
-   /// DOTGraphTraitsPrinter is also used as a mixin for avoiding repeated 
-   /// implementation of printer passes, ie there should be no 
-   /// runtime-polymorphisms/downcasting involving this class and hence no 
-   /// virtual destructor needed. Making this dtor protected stops accidental 
-   /// invocation when the derived class destructor should have been called. 
-   /// Those derived classes sould be marked final to avoid the warning. 
-   ~DOTGraphTraitsPrinter() {} 
-   
- private: 
-   StringRef Name; 
- }; 
-   
- /// Default traits class for extracting a graph from an analysis pass. 
- /// 
- /// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through. 
- template <typename AnalysisT, typename GraphT = AnalysisT *> 
- struct LegacyDefaultAnalysisGraphTraits { 
-   static GraphT getGraph(AnalysisT *A) { return A; } 
- }; 
-   
- template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 
-           typename AnalysisGraphTraitsT = 
-               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>> 
- class DOTGraphTraitsViewerWrapperPass : public FunctionPass { 
- public: 
-   DOTGraphTraitsViewerWrapperPass(StringRef GraphName, char &ID) 
-       : FunctionPass(ID), Name(GraphName) {} 
-   
-   /// Return true if this function should be processed. 
-   /// 
-   /// An implementation of this class my override this function to indicate that 
-   /// only certain functions should be viewed. 
-   /// 
-   /// @param Analysis The current analysis result for this function. 
-   virtual bool processFunction(Function &F, AnalysisT &Analysis) { 
-     return true; 
-   } 
-   
-   bool runOnFunction(Function &F) override { 
-     auto &Analysis = getAnalysis<AnalysisT>(); 
-   
-     if (!processFunction(F, Analysis)) 
-       return false; 
-   
-     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis); 
-     viewGraphForFunction(F, Graph, Name, IsSimple); 
-   
-     return false; 
-   } 
-   
-   void getAnalysisUsage(AnalysisUsage &AU) const override { 
-     AU.setPreservesAll(); 
-     AU.addRequired<AnalysisT>(); 
-   } 
-   
- private: 
-   std::string Name; 
- }; 
-   
- template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 
-           typename AnalysisGraphTraitsT = 
-               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>> 
- class DOTGraphTraitsPrinterWrapperPass : public FunctionPass { 
- public: 
-   DOTGraphTraitsPrinterWrapperPass(StringRef GraphName, char &ID) 
-       : FunctionPass(ID), Name(GraphName) {} 
-   
-   /// Return true if this function should be processed. 
-   /// 
-   /// An implementation of this class my override this function to indicate that 
-   /// only certain functions should be printed. 
-   /// 
-   /// @param Analysis The current analysis result for this function. 
-   virtual bool processFunction(Function &F, AnalysisT &Analysis) { 
-     return true; 
-   } 
-   
-   bool runOnFunction(Function &F) override { 
-     auto &Analysis = getAnalysis<AnalysisT>(); 
-   
-     if (!processFunction(F, Analysis)) 
-       return false; 
-   
-     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis); 
-     printGraphForFunction(F, Graph, Name, IsSimple); 
-   
-     return false; 
-   } 
-   
-   void getAnalysisUsage(AnalysisUsage &AU) const override { 
-     AU.setPreservesAll(); 
-     AU.addRequired<AnalysisT>(); 
-   } 
-   
- private: 
-   std::string Name; 
- }; 
-   
- template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 
-           typename AnalysisGraphTraitsT = 
-               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>> 
- class DOTGraphTraitsModuleViewerWrapperPass : public ModulePass { 
- public: 
-   DOTGraphTraitsModuleViewerWrapperPass(StringRef GraphName, char &ID) 
-       : ModulePass(ID), Name(GraphName) {} 
-   
-   bool runOnModule(Module &M) override { 
-     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); 
-     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); 
-   
-     ViewGraph(Graph, Name, IsSimple, Title); 
-   
-     return false; 
-   } 
-   
-   void getAnalysisUsage(AnalysisUsage &AU) const override { 
-     AU.setPreservesAll(); 
-     AU.addRequired<AnalysisT>(); 
-   } 
-   
- private: 
-   std::string Name; 
- }; 
-   
- template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 
-           typename AnalysisGraphTraitsT = 
-               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>> 
- class DOTGraphTraitsModulePrinterWrapperPass : public ModulePass { 
- public: 
-   DOTGraphTraitsModulePrinterWrapperPass(StringRef GraphName, char &ID) 
-       : ModulePass(ID), Name(GraphName) {} 
-   
-   bool runOnModule(Module &M) override { 
-     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); 
-     std::string Filename = Name + ".dot"; 
-     std::error_code EC; 
-   
-     errs() << "Writing '" << Filename << "'..."; 
-   
-     raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF); 
-     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); 
-   
-     if (!EC) 
-       WriteGraph(File, Graph, IsSimple, Title); 
-     else 
-       errs() << "  error opening file for writing!"; 
-     errs() << "\n"; 
-   
-     return false; 
-   } 
-   
-   void getAnalysisUsage(AnalysisUsage &AU) const override { 
-     AU.setPreservesAll(); 
-     AU.addRequired<AnalysisT>(); 
-   } 
-   
- private: 
-   std::string Name; 
- }; 
-   
- template <typename GraphT> 
- void WriteDOTGraphToFile(Function &F, GraphT &&Graph, 
-                          std::string FileNamePrefix, bool IsSimple) { 
-   std::string Filename = FileNamePrefix + "." + F.getName().str() + ".dot"; 
-   std::error_code EC; 
-   
-   errs() << "Writing '" << Filename << "'..."; 
-   
-   raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF); 
-   std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); 
-   std::string Title = GraphName + " for '" + F.getName().str() + "' function"; 
-   
-   if (!EC) 
-     WriteGraph(File, Graph, IsSimple, Title); 
-   else 
-     errs() << "  error opening file for writing!"; 
-   errs() << "\n"; 
- } 
-   
- } // end namespace llvm 
-   
- #endif 
-