DOTGraphTraitsPass.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===-- DOTGraphTraitsPass.h - Print/View dotty graphs-----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Templates to create dotty viewer and printer passes for GraphTraits graphs.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
  18. #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
  19. #include "llvm/Analysis/CFGPrinter.h"
  20. namespace llvm {
  21. /// Default traits class for extracting a graph from an analysis pass.
  22. ///
  23. /// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through.
  24. template <typename AnalysisT, typename GraphT = AnalysisT *>
  25. struct DefaultAnalysisGraphTraits {
  26. static GraphT getGraph(AnalysisT *A) { return A; }
  27. };
  28. template <
  29. typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  30. typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
  31. class DOTGraphTraitsViewer : public FunctionPass {
  32. public:
  33. DOTGraphTraitsViewer(StringRef GraphName, char &ID)
  34. : FunctionPass(ID), Name(GraphName) {}
  35. /// Return true if this function should be processed.
  36. ///
  37. /// An implementation of this class my override this function to indicate that
  38. /// only certain functions should be viewed.
  39. ///
  40. /// @param Analysis The current analysis result for this function.
  41. virtual bool processFunction(Function &F, AnalysisT &Analysis) {
  42. return true;
  43. }
  44. bool runOnFunction(Function &F) override {
  45. auto &Analysis = getAnalysis<AnalysisT>();
  46. if (!processFunction(F, Analysis))
  47. return false;
  48. GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
  49. std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
  50. std::string Title = GraphName + " for '" + F.getName().str() + "' function";
  51. ViewGraph(Graph, Name, IsSimple, Title);
  52. return false;
  53. }
  54. void getAnalysisUsage(AnalysisUsage &AU) const override {
  55. AU.setPreservesAll();
  56. AU.addRequired<AnalysisT>();
  57. }
  58. private:
  59. std::string Name;
  60. };
  61. template <
  62. typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  63. typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
  64. class DOTGraphTraitsPrinter : public FunctionPass {
  65. public:
  66. DOTGraphTraitsPrinter(StringRef GraphName, char &ID)
  67. : FunctionPass(ID), Name(GraphName) {}
  68. /// Return true if this function should be processed.
  69. ///
  70. /// An implementation of this class my override this function to indicate that
  71. /// only certain functions should be printed.
  72. ///
  73. /// @param Analysis The current analysis result for this function.
  74. virtual bool processFunction(Function &F, AnalysisT &Analysis) {
  75. return true;
  76. }
  77. bool runOnFunction(Function &F) override {
  78. auto &Analysis = getAnalysis<AnalysisT>();
  79. if (!processFunction(F, Analysis))
  80. return false;
  81. GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
  82. std::string Filename = Name + "." + F.getName().str() + ".dot";
  83. std::error_code EC;
  84. errs() << "Writing '" << Filename << "'...";
  85. raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  86. std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
  87. std::string Title = GraphName + " for '" + F.getName().str() + "' function";
  88. if (!EC)
  89. WriteGraph(File, Graph, IsSimple, Title);
  90. else
  91. errs() << " error opening file for writing!";
  92. errs() << "\n";
  93. return false;
  94. }
  95. void getAnalysisUsage(AnalysisUsage &AU) const override {
  96. AU.setPreservesAll();
  97. AU.addRequired<AnalysisT>();
  98. }
  99. private:
  100. std::string Name;
  101. };
  102. template <
  103. typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  104. typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
  105. class DOTGraphTraitsModuleViewer : public ModulePass {
  106. public:
  107. DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID)
  108. : ModulePass(ID), Name(GraphName) {}
  109. bool runOnModule(Module &M) override {
  110. GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
  111. std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
  112. ViewGraph(Graph, Name, IsSimple, Title);
  113. return false;
  114. }
  115. void getAnalysisUsage(AnalysisUsage &AU) const override {
  116. AU.setPreservesAll();
  117. AU.addRequired<AnalysisT>();
  118. }
  119. private:
  120. std::string Name;
  121. };
  122. template <
  123. typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
  124. typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT, GraphT> >
  125. class DOTGraphTraitsModulePrinter : public ModulePass {
  126. public:
  127. DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID)
  128. : ModulePass(ID), Name(GraphName) {}
  129. bool runOnModule(Module &M) override {
  130. GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
  131. std::string Filename = Name + ".dot";
  132. std::error_code EC;
  133. errs() << "Writing '" << Filename << "'...";
  134. raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  135. std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
  136. if (!EC)
  137. WriteGraph(File, Graph, IsSimple, Title);
  138. else
  139. errs() << " error opening file for writing!";
  140. errs() << "\n";
  141. return false;
  142. }
  143. void getAnalysisUsage(AnalysisUsage &AU) const override {
  144. AU.setPreservesAll();
  145. AU.addRequired<AnalysisT>();
  146. }
  147. private:
  148. std::string Name;
  149. };
  150. template <typename GraphT>
  151. void WriteDOTGraphToFile(Function &F, GraphT &&Graph,
  152. std::string FileNamePrefix, bool IsSimple) {
  153. std::string Filename = FileNamePrefix + "." + F.getName().str() + ".dot";
  154. std::error_code EC;
  155. errs() << "Writing '" << Filename << "'...";
  156. raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  157. std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
  158. std::string Title = GraphName + " for '" + F.getName().str() + "' function";
  159. if (!EC)
  160. WriteGraph(File, Graph, IsSimple, Title);
  161. else
  162. errs() << " error opening file for writing!";
  163. errs() << "\n";
  164. }
  165. } // end namespace llvm
  166. #endif
  167. #ifdef __GNUC__
  168. #pragma GCC diagnostic pop
  169. #endif