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 {
getGraphDefaultAnalysisGraphTraits28   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:
DOTGraphTraitsViewer(StringRef GraphName,char & ID)36   DOTGraphTraitsViewer(StringRef GraphName, char &ID)
37       : FunctionPass(ID), Name(GraphName) {}
38 
runOnFunction(Function & F)39   bool runOnFunction(Function &F) override {
40     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
41     std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
42     std::string Title = GraphName + " for '" + F.getName().str() + "' function";
43 
44     ViewGraph(Graph, Name, IsSimple, Title);
45 
46     return false;
47   }
48 
getAnalysisUsage(AnalysisUsage & AU)49   void getAnalysisUsage(AnalysisUsage &AU) const override {
50     AU.setPreservesAll();
51     AU.addRequired<AnalysisT>();
52   }
53 
54 private:
55   std::string Name;
56 };
57 
58 template <
59     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
60     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
61 class DOTGraphTraitsPrinter : public FunctionPass {
62 public:
DOTGraphTraitsPrinter(StringRef GraphName,char & ID)63   DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
64       : FunctionPass(ID), Name(GraphName) {}
65 
runOnFunction(Function & F)66   bool runOnFunction(Function &F) override {
67     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
68     std::string Filename = Name + "." + F.getName().str() + ".dot";
69     std::error_code EC;
70 
71     errs() << "Writing '" << Filename << "'...";
72 
73     raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
74     std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
75     std::string Title = GraphName + " for '" + F.getName().str() + "' function";
76 
77     if (!EC)
78       WriteGraph(File, Graph, IsSimple, Title);
79     else
80       errs() << "  error opening file for writing!";
81     errs() << "\n";
82 
83     return false;
84   }
85 
getAnalysisUsage(AnalysisUsage & AU)86   void getAnalysisUsage(AnalysisUsage &AU) const override {
87     AU.setPreservesAll();
88     AU.addRequired<AnalysisT>();
89   }
90 
91 private:
92   std::string Name;
93 };
94 
95 template <
96     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
97     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
98 class DOTGraphTraitsModuleViewer : public ModulePass {
99 public:
DOTGraphTraitsModuleViewer(StringRef GraphName,char & ID)100   DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
101       : ModulePass(ID), Name(GraphName) {}
102 
runOnModule(Module & M)103   bool runOnModule(Module &M) override {
104     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
105     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
106 
107     ViewGraph(Graph, Name, IsSimple, Title);
108 
109     return false;
110   }
111 
getAnalysisUsage(AnalysisUsage & AU)112   void getAnalysisUsage(AnalysisUsage &AU) const override {
113     AU.setPreservesAll();
114     AU.addRequired<AnalysisT>();
115   }
116 
117 private:
118   std::string Name;
119 };
120 
121 template <
122     typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
123     typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
124 class DOTGraphTraitsModulePrinter : public ModulePass {
125 public:
DOTGraphTraitsModulePrinter(StringRef GraphName,char & ID)126   DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
127       : ModulePass(ID), Name(GraphName) {}
128 
runOnModule(Module & M)129   bool runOnModule(Module &M) override {
130     GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
131     std::string Filename = Name + ".dot";
132     std::error_code EC;
133 
134     errs() << "Writing '" << Filename << "'...";
135 
136     raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
137     std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
138 
139     if (!EC)
140       WriteGraph(File, Graph, IsSimple, Title);
141     else
142       errs() << "  error opening file for writing!";
143     errs() << "\n";
144 
145     return false;
146   }
147 
getAnalysisUsage(AnalysisUsage & AU)148   void getAnalysisUsage(AnalysisUsage &AU) const override {
149     AU.setPreservesAll();
150     AU.addRequired<AnalysisT>();
151   }
152 
153 private:
154   std::string Name;
155 };
156 
157 } // end namespace llvm
158 
159 #endif
160