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