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> > 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> > 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> > 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> > 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