1 //===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// 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 // This file defines external functions that can be called to explicitly 15 // instantiate the CFG printer. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #ifndef LLVM_ANALYSIS_CFGPRINTER_H 20 #define LLVM_ANALYSIS_CFGPRINTER_H 21 22 #include "llvm/IR/CFG.h" 23 #include "llvm/IR/Constants.h" 24 #include "llvm/IR/Function.h" 25 #include "llvm/IR/Instructions.h" 26 #include "llvm/IR/PassManager.h" 27 #include "llvm/Support/GraphWriter.h" 28 29 namespace llvm { 30 class CFGViewerPass 31 : public PassInfoMixin<CFGViewerPass> { 32 public: 33 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 34 }; 35 36 class CFGOnlyViewerPass 37 : public PassInfoMixin<CFGOnlyViewerPass> { 38 public: 39 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 40 }; 41 42 class CFGPrinterPass 43 : public PassInfoMixin<CFGPrinterPass> { 44 public: 45 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 46 }; 47 48 class CFGOnlyPrinterPass 49 : public PassInfoMixin<CFGOnlyPrinterPass> { 50 public: 51 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 52 }; 53 54 template<> 55 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { 56 57 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 58 59 static std::string getGraphName(const Function *F) { 60 return "CFG for '" + F->getName().str() + "' function"; 61 } 62 63 static std::string getSimpleNodeLabel(const BasicBlock *Node, 64 const Function *) { 65 if (!Node->getName().empty()) 66 return Node->getName().str(); 67 68 std::string Str; 69 raw_string_ostream OS(Str); 70 71 Node->printAsOperand(OS, false); 72 return OS.str(); 73 } 74 75 static std::string getCompleteNodeLabel(const BasicBlock *Node, 76 const Function *) { 77 enum { MaxColumns = 80 }; 78 std::string Str; 79 raw_string_ostream OS(Str); 80 81 if (Node->getName().empty()) { 82 Node->printAsOperand(OS, false); 83 OS << ":"; 84 } 85 86 OS << *Node; 87 std::string OutStr = OS.str(); 88 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 89 90 // Process string output to make it nicer... 91 unsigned ColNum = 0; 92 unsigned LastSpace = 0; 93 for (unsigned i = 0; i != OutStr.length(); ++i) { 94 if (OutStr[i] == '\n') { // Left justify 95 OutStr[i] = '\\'; 96 OutStr.insert(OutStr.begin()+i+1, 'l'); 97 ColNum = 0; 98 LastSpace = 0; 99 } else if (OutStr[i] == ';') { // Delete comments! 100 unsigned Idx = OutStr.find('\n', i+1); // Find end of line 101 OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); 102 --i; 103 } else if (ColNum == MaxColumns) { // Wrap lines. 104 // Wrap very long names even though we can't find a space. 105 if (!LastSpace) 106 LastSpace = i; 107 OutStr.insert(LastSpace, "\\l..."); 108 ColNum = i - LastSpace; 109 LastSpace = 0; 110 i += 3; // The loop will advance 'i' again. 111 } 112 else 113 ++ColNum; 114 if (OutStr[i] == ' ') 115 LastSpace = i; 116 } 117 return OutStr; 118 } 119 120 std::string getNodeLabel(const BasicBlock *Node, 121 const Function *Graph) { 122 if (isSimple()) 123 return getSimpleNodeLabel(Node, Graph); 124 else 125 return getCompleteNodeLabel(Node, Graph); 126 } 127 128 static std::string getEdgeSourceLabel(const BasicBlock *Node, 129 succ_const_iterator I) { 130 // Label source of conditional branches with "T" or "F" 131 if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) 132 if (BI->isConditional()) 133 return (I == succ_begin(Node)) ? "T" : "F"; 134 135 // Label source of switch edges with the associated value. 136 if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { 137 unsigned SuccNo = I.getSuccessorIndex(); 138 139 if (SuccNo == 0) return "def"; 140 141 std::string Str; 142 raw_string_ostream OS(Str); 143 auto Case = *SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); 144 OS << Case.getCaseValue()->getValue(); 145 return OS.str(); 146 } 147 return ""; 148 } 149 150 /// Display the raw branch weights from PGO. 151 std::string getEdgeAttributes(const BasicBlock *Node, succ_const_iterator I, 152 const Function *F) { 153 const TerminatorInst *TI = Node->getTerminator(); 154 if (TI->getNumSuccessors() == 1) 155 return ""; 156 157 MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof); 158 if (!WeightsNode) 159 return ""; 160 161 MDString *MDName = cast<MDString>(WeightsNode->getOperand(0)); 162 if (MDName->getString() != "branch_weights") 163 return ""; 164 165 unsigned OpNo = I.getSuccessorIndex() + 1; 166 if (OpNo >= WeightsNode->getNumOperands()) 167 return ""; 168 ConstantInt *Weight = 169 mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand(OpNo)); 170 if (!Weight) 171 return ""; 172 173 // Prepend a 'W' to indicate that this is a weight rather than the actual 174 // profile count (due to scaling). 175 Twine Attrs = "label=\"W:" + Twine(Weight->getZExtValue()) + "\""; 176 return Attrs.str(); 177 } 178 }; 179 } // End llvm namespace 180 181 namespace llvm { 182 class FunctionPass; 183 FunctionPass *createCFGPrinterLegacyPassPass (); 184 FunctionPass *createCFGOnlyPrinterLegacyPassPass (); 185 } // End llvm namespace 186 187 #endif 188