123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===//
223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//
323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//                     The LLVM Compiler Infrastructure
423279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//
523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser// This file is distributed under the University of Illinois Open Source
623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser// License. See LICENSE.TXT for details.
723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//
823279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//===----------------------------------------------------------------------===//
923279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//
1023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser// Templates to create dotty viewer and printer passes for GraphTraits graphs.
1123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//
1223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser//===----------------------------------------------------------------------===//
1323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
14674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
15674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
1623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
1723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser#include "llvm/Analysis/CFGPrinter.h"
18255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "llvm/Pass.h"
19dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Support/FileSystem.h"
2023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
2123279f18a9759d94579de7e79be61c7aa790b8baTobias Grossernamespace llvm {
2223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Default traits class for extracting a graph from an analysis pass.
2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines///
2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <typename AnalysisT, typename GraphT = AnalysisT *>
2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesstruct DefaultAnalysisGraphTraits {
2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  static GraphT getGraph(AnalysisT *A) { return A; }
2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines};
3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
3236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
3336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
34a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsViewer : public FunctionPass {
35a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
3696f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsViewer(StringRef GraphName, char &ID)
3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : FunctionPass(ID), Name(GraphName) {}
3823279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
39f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// @brief Return true if this function should be processed.
40f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  ///
41f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// An implementation of this class my override this function to indicate that
42f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// only certain functions should be viewed.
43f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  ///
44f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// @param Analysis The current analysis result for this function.
45f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  virtual bool processFunction(Function &F, AnalysisT &Analysis) {
46f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    return true;
47f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
48f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnFunction(Function &F) override {
50f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    auto &Analysis = getAnalysis<AnalysisT>();
51f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
52f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    if (!processFunction(F, Analysis))
53f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      return false;
54f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
55f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
5636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
57a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Title = GraphName + " for '" + F.getName().str() + "' function";
58a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ViewGraph(Graph, Name, IsSimple, Title);
6023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
6123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    return false;
6223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
6323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
6523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    AU.setPreservesAll();
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
6723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
68a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
69a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
70a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  std::string Name;
7123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser};
7223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
7536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
76a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsPrinter : public FunctionPass {
77a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
7896f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
7936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : FunctionPass(ID), Name(GraphName) {}
80a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// @brief Return true if this function should be processed.
82f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  ///
83f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// An implementation of this class my override this function to indicate that
84f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// only certain functions should be printed.
85f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  ///
86f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  /// @param Analysis The current analysis result for this function.
87f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  virtual bool processFunction(Function &F, AnalysisT &Analysis) {
88f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    return true;
89f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
90f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
9136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnFunction(Function &F) override {
92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    auto &Analysis = getAnalysis<AnalysisT>();
93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    if (!processFunction(F, Analysis))
95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      return false;
96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
97f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
98a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Filename = Name + "." + F.getName().str() + ".dot";
9937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    std::error_code EC;
100a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
101a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    errs() << "Writing '" << Filename << "'...";
102a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
10337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
105a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Title = GraphName + " for '" + F.getName().str() + "' function";
106a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
10737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (!EC)
10836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      WriteGraph(File, Graph, IsSimple, Title);
109a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    else
110a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick      errs() << "  error opening file for writing!";
111a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    errs() << "\n";
112a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
113a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    return false;
114a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  }
115a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
11636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
117a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    AU.setPreservesAll();
11836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
119a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  }
12023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
121a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
12223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  std::string Name;
123a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick};
124a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
12536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
12636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
128a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsModuleViewer : public ModulePass {
129a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
13096f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
13136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : ModulePass(ID), Name(GraphName) {}
132a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
13336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnModule(Module &M) override {
13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
13623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ViewGraph(Graph, Name, IsSimple, Title);
138a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
139a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    return false;
14023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
14123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
14236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
143a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    AU.setPreservesAll();
14436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
145a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  }
14623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
147a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
148a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  std::string Name;
149a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick};
150a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
15136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
15236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
15336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
154a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsModulePrinter : public ModulePass {
155a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
15696f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
15736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : ModulePass(ID), Name(GraphName) {}
158a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
15936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnModule(Module &M) override {
16036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
161a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Filename = Name + ".dot";
16237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    std::error_code EC;
16323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
164a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    errs() << "Writing '" << Filename << "'...";
165a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
16637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
16823279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
16937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (!EC)
17036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      WriteGraph(File, Graph, IsSimple, Title);
17123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    else
17223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser      errs() << "  error opening file for writing!";
17323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    errs() << "\n";
174a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
17523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    return false;
17623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
17723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
17836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
17923279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    AU.setPreservesAll();
18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
18123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
182a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
183a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
184a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  std::string Name;
18523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser};
186a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
187a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick} // end namespace llvm
188a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
18923279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser#endif
190