File indexing completed on 2026-05-10 08:43:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
0014 #define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
0015
0016 #include "llvm/Analysis/CFGPrinter.h"
0017 #include "llvm/Support/FileSystem.h"
0018 #include "llvm/Support/GraphWriter.h"
0019 #include <unordered_set>
0020
0021 static std::unordered_set<std::string> nameObj;
0022
0023 namespace llvm {
0024
0025
0026
0027
0028 template <typename Result, typename GraphT = Result *>
0029 struct DefaultAnalysisGraphTraits {
0030 static GraphT getGraph(Result R) { return &R; }
0031 };
0032
0033 template <typename GraphT>
0034 void viewGraphForFunction(Function &F, GraphT Graph, StringRef Name,
0035 bool IsSimple) {
0036 std::string GraphName = DOTGraphTraits<GraphT *>::getGraphName(&Graph);
0037
0038 ViewGraph(Graph, Name, IsSimple,
0039 GraphName + " for '" + F.getName() + "' function");
0040 }
0041
0042 template <typename AnalysisT, bool IsSimple,
0043 typename GraphT = typename AnalysisT::Result *,
0044 typename AnalysisGraphTraitsT =
0045 DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
0046 struct DOTGraphTraitsViewer
0047 : PassInfoMixin<DOTGraphTraitsViewer<AnalysisT, IsSimple, GraphT,
0048 AnalysisGraphTraitsT>> {
0049 DOTGraphTraitsViewer(StringRef GraphName) : Name(GraphName) {}
0050
0051
0052
0053
0054
0055
0056
0057 virtual bool processFunction(Function &F,
0058 const typename AnalysisT::Result &Result) {
0059 return true;
0060 }
0061
0062 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
0063 auto &Result = FAM.getResult<AnalysisT>(F);
0064 if (!processFunction(F, Result))
0065 return PreservedAnalyses::all();
0066
0067 GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
0068 viewGraphForFunction(F, Graph, Name, IsSimple);
0069
0070 return PreservedAnalyses::all();
0071 };
0072
0073 protected:
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083 ~DOTGraphTraitsViewer() {}
0084
0085 private:
0086 StringRef Name;
0087 };
0088
0089 static inline void shortenFileName(std::string &FN, unsigned char len = 250) {
0090 if (FN.length() > len)
0091 FN.resize(len);
0092 auto strLen = FN.length();
0093 while (strLen > 0) {
0094 if (nameObj.insert(FN).second)
0095 break;
0096 FN.resize(--len);
0097 strLen--;
0098 }
0099 }
0100
0101 template <typename GraphT>
0102 void printGraphForFunction(Function &F, GraphT Graph, StringRef Name,
0103 bool IsSimple) {
0104 std::string Filename = Name.str() + "." + F.getName().str();
0105 shortenFileName(Filename);
0106 Filename = Filename + ".dot";
0107 std::error_code EC;
0108
0109 errs() << "Writing '" << Filename << "'...";
0110
0111 raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
0112 std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
0113
0114 if (!EC)
0115 WriteGraph(File, Graph, IsSimple,
0116 GraphName + " for '" + F.getName() + "' function");
0117 else
0118 errs() << " error opening file for writing!";
0119 errs() << "\n";
0120 }
0121
0122 template <typename AnalysisT, bool IsSimple,
0123 typename GraphT = typename AnalysisT::Result *,
0124 typename AnalysisGraphTraitsT =
0125 DefaultAnalysisGraphTraits<typename AnalysisT::Result &, GraphT>>
0126 struct DOTGraphTraitsPrinter
0127 : PassInfoMixin<DOTGraphTraitsPrinter<AnalysisT, IsSimple, GraphT,
0128 AnalysisGraphTraitsT>> {
0129 DOTGraphTraitsPrinter(StringRef GraphName) : Name(GraphName) {}
0130
0131
0132
0133
0134
0135
0136
0137 virtual bool processFunction(Function &F,
0138 const typename AnalysisT::Result &Result) {
0139 return true;
0140 }
0141
0142 PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM) {
0143 auto &Result = FAM.getResult<AnalysisT>(F);
0144 if (!processFunction(F, Result))
0145 return PreservedAnalyses::all();
0146
0147 GraphT Graph = AnalysisGraphTraitsT::getGraph(Result);
0148
0149 printGraphForFunction(F, Graph, Name, IsSimple);
0150
0151 return PreservedAnalyses::all();
0152 };
0153
0154 protected:
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 ~DOTGraphTraitsPrinter() {}
0165
0166 private:
0167 StringRef Name;
0168 };
0169
0170
0171
0172
0173 template <typename AnalysisT, typename GraphT = AnalysisT *>
0174 struct LegacyDefaultAnalysisGraphTraits {
0175 static GraphT getGraph(AnalysisT *A) { return A; }
0176 };
0177
0178 template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
0179 typename AnalysisGraphTraitsT =
0180 LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
0181 class DOTGraphTraitsViewerWrapperPass : public FunctionPass {
0182 public:
0183 DOTGraphTraitsViewerWrapperPass(StringRef GraphName, char &ID)
0184 : FunctionPass(ID), Name(GraphName) {}
0185
0186
0187
0188
0189
0190
0191
0192 virtual bool processFunction(Function &F, AnalysisT &Analysis) {
0193 return true;
0194 }
0195
0196 bool runOnFunction(Function &F) override {
0197 auto &Analysis = getAnalysis<AnalysisT>();
0198
0199 if (!processFunction(F, Analysis))
0200 return false;
0201
0202 GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
0203 viewGraphForFunction(F, Graph, Name, IsSimple);
0204
0205 return false;
0206 }
0207
0208 void getAnalysisUsage(AnalysisUsage &AU) const override {
0209 AU.setPreservesAll();
0210 AU.addRequired<AnalysisT>();
0211 }
0212
0213 private:
0214 std::string Name;
0215 };
0216
0217 template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
0218 typename AnalysisGraphTraitsT =
0219 LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
0220 class DOTGraphTraitsPrinterWrapperPass : public FunctionPass {
0221 public:
0222 DOTGraphTraitsPrinterWrapperPass(StringRef GraphName, char &ID)
0223 : FunctionPass(ID), Name(GraphName) {}
0224
0225
0226
0227
0228
0229
0230
0231 virtual bool processFunction(Function &F, AnalysisT &Analysis) {
0232 return true;
0233 }
0234
0235 bool runOnFunction(Function &F) override {
0236 auto &Analysis = getAnalysis<AnalysisT>();
0237
0238 if (!processFunction(F, Analysis))
0239 return false;
0240
0241 GraphT Graph = AnalysisGraphTraitsT::getGraph(&Analysis);
0242 printGraphForFunction(F, Graph, Name, IsSimple);
0243
0244 return false;
0245 }
0246
0247 void getAnalysisUsage(AnalysisUsage &AU) const override {
0248 AU.setPreservesAll();
0249 AU.addRequired<AnalysisT>();
0250 }
0251
0252 private:
0253 std::string Name;
0254 };
0255
0256 template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
0257 typename AnalysisGraphTraitsT =
0258 LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
0259 class DOTGraphTraitsModuleViewerWrapperPass : public ModulePass {
0260 public:
0261 DOTGraphTraitsModuleViewerWrapperPass(StringRef GraphName, char &ID)
0262 : ModulePass(ID), Name(GraphName) {}
0263
0264 bool runOnModule(Module &M) override {
0265 GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
0266 std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
0267
0268 ViewGraph(Graph, Name, IsSimple, Title);
0269
0270 return false;
0271 }
0272
0273 void getAnalysisUsage(AnalysisUsage &AU) const override {
0274 AU.setPreservesAll();
0275 AU.addRequired<AnalysisT>();
0276 }
0277
0278 private:
0279 std::string Name;
0280 };
0281
0282 template <typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *,
0283 typename AnalysisGraphTraitsT =
0284 LegacyDefaultAnalysisGraphTraits<AnalysisT, GraphT>>
0285 class DOTGraphTraitsModulePrinterWrapperPass : public ModulePass {
0286 public:
0287 DOTGraphTraitsModulePrinterWrapperPass(StringRef GraphName, char &ID)
0288 : ModulePass(ID), Name(GraphName) {}
0289
0290 bool runOnModule(Module &M) override {
0291 GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>());
0292 shortenFileName(Name);
0293 std::string Filename = Name + ".dot";
0294 std::error_code EC;
0295
0296 errs() << "Writing '" << Filename << "'...";
0297
0298 raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
0299 std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph);
0300
0301 if (!EC)
0302 WriteGraph(File, Graph, IsSimple, Title);
0303 else
0304 errs() << " error opening file for writing!";
0305 errs() << "\n";
0306
0307 return false;
0308 }
0309
0310 void getAnalysisUsage(AnalysisUsage &AU) const override {
0311 AU.setPreservesAll();
0312 AU.addRequired<AnalysisT>();
0313 }
0314
0315 private:
0316 std::string Name;
0317 };
0318
0319 template <typename GraphT>
0320 void WriteDOTGraphToFile(Function &F, GraphT &&Graph,
0321 std::string FileNamePrefix, bool IsSimple) {
0322 std::string Filename = FileNamePrefix + "." + F.getName().str();
0323 shortenFileName(Filename);
0324 Filename = Filename + ".dot";
0325 std::error_code EC;
0326
0327 errs() << "Writing '" << Filename << "'...";
0328
0329 raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
0330 std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph);
0331 std::string Title = GraphName + " for '" + F.getName().str() + "' function";
0332
0333 if (!EC)
0334 WriteGraph(File, Graph, IsSimple, Title);
0335 else
0336 errs() << " error opening file for writing!";
0337 errs() << "\n";
0338 }
0339
0340 }
0341
0342 #endif