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