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 external functions that can be called to explicitly 11 // instantiate the CFG printer. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_ANALYSIS_CFGPRINTER_H 16 #define LLVM_ANALYSIS_CFGPRINTER_H 17 18 #include "llvm/IR/CFG.h" 19 #include "llvm/IR/Constants.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/Instructions.h" 22 #include "llvm/Support/GraphWriter.h" 23 24 namespace llvm { 25 template<> 26 struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { 27 28 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 29 30 static std::string getGraphName(const Function *F) { 31 return "CFG for '" + F->getName().str() + "' function"; 32 } 33 34 static std::string getSimpleNodeLabel(const BasicBlock *Node, 35 const Function *) { 36 if (!Node->getName().empty()) 37 return Node->getName().str(); 38 39 std::string Str; 40 raw_string_ostream OS(Str); 41 42 Node->printAsOperand(OS, false); 43 return OS.str(); 44 } 45 46 static std::string getCompleteNodeLabel(const BasicBlock *Node, 47 const Function *) { 48 enum { MaxColumns = 80 }; 49 std::string Str; 50 raw_string_ostream OS(Str); 51 52 if (Node->getName().empty()) { 53 Node->printAsOperand(OS, false); 54 OS << ":"; 55 } 56 57 OS << *Node; 58 std::string OutStr = OS.str(); 59 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 60 61 // Process string output to make it nicer... 62 unsigned ColNum = 0; 63 unsigned LastSpace = 0; 64 for (unsigned i = 0; i != OutStr.length(); ++i) { 65 if (OutStr[i] == '\n') { // Left justify 66 OutStr[i] = '\\'; 67 OutStr.insert(OutStr.begin()+i+1, 'l'); 68 ColNum = 0; 69 LastSpace = 0; 70 } else if (OutStr[i] == ';') { // Delete comments! 71 unsigned Idx = OutStr.find('\n', i+1); // Find end of line 72 OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); 73 --i; 74 } else if (ColNum == MaxColumns) { // Wrap lines. 75 // Wrap very long names even though we can't find a space. 76 if (!LastSpace) 77 LastSpace = i; 78 OutStr.insert(LastSpace, "\\l..."); 79 ColNum = i - LastSpace; 80 LastSpace = 0; 81 i += 3; // The loop will advance 'i' again. 82 } 83 else 84 ++ColNum; 85 if (OutStr[i] == ' ') 86 LastSpace = i; 87 } 88 return OutStr; 89 } 90 91 std::string getNodeLabel(const BasicBlock *Node, 92 const Function *Graph) { 93 if (isSimple()) 94 return getSimpleNodeLabel(Node, Graph); 95 else 96 return getCompleteNodeLabel(Node, Graph); 97 } 98 99 static std::string getEdgeSourceLabel(const BasicBlock *Node, 100 succ_const_iterator I) { 101 // Label source of conditional branches with "T" or "F" 102 if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) 103 if (BI->isConditional()) 104 return (I == succ_begin(Node)) ? "T" : "F"; 105 106 // Label source of switch edges with the associated value. 107 if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { 108 unsigned SuccNo = I.getSuccessorIndex(); 109 110 if (SuccNo == 0) return "def"; 111 112 std::string Str; 113 raw_string_ostream OS(Str); 114 SwitchInst::ConstCaseIt Case = 115 SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); 116 OS << Case.getCaseValue()->getValue(); 117 return OS.str(); 118 } 119 return ""; 120 } 121 }; 122 } // End llvm namespace 123 124 namespace llvm { 125 class FunctionPass; 126 FunctionPass *createCFGPrinterPass (); 127 FunctionPass *createCFGOnlyPrinterPass (); 128 } // End llvm namespace 129 130 #endif 131