Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Templates to create dotty viewer and printer passes for GraphTraits graphs.
  10. //
  11. //===----------------------------------------------------------------------===//
  12.  
  13. #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
  14. #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
  15.  
  16. #include "llvm/Analysis/CFGPrinter.h"
  17. #include "llvm/Support/FileSystem.h"
  18. #include "llvm/Support/GraphWriter.h"
  19.  
  20. namespace llvm {
  21.  
  22. /// Default traits class for extracting a graph from an analysis pass.
  23. ///
  24. /// This assumes that 'GraphT' is 'AnalysisT::Result *', and pass it through
  25. template <typename Result, typename GraphT = Result *>
  26. struct DefaultAnalysisGraphTraits {
  27.   static GraphT getGraph(Result R) { return &R; }
  28. };
  29.  
  30. template <typename GraphT>
  31. void viewGraphForFunction(Function &F, GraphT Graph, StringRef Name,
  32.                           bool IsSimple) {
  33.   std::string GraphName = DOTGraphTraits<GraphT *>::getGraphName(&Graph);
  34.  
  35.   ViewGraph(Graph, Name, IsSimple,
  36.             GraphName + " for '" + F.getName() + "' function");
  37. }
  38.  
  39. template <typename AnalysisT, bool IsSimple,
  40.           typename GraphT = typename AnalysisT::Result *,
  41.           typename AnalysisGraphTraitsT =
  42.               DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
  43. struct DOTGraphTraitsViewer
  44.     : PassInfoMixin<DOTGraphTraitsViewer<AnalysisT, IsSimple, GraphT,
  45.                                          AnalysisGraphTraitsT>> {
  46.   DOTGraphTraitsViewer(StringRef GraphName) : Name(GraphName) {}
  47.  
  48.   /// Return true if this function should be processed.
  49.   ///
  50.   /// An implementation of this class my override this function to indicate that
  51.   /// only certain functions should be viewed.
  52.   ///
  53.   /// @param Result The current analysis result for this function.
  54.   virtual bool processFunction(Function &F,
  55.                                const typename AnalysisT::Result &Result) {
  56.     return true;
  57.   }
  58.  
  59.   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
  60.     auto &Result = FAM.getResult<AnalysisT>(F);
  61.     if (!processFunction(F, Result))
  62.       return PreservedAnalyses::all();
  63.  
  64.     GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
  65.     viewGraphForFunction(F, Graph, Name, IsSimple);
  66.  
  67.     return PreservedAnalyses::all();
  68.   };
  69.  
  70. protected:
  71.   /// Avoid compiler warning "has virtual functions but non-virtual destructor
  72.   /// [-Wnon-virtual-dtor]" in derived classes.
  73.   ///
  74.   /// DOTGraphTraitsViewer is also used as a mixin for avoiding repeated
  75.   /// implementation of viewer passes, ie there should be no
  76.   /// runtime-polymorphisms/downcasting involving this class and hence no
  77.   /// virtual destructor needed. Making this dtor protected stops accidental
  78.   /// invocation when the derived class destructor should have been called.
  79.   /// Those derived classes sould be marked final to avoid the warning.
  80.   ~DOTGraphTraitsViewer() {}
  81.  
  82. private:
  83.   StringRef Name;
  84. };
  85.  
  86. template <typename GraphT>
  87. void printGraphForFunction(Function &F, GraphT Graph, StringRef Name,
  88.                            bool IsSimple) {
  89.   std::string Filename = Name.str() + "." + F.getName().str() + ".dot";
  90.   std::error_code EC;
  91.  
  92.   errs() << "Writing '" << Filename << "'...";
  93.  
  94.   raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  95.   std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
  96.  
  97.   if (!EC)
  98.     WriteGraph(File, Graph, IsSimple,
  99.                GraphName + " for '" + F.getName() + "' function");
  100.   else
  101.     errs() << "  error opening file for writing!";
  102.   errs() << "\n";
  103. }
  104.  
  105. template <typename AnalysisT, bool IsSimple,
  106.           typename GraphT = typename AnalysisT::Result *,
  107.           typename AnalysisGraphTraitsT =
  108.               DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
  109. struct DOTGraphTraitsPrinter
  110.     : PassInfoMixin<DOTGraphTraitsPrinter<AnalysisT, IsSimple, GraphT,
  111.                                           AnalysisGraphTraitsT>> {
  112.   DOTGraphTraitsPrinter(StringRef GraphName) : Name(GraphName) {}
  113.  
  114.   /// Return true if this function should be processed.
  115.   ///
  116.   /// An implementation of this class my override this function to indicate that
  117.   /// only certain functions should be viewed.
  118.   ///
  119.   /// @param Result The current analysis result for this function.
  120.   virtual bool processFunction(Function &F,
  121.                                const typename AnalysisT::Result &Result) {
  122.     return true;
  123.   }
  124.  
  125.   PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
  126.     auto &Result = FAM.getResult<AnalysisT>(F);
  127.     if (!processFunction(F, Result))
  128.       return PreservedAnalyses::all();
  129.  
  130.     GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
  131.  
  132.     printGraphForFunction(F, Graph, Name, IsSimple);
  133.  
  134.     return PreservedAnalyses::all();
  135.   };
  136.  
  137. protected:
  138.   /// Avoid compiler warning "has virtual functions but non-virtual destructor
  139.   /// [-Wnon-virtual-dtor]" in derived classes.
  140.   ///
  141.   /// DOTGraphTraitsPrinter is also used as a mixin for avoiding repeated
  142.   /// implementation of printer passes, ie there should be no
  143.   /// runtime-polymorphisms/downcasting involving this class and hence no
  144.   /// virtual destructor needed. Making this dtor protected stops accidental
  145.   /// invocation when the derived class destructor should have been called.
  146.   /// Those derived classes sould be marked final to avoid the warning.
  147.   ~DOTGraphTraitsPrinter() {}
  148.  
  149. private:
  150.   StringRef Name;
  151. };
  152.  
  153. /// Default traits class for extracting a graph from an analysis pass.
  154. ///
  155. /// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
  156. template <typename AnalysisT, typename GraphT = AnalysisT *>
  157. struct LegacyDefaultAnalysisGraphTraits {
  158.   static GraphT getGraph(AnalysisT *A) { return A; }
  159. };
  160.  
  161. template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  162.           typename AnalysisGraphTraitsT =
  163.               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
  164. class DOTGraphTraitsViewerWrapperPass : public FunctionPass {
  165. public:
  166.   DOTGraphTraitsViewerWrapperPass(StringRef GraphName, char &ID)
  167.       : FunctionPass(ID), Name(GraphName) {}
  168.  
  169.   /// Return true if this function should be processed.
  170.   ///
  171.   /// An implementation of this class my override this function to indicate that
  172.   /// only certain functions should be viewed.
  173.   ///
  174.   /// @param Analysis The current analysis result for this function.
  175.   virtual bool processFunction(Function &F, AnalysisT &Analysis) {
  176.     return true;
  177.   }
  178.  
  179.   bool runOnFunction(Function &F) override {
  180.     auto &Analysis = getAnalysis<AnalysisT>();
  181.  
  182.     if (!processFunction(F, Analysis))
  183.       return false;
  184.  
  185.     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
  186.     viewGraphForFunction(F, Graph, Name, IsSimple);
  187.  
  188.     return false;
  189.   }
  190.  
  191.   void getAnalysisUsage(AnalysisUsage &AU) const override {
  192.     AU.setPreservesAll();
  193.     AU.addRequired<AnalysisT>();
  194.   }
  195.  
  196. private:
  197.   std::string Name;
  198. };
  199.  
  200. template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  201.           typename AnalysisGraphTraitsT =
  202.               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
  203. class DOTGraphTraitsPrinterWrapperPass : public FunctionPass {
  204. public:
  205.   DOTGraphTraitsPrinterWrapperPass(StringRef GraphName, char &ID)
  206.       : FunctionPass(ID), Name(GraphName) {}
  207.  
  208.   /// Return true if this function should be processed.
  209.   ///
  210.   /// An implementation of this class my override this function to indicate that
  211.   /// only certain functions should be printed.
  212.   ///
  213.   /// @param Analysis The current analysis result for this function.
  214.   virtual bool processFunction(Function &F, AnalysisT &Analysis) {
  215.     return true;
  216.   }
  217.  
  218.   bool runOnFunction(Function &F) override {
  219.     auto &Analysis = getAnalysis<AnalysisT>();
  220.  
  221.     if (!processFunction(F, Analysis))
  222.       return false;
  223.  
  224.     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
  225.     printGraphForFunction(F, Graph, Name, IsSimple);
  226.  
  227.     return false;
  228.   }
  229.  
  230.   void getAnalysisUsage(AnalysisUsage &AU) const override {
  231.     AU.setPreservesAll();
  232.     AU.addRequired<AnalysisT>();
  233.   }
  234.  
  235. private:
  236.   std::string Name;
  237. };
  238.  
  239. template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  240.           typename AnalysisGraphTraitsT =
  241.               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
  242. class DOTGraphTraitsModuleViewerWrapperPass : public ModulePass {
  243. public:
  244.   DOTGraphTraitsModuleViewerWrapperPass(StringRef GraphName, char &ID)
  245.       : ModulePass(ID), Name(GraphName) {}
  246.  
  247.   bool runOnModule(Module &M) override {
  248.     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
  249.     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
  250.  
  251.     ViewGraph(Graph, Name, IsSimple, Title);
  252.  
  253.     return false;
  254.   }
  255.  
  256.   void getAnalysisUsage(AnalysisUsage &AU) const override {
  257.     AU.setPreservesAll();
  258.     AU.addRequired<AnalysisT>();
  259.   }
  260.  
  261. private:
  262.   std::string Name;
  263. };
  264.  
  265. template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  266.           typename AnalysisGraphTraitsT =
  267.               LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
  268. class DOTGraphTraitsModulePrinterWrapperPass : public ModulePass {
  269. public:
  270.   DOTGraphTraitsModulePrinterWrapperPass(StringRef GraphName, char &ID)
  271.       : ModulePass(ID), Name(GraphName) {}
  272.  
  273.   bool runOnModule(Module &M) override {
  274.     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
  275.     std::string Filename = Name + ".dot";
  276.     std::error_code EC;
  277.  
  278.     errs() << "Writing '" << Filename << "'...";
  279.  
  280.     raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  281.     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
  282.  
  283.     if (!EC)
  284.       WriteGraph(File, Graph, IsSimple, Title);
  285.     else
  286.       errs() << "  error opening file for writing!";
  287.     errs() << "\n";
  288.  
  289.     return false;
  290.   }
  291.  
  292.   void getAnalysisUsage(AnalysisUsage &AU) const override {
  293.     AU.setPreservesAll();
  294.     AU.addRequired<AnalysisT>();
  295.   }
  296.  
  297. private:
  298.   std::string Name;
  299. };
  300.  
  301. template <typename GraphT>
  302. void WriteDOTGraphToFile(Function &F, GraphT &&Graph,
  303.                          std::string FileNamePrefix, bool IsSimple) {
  304.   std::string Filename = FileNamePrefix + "." + F.getName().str() + ".dot";
  305.   std::error_code EC;
  306.  
  307.   errs() << "Writing '" << Filename << "'...";
  308.  
  309.   raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  310.   std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
  311.   std::string Title = GraphName + " for '" + F.getName().str() + "' function";
  312.  
  313.   if (!EC)
  314.     WriteGraph(File, Graph, IsSimple, Title);
  315.   else
  316.     errs() << "  error opening file for writing!";
  317.   errs() << "\n";
  318. }
  319.  
  320. } // end namespace llvm
  321.  
  322. #endif
  323.