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