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