Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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/Support/FileSystem.h"
18
#include "llvm/Support/GraphWriter.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::Result *', and pass it through
25
template <typename Result, typename GraphT = Result *>
26
struct DefaultAnalysisGraphTraits {
27
  static GraphT getGraph(Result R) { return &R; }
28
};
29
 
30
template <typename GraphT>
31
void viewGraphForFunction(Function &F, GraphT Graph, StringRef Name,
32
                          bool IsSimple) {
33
  std::string GraphName = DOTGraphTraits<GraphT *>::getGraphName(&Graph);
34
 
35
  ViewGraph(Graph, Name, IsSimple,
36
            GraphName + " for '" + F.getName() + "' function");
37
}
38
 
39
template <typename AnalysisT, bool IsSimple,
40
          typename GraphT = typename AnalysisT::Result *,
41
          typename AnalysisGraphTraitsT =
42
              DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
43
struct DOTGraphTraitsViewer
44
    : PassInfoMixin<DOTGraphTraitsViewer<AnalysisT, IsSimple, GraphT,
45
                                         AnalysisGraphTraitsT>> {
46
  DOTGraphTraitsViewer(StringRef GraphName) : Name(GraphName) {}
47
 
48
  /// Return true if this function should be processed.
49
  ///
50
  /// An implementation of this class my override this function to indicate that
51
  /// only certain functions should be viewed.
52
  ///
53
  /// @param Result The current analysis result for this function.
54
  virtual bool processFunction(Function &F,
55
                               const typename AnalysisT::Result &Result) {
56
    return true;
57
  }
58
 
59
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
60
    auto &Result = FAM.getResult<AnalysisT>(F);
61
    if (!processFunction(F, Result))
62
      return PreservedAnalyses::all();
63
 
64
    GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
65
    viewGraphForFunction(F, Graph, Name, IsSimple);
66
 
67
    return PreservedAnalyses::all();
68
  };
69
 
70
protected:
71
  /// Avoid compiler warning "has virtual functions but non-virtual destructor
72
  /// [-Wnon-virtual-dtor]" in derived classes.
73
  ///
74
  /// DOTGraphTraitsViewer is also used as a mixin for avoiding repeated
75
  /// implementation of viewer passes, ie there should be no
76
  /// runtime-polymorphisms/downcasting involving this class and hence no
77
  /// virtual destructor needed. Making this dtor protected stops accidental
78
  /// invocation when the derived class destructor should have been called.
79
  /// Those derived classes sould be marked final to avoid the warning.
80
  ~DOTGraphTraitsViewer() {}
81
 
82
private:
83
  StringRef Name;
84
};
85
 
86
template <typename GraphT>
87
void printGraphForFunction(Function &F, GraphT Graph, StringRef Name,
88
                           bool IsSimple) {
89
  std::string Filename = Name.str() + "." + F.getName().str() + ".dot";
90
  std::error_code EC;
91
 
92
  errs() << "Writing '" << Filename << "'...";
93
 
94
  raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
95
  std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
96
 
97
  if (!EC)
98
    WriteGraph(File, Graph, IsSimple,
99
               GraphName + " for '" + F.getName() + "' function");
100
  else
101
    errs() << "  error opening file for writing!";
102
  errs() << "\n";
103
}
104
 
105
template <typename AnalysisT, bool IsSimple,
106
          typename GraphT = typename AnalysisT::Result *,
107
          typename AnalysisGraphTraitsT =
108
              DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
109
struct DOTGraphTraitsPrinter
110
    : PassInfoMixin<DOTGraphTraitsPrinter<AnalysisT, IsSimple, GraphT,
111
                                          AnalysisGraphTraitsT>> {
112
  DOTGraphTraitsPrinter(StringRef GraphName) : Name(GraphName) {}
113
 
114
  /// Return true if this function should be processed.
115
  ///
116
  /// An implementation of this class my override this function to indicate that
117
  /// only certain functions should be viewed.
118
  ///
119
  /// @param Result The current analysis result for this function.
120
  virtual bool processFunction(Function &F,
121
                               const typename AnalysisT::Result &Result) {
122
    return true;
123
  }
124
 
125
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
126
    auto &Result = FAM.getResult<AnalysisT>(F);
127
    if (!processFunction(F, Result))
128
      return PreservedAnalyses::all();
129
 
130
    GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
131
 
132
    printGraphForFunction(F, Graph, Name, IsSimple);
133
 
134
    return PreservedAnalyses::all();
135
  };
136
 
137
protected:
138
  /// Avoid compiler warning "has virtual functions but non-virtual destructor
139
  /// [-Wnon-virtual-dtor]" in derived classes.
140
  ///
141
  /// DOTGraphTraitsPrinter is also used as a mixin for avoiding repeated
142
  /// implementation of printer passes, ie there should be no
143
  /// runtime-polymorphisms/downcasting involving this class and hence no
144
  /// virtual destructor needed. Making this dtor protected stops accidental
145
  /// invocation when the derived class destructor should have been called.
146
  /// Those derived classes sould be marked final to avoid the warning.
147
  ~DOTGraphTraitsPrinter() {}
148
 
149
private:
150
  StringRef Name;
151
};
152
 
153
/// Default traits class for extracting a graph from an analysis pass.
154
///
155
/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
156
template <typename AnalysisT, typename GraphT = AnalysisT *>
157
struct LegacyDefaultAnalysisGraphTraits {
158
  static GraphT getGraph(AnalysisT *A) { return A; }
159
};
160
 
161
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
162
          typename AnalysisGraphTraitsT =
163
              LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
164
class DOTGraphTraitsViewerWrapperPass : public FunctionPass {
165
public:
166
  DOTGraphTraitsViewerWrapperPass(StringRef GraphName, char &ID)
167
      : FunctionPass(ID), Name(GraphName) {}
168
 
169
  /// Return true if this function should be processed.
170
  ///
171
  /// An implementation of this class my override this function to indicate that
172
  /// only certain functions should be viewed.
173
  ///
174
  /// @param Analysis The current analysis result for this function.
175
  virtual bool processFunction(Function &F, AnalysisT &Analysis) {
176
    return true;
177
  }
178
 
179
  bool runOnFunction(Function &F) override {
180
    auto &Analysis = getAnalysis<AnalysisT>();
181
 
182
    if (!processFunction(F, Analysis))
183
      return false;
184
 
185
    GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
186
    viewGraphForFunction(F, Graph, Name, IsSimple);
187
 
188
    return false;
189
  }
190
 
191
  void getAnalysisUsage(AnalysisUsage &AU) const override {
192
    AU.setPreservesAll();
193
    AU.addRequired<AnalysisT>();
194
  }
195
 
196
private:
197
  std::string Name;
198
};
199
 
200
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
201
          typename AnalysisGraphTraitsT =
202
              LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
203
class DOTGraphTraitsPrinterWrapperPass : public FunctionPass {
204
public:
205
  DOTGraphTraitsPrinterWrapperPass(StringRef GraphName, char &ID)
206
      : FunctionPass(ID), Name(GraphName) {}
207
 
208
  /// Return true if this function should be processed.
209
  ///
210
  /// An implementation of this class my override this function to indicate that
211
  /// only certain functions should be printed.
212
  ///
213
  /// @param Analysis The current analysis result for this function.
214
  virtual bool processFunction(Function &F, AnalysisT &Analysis) {
215
    return true;
216
  }
217
 
218
  bool runOnFunction(Function &F) override {
219
    auto &Analysis = getAnalysis<AnalysisT>();
220
 
221
    if (!processFunction(F, Analysis))
222
      return false;
223
 
224
    GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
225
    printGraphForFunction(F, Graph, Name, IsSimple);
226
 
227
    return false;
228
  }
229
 
230
  void getAnalysisUsage(AnalysisUsage &AU) const override {
231
    AU.setPreservesAll();
232
    AU.addRequired<AnalysisT>();
233
  }
234
 
235
private:
236
  std::string Name;
237
};
238
 
239
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
240
          typename AnalysisGraphTraitsT =
241
              LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
242
class DOTGraphTraitsModuleViewerWrapperPass : public ModulePass {
243
public:
244
  DOTGraphTraitsModuleViewerWrapperPass(StringRef GraphName, char &ID)
245
      : ModulePass(ID), Name(GraphName) {}
246
 
247
  bool runOnModule(Module &M) override {
248
    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
249
    std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
250
 
251
    ViewGraph(Graph, Name, IsSimple, Title);
252
 
253
    return false;
254
  }
255
 
256
  void getAnalysisUsage(AnalysisUsage &AU) const override {
257
    AU.setPreservesAll();
258
    AU.addRequired<AnalysisT>();
259
  }
260
 
261
private:
262
  std::string Name;
263
};
264
 
265
template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
266
          typename AnalysisGraphTraitsT =
267
              LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
268
class DOTGraphTraitsModulePrinterWrapperPass : public ModulePass {
269
public:
270
  DOTGraphTraitsModulePrinterWrapperPass(StringRef GraphName, char &ID)
271
      : ModulePass(ID), Name(GraphName) {}
272
 
273
  bool runOnModule(Module &M) override {
274
    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
275
    std::string Filename = Name + ".dot";
276
    std::error_code EC;
277
 
278
    errs() << "Writing '" << Filename << "'...";
279
 
280
    raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
281
    std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
282
 
283
    if (!EC)
284
      WriteGraph(File, Graph, IsSimple, Title);
285
    else
286
      errs() << "  error opening file for writing!";
287
    errs() << "\n";
288
 
289
    return false;
290
  }
291
 
292
  void getAnalysisUsage(AnalysisUsage &AU) const override {
293
    AU.setPreservesAll();
294
    AU.addRequired<AnalysisT>();
295
  }
296
 
297
private:
298
  std::string Name;
299
};
300
 
301
template <typename GraphT>
302
void WriteDOTGraphToFile(Function &F, GraphT &&Graph,
303
                         std::string FileNamePrefix, bool IsSimple) {
304
  std::string Filename = FileNamePrefix + "." + F.getName().str() + ".dot";
305
  std::error_code EC;
306
 
307
  errs() << "Writing '" << Filename << "'...";
308
 
309
  raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
310
  std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
311
  std::string Title = GraphName + " for '" + F.getName().str() + "' function";
312
 
313
  if (!EC)
314
    WriteGraph(File, Graph, IsSimple, Title);
315
  else
316
    errs() << "  error opening file for writing!";
317
  errs() << "\n";
318
}
319
 
320
} // end namespace llvm
321
 
322
#endif