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
3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnFunction(Function &F) override {
4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
4136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
42a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Title = GraphName + " for '" + F.getName().str() + "' function";
43a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
4436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ViewGraph(Graph, Name, IsSimple, Title);
4523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
4623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    return false;
4723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
4823279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
4936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
5023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    AU.setPreservesAll();
5136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
5223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
53a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
54a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
55a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  std::string Name;
5623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser};
5723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
5836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
61a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsPrinter : public FunctionPass {
62a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
6396f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : FunctionPass(ID), Name(GraphName) {}
65a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnFunction(Function &F) override {
6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
68a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Filename = Name + "." + F.getName().str() + ".dot";
69a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string ErrorInfo;
70a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
71a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    errs() << "Writing '" << Filename << "'...";
72a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
7336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
7436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
75a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Title = GraphName + " for '" + F.getName().str() + "' function";
76a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
77a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    if (ErrorInfo.empty())
7836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      WriteGraph(File, Graph, IsSimple, Title);
79a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    else
80a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick      errs() << "  error opening file for writing!";
81a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    errs() << "\n";
82a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
83a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    return false;
84a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  }
85a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
8636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
87a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    AU.setPreservesAll();
8836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
89a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  }
9023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
91a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
9223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  std::string Name;
93a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick};
94a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
9536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
9636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
9736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
98a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsModuleViewer : public ModulePass {
99a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
10096f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
10136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : ModulePass(ID), Name(GraphName) {}
102a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
10336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnModule(Module &M) override {
10436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
10536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
10623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
10736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ViewGraph(Graph, Name, IsSimple, Title);
108a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
109a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    return false;
11023279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
11123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
11236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
113a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    AU.setPreservesAll();
11436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
115a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  }
11623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
117a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
118a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  std::string Name;
119a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick};
120a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
12136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinestemplate <
12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
12336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> >
124a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickclass DOTGraphTraitsModulePrinter : public ModulePass {
125a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickpublic:
12696f498bd9f140a98321c478f517877c4767b94faDmitri Gribenko  DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
12736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      : ModulePass(ID), Name(GraphName) {}
128a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
12936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool runOnModule(Module &M) override {
13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
131a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    std::string Filename = Name + ".dot";
13223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    std::string ErrorInfo;
13323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
134a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick    errs() << "Writing '" << Filename << "'...";
135a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text);
13736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
13823279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
13923279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    if (ErrorInfo.empty())
14036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      WriteGraph(File, Graph, IsSimple, Title);
14123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    else
14223279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser      errs() << "  error opening file for writing!";
14323279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    errs() << "\n";
144a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
14523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    return false;
14623279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
14723279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser
14836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
14923279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser    AU.setPreservesAll();
15036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    AU.addRequired<AnalysisT>();
15123279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser  }
152a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
153a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trickprivate:
154a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick  std::string Name;
15523279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser};
156a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
157a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick} // end namespace llvm
158a125cacf7d154d0e5cad47f011e619e45517c839Andrew Trick
15923279f18a9759d94579de7e79be61c7aa790b8baTobias Grosser#endif
160