blob: ecf54cd8a680d121da2d5c5158089e1b220ac6ab [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010017
18namespace llvm {
19
Andrew Scullcdfcccc2018-10-05 20:58:37 +010020/// Default traits class for extracting a graph from an analysis pass.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010021///
22/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
23template <typename AnalysisT, typename GraphT = AnalysisT *>
24struct DefaultAnalysisGraphTraits {
25 static GraphT getGraph(AnalysisT *A) { return A; }
26};
27
28template <
29 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
30 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
31class DOTGraphTraitsViewer : public FunctionPass {
32public:
33 DOTGraphTraitsViewer(StringRef GraphName, char &ID)
34 : FunctionPass(ID), Name(GraphName) {}
35
Andrew Scullcdfcccc2018-10-05 20:58:37 +010036 /// Return true if this function should be processed.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010037 ///
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.
42 virtual bool processFunction(Function &F, AnalysisT &Analysis) {
43 return true;
44 }
45
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
61 void getAnalysisUsage(AnalysisUsage &AU) const override {
62 AU.setPreservesAll();
63 AU.addRequired<AnalysisT>();
64 }
65
66private:
67 std::string Name;
68};
69
70template <
71 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
72 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
73class DOTGraphTraitsPrinter : public FunctionPass {
74public:
75 DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
76 : FunctionPass(ID), Name(GraphName) {}
77
Andrew Scullcdfcccc2018-10-05 20:58:37 +010078 /// Return true if this function should be processed.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010079 ///
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.
84 virtual bool processFunction(Function &F, AnalysisT &Analysis) {
85 return true;
86 }
87
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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200100 raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101 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
113 void getAnalysisUsage(AnalysisUsage &AU) const override {
114 AU.setPreservesAll();
115 AU.addRequired<AnalysisT>();
116 }
117
118private:
119 std::string Name;
120};
121
122template <
123 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
124 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
125class DOTGraphTraitsModuleViewer : public ModulePass {
126public:
127 DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
128 : ModulePass(ID), Name(GraphName) {}
129
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
139 void getAnalysisUsage(AnalysisUsage &AU) const override {
140 AU.setPreservesAll();
141 AU.addRequired<AnalysisT>();
142 }
143
144private:
145 std::string Name;
146};
147
148template <
149 typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
150 typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
151class DOTGraphTraitsModulePrinter : public ModulePass {
152public:
153 DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
154 : ModulePass(ID), Name(GraphName) {}
155
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
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200163 raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100164 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
175 void getAnalysisUsage(AnalysisUsage &AU) const override {
176 AU.setPreservesAll();
177 AU.addRequired<AnalysisT>();
178 }
179
180private:
181 std::string Name;
182};
183
184} // end namespace llvm
185
186#endif