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 24namespace llvm { 25template<> 26struct 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 if (LastSpace) { 76 OutStr.insert(LastSpace, "\\l..."); 77 ColNum = i - LastSpace; 78 LastSpace = 0; 79 i += 3; // The loop will advance 'i' again. 80 } 81 // Else keep trying to find a space. 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 124namespace llvm { 125 class FunctionPass; 126 FunctionPass *createCFGPrinterPass (); 127 FunctionPass *createCFGOnlyPrinterPass (); 128} // End llvm namespace 129 130#endif 131