1 //===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a '-dot-cfg' analysis pass, which emits the
11 // cfg.<fnname>.dot file for each function in the program, with a graph of the
12 // CFG for that function.
13 //
14 // The other main feature of this file is that it implements the
15 // Function::viewCFG method, which is useful for debugging passes which operate
16 // on the CFG.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "llvm/Analysis/CFGPrinter.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Support/FileSystem.h"
23 using namespace llvm;
24 
25 static cl::opt<bool> CFGHeatPerFunction("cfg-heat-per-function",
26                                         cl::init(false), cl::Hidden,
27                                         cl::desc("Heat CFG per function"));
28 
29 static cl::opt<bool> ShowHeatColors("cfg-heat-colors", cl::init(true),
30                                     cl::Hidden,
31                                     cl::desc("Show heat colors in CFG"));
32 
33 static cl::opt<bool> UseRawEdgeWeight("cfg-raw-weights", cl::init(false),
34                                       cl::Hidden,
35                                       cl::desc("Use raw weights for labels. "
36                                                "Use percentages as default."));
37 
38 static cl::opt<bool> ShowEdgeWeight("cfg-weights", cl::init(true), cl::Hidden,
39                                     cl::desc("Show edges labeled with weights"));
40 
41 static void writeHeatCFGToDotFile(Function &F, BlockFrequencyInfo *BFI,
42                                  BranchProbabilityInfo *BPI, uint64_t MaxFreq,
43                                  bool UseHeuristic, bool isSimple) {
44   std::string Filename = ("cfg." + F.getName() + ".dot").str();
45   errs() << "Writing '" << Filename << "'...";
46 
47   std::error_code EC;
48   raw_fd_ostream File(Filename, EC, sys::fs::F_Text);
49 
50   CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq);
51   CFGInfo.setHeuristic(UseHeuristic);
52   CFGInfo.setHeatColors(ShowHeatColors);
53   CFGInfo.setEdgeWeights(ShowEdgeWeight);
54   CFGInfo.setRawEdgeWeights(UseRawEdgeWeight);
55 
56   if (!EC)
57     WriteGraph(File, &CFGInfo, isSimple);
58   else
59     errs() << "  error opening file for writing!";
60   errs() << "\n";
61 }
62 
63 static void writeAllCFGsToDotFile(Module &M,
64                        function_ref<BlockFrequencyInfo *(Function &)> LookupBFI,
65                        function_ref<BranchProbabilityInfo *(Function &)> LookupBPI,
66                        bool isSimple) {
67   bool UseHeuristic = true;
68   uint64_t MaxFreq = 0;
69   if (!CFGHeatPerFunction)
70     MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic);
71 
72   for (auto &F : M) {
73     if (F.isDeclaration()) continue;
74     auto *BFI = LookupBFI(F);
75     auto *BPI = LookupBPI(F);
76     if (CFGHeatPerFunction)
77       MaxFreq = getMaxFreq(F, BFI, UseHeuristic);
78     writeHeatCFGToDotFile(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple);
79   }
80 
81 }
82 
83 static void viewHeatCFG(Function &F, BlockFrequencyInfo *BFI,
84                                  BranchProbabilityInfo *BPI, uint64_t MaxFreq,
85                                  bool UseHeuristic, bool isSimple) {
86   CFGDOTInfo CFGInfo(&F, BFI, BPI, MaxFreq);
87   CFGInfo.setHeuristic(UseHeuristic);
88   CFGInfo.setHeatColors(ShowHeatColors);
89   CFGInfo.setEdgeWeights(ShowEdgeWeight);
90   CFGInfo.setRawEdgeWeights(UseRawEdgeWeight);
91 
92   ViewGraph(&CFGInfo, "cfg." + F.getName(), isSimple);
93 }
94 
95 static void viewAllCFGs(Module &M,
96                        function_ref<BlockFrequencyInfo *(Function &)> LookupBFI,
97                        function_ref<BranchProbabilityInfo *(Function &)> LookupBPI,
98                        bool isSimple) {
99   bool UseHeuristic = true;
100   uint64_t MaxFreq = 0;
101   if (!CFGHeatPerFunction)
102     MaxFreq = getMaxFreq(M, LookupBFI, UseHeuristic);
103 
104   for (auto &F : M) {
105     if (F.isDeclaration()) continue;
106     auto *BFI = LookupBFI(F);
107     auto *BPI = LookupBPI(F);
108     if (CFGHeatPerFunction)
109       MaxFreq = getMaxFreq(F, BFI, UseHeuristic);
110     viewHeatCFG(F, BFI, BPI, MaxFreq, UseHeuristic, isSimple);
111   }
112 
113 }
114 
115 namespace {
116   struct CFGViewerLegacyPass : public ModulePass {
117     static char ID; // Pass identifcation, replacement for typeid
118     CFGViewerLegacyPass() : ModulePass(ID) {
119       initializeCFGViewerLegacyPassPass(*PassRegistry::getPassRegistry());
120     }
121 
122     bool runOnModule(Module &M) override {
123       auto LookupBFI = [this](Function &F) {
124         return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
125       };
126       auto LookupBPI = [this](Function &F) {
127         return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
128       };
129       viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false);
130       return false;
131     }
132 
133     void print(raw_ostream &OS, const Module * = nullptr) const override {}
134 
135     void getAnalysisUsage(AnalysisUsage &AU) const override {
136       ModulePass::getAnalysisUsage(AU);
137       AU.addRequired<BlockFrequencyInfoWrapperPass>();
138       AU.addRequired<BranchProbabilityInfoWrapperPass>();
139       AU.setPreservesAll();
140     }
141 
142   };
143 }
144 
145 char CFGViewerLegacyPass::ID = 0;
146 INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, true)
147 
148 PreservedAnalyses CFGViewerPass::run(Module &M,
149                                      ModuleAnalysisManager &AM) {
150   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
151   auto LookupBFI = [&FAM](Function &F) {
152     return &FAM.getResult<BlockFrequencyAnalysis>(F);
153   };
154   auto LookupBPI = [&FAM](Function &F) {
155     return &FAM.getResult<BranchProbabilityAnalysis>(F);
156   };
157   viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/false);
158   return PreservedAnalyses::all();
159 }
160 
161 
162 namespace {
163   struct CFGOnlyViewerLegacyPass : public ModulePass {
164     static char ID; // Pass identifcation, replacement for typeid
165     CFGOnlyViewerLegacyPass() : ModulePass(ID) {
166       initializeCFGOnlyViewerLegacyPassPass(*PassRegistry::getPassRegistry());
167     }
168 
169     bool runOnModule(Module &M) override {
170       auto LookupBFI = [this](Function &F) {
171         return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
172       };
173       auto LookupBPI = [this](Function &F) {
174         return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
175       };
176       viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true);
177       return false;
178     }
179 
180     void print(raw_ostream &OS, const Module * = nullptr) const override {}
181 
182     void getAnalysisUsage(AnalysisUsage &AU) const override {
183       ModulePass::getAnalysisUsage(AU);
184       AU.addRequired<BlockFrequencyInfoWrapperPass>();
185       AU.addRequired<BranchProbabilityInfoWrapperPass>();
186       AU.setPreservesAll();
187     }
188 
189   };
190 }
191 
192 char CFGOnlyViewerLegacyPass::ID = 0;
193 INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only",
194                 "View CFG of function (with no function bodies)", false, true)
195 
196 PreservedAnalyses CFGOnlyViewerPass::run(Module &M,
197                                          ModuleAnalysisManager &AM) {
198   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
199   auto LookupBFI = [&FAM](Function &F) {
200     return &FAM.getResult<BlockFrequencyAnalysis>(F);
201   };
202   auto LookupBPI = [&FAM](Function &F) {
203     return &FAM.getResult<BranchProbabilityAnalysis>(F);
204   };
205   viewAllCFGs(M, LookupBFI, LookupBPI, /*isSimple=*/true);
206   return PreservedAnalyses::all();
207 }
208 
209 namespace {
210   struct CFGPrinterLegacyPass : public ModulePass {
211     static char ID; // Pass identification, replacement for typeid
212     CFGPrinterLegacyPass() : ModulePass(ID) {
213       initializeCFGPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
214     }
215 
216     bool runOnModule(Module &M) override {
217       auto LookupBFI = [this](Function &F) {
218         return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
219       };
220       auto LookupBPI = [this](Function &F) {
221         return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
222       };
223       writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false);
224       return false;
225     }
226 
227     void print(raw_ostream &OS, const Module * = nullptr) const override {}
228 
229     void getAnalysisUsage(AnalysisUsage &AU) const override {
230       ModulePass::getAnalysisUsage(AU);
231       AU.addRequired<BlockFrequencyInfoWrapperPass>();
232       AU.addRequired<BranchProbabilityInfoWrapperPass>();
233       AU.setPreservesAll();
234     }
235 
236   };
237 }
238 
239 char CFGPrinterLegacyPass::ID = 0;
240 INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' file",
241                 false, true)
242 
243 PreservedAnalyses CFGPrinterPass::run(Module &M,
244                                       ModuleAnalysisManager &AM) {
245   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
246   auto LookupBFI = [&FAM](Function &F) {
247     return &FAM.getResult<BlockFrequencyAnalysis>(F);
248   };
249   auto LookupBPI = [&FAM](Function &F) {
250     return &FAM.getResult<BranchProbabilityAnalysis>(F);
251   };
252   writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/false);
253   return PreservedAnalyses::all();
254 }
255 
256 namespace {
257   struct CFGOnlyPrinterLegacyPass : public ModulePass {
258     static char ID; // Pass identification, replacement for typeid
259     CFGOnlyPrinterLegacyPass() : ModulePass(ID) {
260       initializeCFGOnlyPrinterLegacyPassPass(*PassRegistry::getPassRegistry());
261     }
262 
263     bool runOnModule(Module &M) override {
264       auto LookupBFI = [this](Function &F) {
265         return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
266       };
267       auto LookupBPI = [this](Function &F) {
268         return &this->getAnalysis<BranchProbabilityInfoWrapperPass>(F).getBPI();
269       };
270       writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true);
271       return false;
272     }
273 
274     void print(raw_ostream &OS, const Module * = nullptr) const override {}
275 
276     void getAnalysisUsage(AnalysisUsage &AU) const override {
277       ModulePass::getAnalysisUsage(AU);
278       AU.addRequired<BlockFrequencyInfoWrapperPass>();
279       AU.addRequired<BranchProbabilityInfoWrapperPass>();
280       AU.setPreservesAll();
281     }
282 
283   };
284 }
285 
286 char CFGOnlyPrinterLegacyPass::ID = 0;
287 INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only",
288    "Print CFG of function to 'dot' file (with no function bodies)",
289    false, true)
290 
291 PreservedAnalyses CFGOnlyPrinterPass::run(Module &M,
292                                           ModuleAnalysisManager &AM) {
293   auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
294   auto LookupBFI = [&FAM](Function &F) {
295     return &FAM.getResult<BlockFrequencyAnalysis>(F);
296   };
297   auto LookupBPI = [&FAM](Function &F) {
298     return &FAM.getResult<BranchProbabilityAnalysis>(F);
299   };
300   writeAllCFGsToDotFile(M, LookupBFI, LookupBPI, /*isSimple=*/true);
301   return PreservedAnalyses::all();
302 }
303 
304 /// viewCFG - This function is meant for use from the debugger.  You can just
305 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
306 /// program, displaying the CFG of the current function.  This depends on there
307 /// being a 'dot' and 'gv' program in your path.
308 ///
309 void Function::viewCFG() const {
310 
311   CFGDOTInfo CFGInfo(this);
312   ViewGraph(&CFGInfo, "cfg" + getName());
313 }
314 
315 /// viewCFGOnly - This function is meant for use from the debugger.  It works
316 /// just like viewCFG, but it does not include the contents of basic blocks
317 /// into the nodes, just the label.  If you are only interested in the CFG
318 /// this can make the graph smaller.
319 ///
320 void Function::viewCFGOnly() const {
321 
322   CFGDOTInfo CFGInfo(this);
323   ViewGraph(&CFGInfo, "cfg" + getName(), true);
324 }
325 
326 ModulePass *llvm::createCFGPrinterLegacyPassPass() {
327   return new CFGPrinterLegacyPass();
328 }
329 
330 ModulePass *llvm::createCFGOnlyPrinterLegacyPassPass() {
331   return new CFGOnlyPrinterLegacyPass();
332 }
333