LLVM  mainline
DOTGraphTraitsPass.h
Go to the documentation of this file.
00001 //===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- 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 // Templates to create dotty viewer and printer passes for GraphTraits graphs.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
00015 #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
00016 
00017 #include "llvm/Analysis/CFGPrinter.h"
00018 #include "llvm/Pass.h"
00019 #include "llvm/Support/FileSystem.h"
00020 
00021 namespace llvm {
00022 
00023 /// \brief Default traits class for extracting a graph from an analysis pass.
00024 ///
00025 /// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
00026 template <typename AnalysisT, typename GraphT = AnalysisT *>
00027 struct DefaultAnalysisGraphTraits {
00028   static GraphT getGraph(AnalysisT *A) { return A; }
00029 };
00030 
00031 template <
00032     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
00033     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
00034 class DOTGraphTraitsViewer : public FunctionPass {
00035 public:
00036   DOTGraphTraitsViewer(StringRef GraphName, char &ID)
00037       : FunctionPass(ID), Name(GraphName) {}
00038 
00039   /// @brief Return true if this function should be processed.
00040   ///
00041   /// An implementation of this class my override this function to indicate that
00042   /// only certain functions should be viewed.
00043   ///
00044   /// @param Analysis The current analysis result for this function.
00045   virtual bool processFunction(Function &F, AnalysisT &Analysis) {
00046     return true;
00047   }
00048 
00049   bool runOnFunction(Function &F) override {
00050     auto &Analysis = getAnalysis<AnalysisT>();
00051 
00052     if (!processFunction(F, Analysis))
00053       return false;
00054 
00055     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
00056     std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
00057     std::string Title = GraphName + " for '" + F.getName().str() + "' function";
00058 
00059     ViewGraph(Graph, Name, IsSimple, Title);
00060 
00061     return false;
00062   }
00063 
00064   void getAnalysisUsage(AnalysisUsage &AU) const override {
00065     AU.setPreservesAll();
00066     AU.addRequired<AnalysisT>();
00067   }
00068 
00069 private:
00070   std::string Name;
00071 };
00072 
00073 template <
00074     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
00075     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
00076 class DOTGraphTraitsPrinter : public FunctionPass {
00077 public:
00078   DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
00079       : FunctionPass(ID), Name(GraphName) {}
00080 
00081   /// @brief Return true if this function should be processed.
00082   ///
00083   /// An implementation of this class my override this function to indicate that
00084   /// only certain functions should be printed.
00085   ///
00086   /// @param Analysis The current analysis result for this function.
00087   virtual bool processFunction(Function &F, AnalysisT &Analysis) {
00088     return true;
00089   }
00090 
00091   bool runOnFunction(Function &F) override {
00092     auto &Analysis = getAnalysis<AnalysisT>();
00093 
00094     if (!processFunction(F, Analysis))
00095       return false;
00096 
00097     GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
00098     std::string Filename = Name + "." + F.getName().str() + ".dot";
00099     std::error_code EC;
00100 
00101     errs() << "Writing '" << Filename << "'...";
00102 
00103     raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
00104     std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
00105     std::string Title = GraphName + " for '" + F.getName().str() + "' function";
00106 
00107     if (!EC)
00108       WriteGraph(File, Graph, IsSimple, Title);
00109     else
00110       errs() << "  error opening file for writing!";
00111     errs() << "\n";
00112 
00113     return false;
00114   }
00115 
00116   void getAnalysisUsage(AnalysisUsage &AU) const override {
00117     AU.setPreservesAll();
00118     AU.addRequired<AnalysisT>();
00119   }
00120 
00121 private:
00122   std::string Name;
00123 };
00124 
00125 template <
00126     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
00127     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
00128 class DOTGraphTraitsModuleViewer : public ModulePass {
00129 public:
00130   DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
00131       : ModulePass(ID), Name(GraphName) {}
00132 
00133   bool runOnModule(Module &M) override {
00134     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
00135     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
00136 
00137     ViewGraph(Graph, Name, IsSimple, Title);
00138 
00139     return false;
00140   }
00141 
00142   void getAnalysisUsage(AnalysisUsage &AU) const override {
00143     AU.setPreservesAll();
00144     AU.addRequired<AnalysisT>();
00145   }
00146 
00147 private:
00148   std::string Name;
00149 };
00150 
00151 template <
00152     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
00153     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
00154 class DOTGraphTraitsModulePrinter : public ModulePass {
00155 public:
00156   DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
00157       : ModulePass(ID), Name(GraphName) {}
00158 
00159   bool runOnModule(Module &M) override {
00160     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
00161     std::string Filename = Name + ".dot";
00162     std::error_code EC;
00163 
00164     errs() << "Writing '" << Filename << "'...";
00165 
00166     raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
00167     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
00168 
00169     if (!EC)
00170       WriteGraph(File, Graph, IsSimple, Title);
00171     else
00172       errs() << "  error opening file for writing!";
00173     errs() << "\n";
00174 
00175     return false;
00176   }
00177 
00178   void getAnalysisUsage(AnalysisUsage &AU) const override {
00179     AU.setPreservesAll();
00180     AU.addRequired<AnalysisT>();
00181   }
00182 
00183 private:
00184   std::string Name;
00185 };
00186 
00187 } // end namespace llvm
00188 
00189 #endif