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 21namespace 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. 26template <typename AnalysisT, typename GraphT = AnalysisT *> 27struct DefaultAnalysisGraphTraits { 28 static GraphT getGraph(AnalysisT *A) { return A; } 29}; 30 31template < 32 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 33 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > 34class DOTGraphTraitsViewer : public FunctionPass { 35public: 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 69private: 70 std::string Name; 71}; 72 73template < 74 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 75 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > 76class DOTGraphTraitsPrinter : public FunctionPass { 77public: 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 121private: 122 std::string Name; 123}; 124 125template < 126 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 127 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > 128class DOTGraphTraitsModuleViewer : public ModulePass { 129public: 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 147private: 148 std::string Name; 149}; 150 151template < 152 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, 153 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > 154class DOTGraphTraitsModulePrinter : public ModulePass { 155public: 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 183private: 184 std::string Name; 185}; 186 187} // end namespace llvm 188 189#endif 190