1210299Sed//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines external functions that can be called to explicitly 11193323Sed// instantiate the CFG printer. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15193323Sed#ifndef LLVM_ANALYSIS_CFGPRINTER_H 16193323Sed#define LLVM_ANALYSIS_CFGPRINTER_H 17193323Sed 18276479Sdim#include "llvm/IR/CFG.h" 19249423Sdim#include "llvm/IR/Constants.h" 20249423Sdim#include "llvm/IR/Function.h" 21249423Sdim#include "llvm/IR/Instructions.h" 22198396Srdivacky#include "llvm/Support/GraphWriter.h" 23198396Srdivacky 24193323Sednamespace llvm { 25198396Srdivackytemplate<> 26198396Srdivackystruct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { 27199989Srdivacky 28199989Srdivacky DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 29199989Srdivacky 30198396Srdivacky static std::string getGraphName(const Function *F) { 31234353Sdim return "CFG for '" + F->getName().str() + "' function"; 32198396Srdivacky } 33198396Srdivacky 34199989Srdivacky static std::string getSimpleNodeLabel(const BasicBlock *Node, 35234353Sdim const Function *) { 36199989Srdivacky if (!Node->getName().empty()) 37234353Sdim return Node->getName().str(); 38198396Srdivacky 39198396Srdivacky std::string Str; 40198396Srdivacky raw_string_ostream OS(Str); 41198396Srdivacky 42276479Sdim Node->printAsOperand(OS, false); 43199989Srdivacky return OS.str(); 44199989Srdivacky } 45198396Srdivacky 46261991Sdim static std::string getCompleteNodeLabel(const BasicBlock *Node, 47234353Sdim const Function *) { 48261991Sdim enum { MaxColumns = 80 }; 49199989Srdivacky std::string Str; 50199989Srdivacky raw_string_ostream OS(Str); 51199989Srdivacky 52198396Srdivacky if (Node->getName().empty()) { 53276479Sdim Node->printAsOperand(OS, false); 54198396Srdivacky OS << ":"; 55198396Srdivacky } 56198396Srdivacky 57198396Srdivacky OS << *Node; 58198396Srdivacky std::string OutStr = OS.str(); 59198396Srdivacky if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 60198396Srdivacky 61198396Srdivacky // Process string output to make it nicer... 62261991Sdim unsigned ColNum = 0; 63261991Sdim unsigned LastSpace = 0; 64261991Sdim for (unsigned i = 0; i != OutStr.length(); ++i) { 65198396Srdivacky if (OutStr[i] == '\n') { // Left justify 66198396Srdivacky OutStr[i] = '\\'; 67198396Srdivacky OutStr.insert(OutStr.begin()+i+1, 'l'); 68261991Sdim ColNum = 0; 69261991Sdim LastSpace = 0; 70198396Srdivacky } else if (OutStr[i] == ';') { // Delete comments! 71198396Srdivacky unsigned Idx = OutStr.find('\n', i+1); // Find end of line 72198396Srdivacky OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); 73198396Srdivacky --i; 74261991Sdim } else if (ColNum == MaxColumns) { // Wrap lines. 75280031Sdim // Wrap very long names even though we can't find a space. 76280031Sdim if (!LastSpace) 77280031Sdim LastSpace = i; 78280031Sdim OutStr.insert(LastSpace, "\\l..."); 79280031Sdim ColNum = i - LastSpace; 80280031Sdim LastSpace = 0; 81280031Sdim i += 3; // The loop will advance 'i' again. 82198396Srdivacky } 83261991Sdim else 84261991Sdim ++ColNum; 85261991Sdim if (OutStr[i] == ' ') 86261991Sdim LastSpace = i; 87261991Sdim } 88198396Srdivacky return OutStr; 89198396Srdivacky } 90198396Srdivacky 91199989Srdivacky std::string getNodeLabel(const BasicBlock *Node, 92199989Srdivacky const Function *Graph) { 93199989Srdivacky if (isSimple()) 94199989Srdivacky return getSimpleNodeLabel(Node, Graph); 95199989Srdivacky else 96199989Srdivacky return getCompleteNodeLabel(Node, Graph); 97199989Srdivacky } 98199989Srdivacky 99198396Srdivacky static std::string getEdgeSourceLabel(const BasicBlock *Node, 100198396Srdivacky succ_const_iterator I) { 101198396Srdivacky // Label source of conditional branches with "T" or "F" 102198396Srdivacky if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) 103198396Srdivacky if (BI->isConditional()) 104198396Srdivacky return (I == succ_begin(Node)) ? "T" : "F"; 105261991Sdim 106199481Srdivacky // Label source of switch edges with the associated value. 107199481Srdivacky if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { 108199481Srdivacky unsigned SuccNo = I.getSuccessorIndex(); 109199481Srdivacky 110199481Srdivacky if (SuccNo == 0) return "def"; 111261991Sdim 112199481Srdivacky std::string Str; 113199481Srdivacky raw_string_ostream OS(Str); 114234353Sdim SwitchInst::ConstCaseIt Case = 115261991Sdim SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); 116234353Sdim OS << Case.getCaseValue()->getValue(); 117199481Srdivacky return OS.str(); 118261991Sdim } 119198396Srdivacky return ""; 120198396Srdivacky } 121198396Srdivacky}; 122198396Srdivacky} // End llvm namespace 123198396Srdivacky 124198396Srdivackynamespace llvm { 125193323Sed class FunctionPass; 126193323Sed FunctionPass *createCFGPrinterPass (); 127193323Sed FunctionPass *createCFGOnlyPrinterPass (); 128193323Sed} // End llvm namespace 129193323Sed 130193323Sed#endif 131