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