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