Home | History | Annotate | Download | only in Analysis
      1 //===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- 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 // Templates to create dotty viewer and printer passes for GraphTraits graphs.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
     15 #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
     16 
     17 #include "llvm/Analysis/CFGPrinter.h"
     18 #include "llvm/Pass.h"
     19 #include "llvm/Support/FileSystem.h"
     20 
     21 namespace llvm {
     22 
     23 /// \brief Default traits class for extracting a graph from an analysis pass.
     24 ///
     25 /// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
     26 template <typename AnalysisT, typename GraphT = AnalysisT *>
     27 struct DefaultAnalysisGraphTraits {
     28   static GraphT getGraph(AnalysisT *A) { return A; }
     29 };
     30 
     31 template <
     32     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
     33     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
     34 class DOTGraphTraitsViewer : public FunctionPass {
     35 public:
     36   DOTGraphTraitsViewer(StringRef GraphName, char &ID)
     37       : FunctionPass(ID), Name(GraphName) {}
     38 
     39   /// @brief Return true if this function should be processed.
     40   ///
     41   /// An implementation of this class my override this function to indicate that
     42   /// only certain functions should be viewed.
     43   ///
     44   /// @param Analysis The current analysis result for this function.
     45   virtual bool processFunction(Function &F, AnalysisT &Analysis) {
     46     return true;
     47   }
     48 
     49   bool runOnFunction(Function &F) override {
     50     auto &Analysis = getAnalysis<AnalysisT>();
     51 
     52     if (!processFunction(F, Analysis))
     53       return false;
     54 
     55     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
     56     std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
     57     std::string Title = GraphName + " for '" + F.getName().str() + "' function";
     58 
     59     ViewGraph(Graph, Name, IsSimple, Title);
     60 
     61     return false;
     62   }
     63 
     64   void getAnalysisUsage(AnalysisUsage &AU) const override {
     65     AU.setPreservesAll();
     66     AU.addRequired<AnalysisT>();
     67   }
     68 
     69 private:
     70   std::string Name;
     71 };
     72 
     73 template <
     74     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
     75     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
     76 class DOTGraphTraitsPrinter : public FunctionPass {
     77 public:
     78   DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
     79       : FunctionPass(ID), Name(GraphName) {}
     80 
     81   /// @brief Return true if this function should be processed.
     82   ///
     83   /// An implementation of this class my override this function to indicate that
     84   /// only certain functions should be printed.
     85   ///
     86   /// @param Analysis The current analysis result for this function.
     87   virtual bool processFunction(Function &F, AnalysisT &Analysis) {
     88     return true;
     89   }
     90 
     91   bool runOnFunction(Function &F) override {
     92     auto &Analysis = getAnalysis<AnalysisT>();
     93 
     94     if (!processFunction(F, Analysis))
     95       return false;
     96 
     97     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
     98     std::string Filename = Name + "." + F.getName().str() + ".dot";
     99     std::error_code EC;
    100 
    101     errs() << "Writing '" << Filename << "'...";
    102 
    103     raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
    104     std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
    105     std::string Title = GraphName + " for '" + F.getName().str() + "' function";
    106 
    107     if (!EC)
    108       WriteGraph(File, Graph, IsSimple, Title);
    109     else
    110       errs() << "  error opening file for writing!";
    111     errs() << "\n";
    112 
    113     return false;
    114   }
    115 
    116   void getAnalysisUsage(AnalysisUsage &AU) const override {
    117     AU.setPreservesAll();
    118     AU.addRequired<AnalysisT>();
    119   }
    120 
    121 private:
    122   std::string Name;
    123 };
    124 
    125 template <
    126     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
    127     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
    128 class DOTGraphTraitsModuleViewer : public ModulePass {
    129 public:
    130   DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
    131       : ModulePass(ID), Name(GraphName) {}
    132 
    133   bool runOnModule(Module &M) override {
    134     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
    135     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
    136 
    137     ViewGraph(Graph, Name, IsSimple, Title);
    138 
    139     return false;
    140   }
    141 
    142   void getAnalysisUsage(AnalysisUsage &AU) const override {
    143     AU.setPreservesAll();
    144     AU.addRequired<AnalysisT>();
    145   }
    146 
    147 private:
    148   std::string Name;
    149 };
    150 
    151 template <
    152     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
    153     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
    154 class DOTGraphTraitsModulePrinter : public ModulePass {
    155 public:
    156   DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
    157       : ModulePass(ID), Name(GraphName) {}
    158 
    159   bool runOnModule(Module &M) override {
    160     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
    161     std::string Filename = Name + ".dot";
    162     std::error_code EC;
    163 
    164     errs() << "Writing '" << Filename << "'...";
    165 
    166     raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
    167     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
    168 
    169     if (!EC)
    170       WriteGraph(File, Graph, IsSimple, Title);
    171     else
    172       errs() << "  error opening file for writing!";
    173     errs() << "\n";
    174 
    175     return false;
    176   }
    177 
    178   void getAnalysisUsage(AnalysisUsage &AU) const override {
    179     AU.setPreservesAll();
    180     AU.addRequired<AnalysisT>();
    181   }
    182 
    183 private:
    184   std::string Name;
    185 };
    186 
    187 } // end namespace llvm
    188 
    189 #endif
    190