CFGPrinter.h revision 263508
1356290Sjkim//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===// 296593Smarkm// 396593Smarkm// The LLVM Compiler Infrastructure 4142429Snectar// 596593Smarkm// This file is distributed under the University of Illinois Open Source 696593Smarkm// License. See LICENSE.TXT for details. 796593Smarkm// 896593Smarkm//===----------------------------------------------------------------------===// 996593Smarkm// 1096593Smarkm// This file defines external functions that can be called to explicitly 1196593Smarkm// instantiate the CFG printer. 1296593Smarkm// 1396593Smarkm//===----------------------------------------------------------------------===// 1496593Smarkm 1596593Smarkm#ifndef LLVM_ANALYSIS_CFGPRINTER_H 1696593Smarkm#define LLVM_ANALYSIS_CFGPRINTER_H 1796593Smarkm 1896593Smarkm#include "llvm/Assembly/Writer.h" 1996593Smarkm#include "llvm/IR/Constants.h" 20215698Ssimon#include "llvm/IR/Function.h" 21215698Ssimon#include "llvm/IR/Instructions.h" 22215698Ssimon#include "llvm/Support/CFG.h" 23215698Ssimon#include "llvm/Support/GraphWriter.h" 24215698Ssimon 2596593Smarkmnamespace llvm { 2696593Smarkmtemplate<> 2796593Smarkmstruct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { 2896593Smarkm 2996593Smarkm DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 3096593Smarkm 3196593Smarkm static std::string getGraphName(const Function *F) { 3296593Smarkm return "CFG for '" + F->getName().str() + "' function"; 3396593Smarkm } 3496593Smarkm 3596593Smarkm static std::string getSimpleNodeLabel(const BasicBlock *Node, 3696593Smarkm const Function *) { 3796593Smarkm if (!Node->getName().empty()) 3896593Smarkm return Node->getName().str(); 3996593Smarkm 4096593Smarkm std::string Str; 41276861Sjkim raw_string_ostream OS(Str); 42276861Sjkim 4396593Smarkm WriteAsOperand(OS, Node, false); 4496593Smarkm return OS.str(); 45215698Ssimon } 46215698Ssimon 47215698Ssimon static std::string getCompleteNodeLabel(const BasicBlock *Node, 48215698Ssimon const Function *) { 49312826Sjkim enum { MaxColumns = 80 }; 50215698Ssimon std::string Str; 51142429Snectar raw_string_ostream OS(Str); 52142429Snectar 53276861Sjkim if (Node->getName().empty()) { 54276861Sjkim WriteAsOperand(OS, Node, false); 55276861Sjkim OS << ":"; 5696593Smarkm } 57344604Sjkim 58344604Sjkim OS << *Node; 59344604Sjkim std::string OutStr = OS.str(); 60344604Sjkim if (OutStr[0] == '\n') OutStr.erase(OutStr.begin()); 61344604Sjkim 62344604Sjkim // Process string output to make it nicer... 63215698Ssimon unsigned ColNum = 0; 64344604Sjkim unsigned LastSpace = 0; 65344604Sjkim for (unsigned i = 0; i != OutStr.length(); ++i) { 66344604Sjkim if (OutStr[i] == '\n') { // Left justify 67344604Sjkim OutStr[i] = '\\'; 68276861Sjkim OutStr.insert(OutStr.begin()+i+1, 'l'); 69215698Ssimon ColNum = 0; 70344604Sjkim LastSpace = 0; 7196593Smarkm } else if (OutStr[i] == ';') { // Delete comments! 7296593Smarkm unsigned Idx = OutStr.find('\n', i+1); // Find end of line 7396593Smarkm OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); 7496593Smarkm --i; 7596593Smarkm } else if (ColNum == MaxColumns) { // Wrap lines. 7696593Smarkm if (LastSpace) { 7796593Smarkm OutStr.insert(LastSpace, "\\l..."); 7896593Smarkm ColNum = i - LastSpace; 7996593Smarkm LastSpace = 0; 8096593Smarkm i += 3; // The loop will advance 'i' again. 8196593Smarkm } 8296593Smarkm // Else keep trying to find a space. 8396593Smarkm } 8496593Smarkm else 8596593Smarkm ++ColNum; 8696593Smarkm if (OutStr[i] == ' ') 8796593Smarkm LastSpace = i; 8896593Smarkm } 8996593Smarkm return OutStr; 9096593Smarkm } 9196593Smarkm 9296593Smarkm std::string getNodeLabel(const BasicBlock *Node, 9396593Smarkm const Function *Graph) { 9496593Smarkm if (isSimple()) 9596593Smarkm return getSimpleNodeLabel(Node, Graph); 9696593Smarkm else 9796593Smarkm return getCompleteNodeLabel(Node, Graph); 9896593Smarkm } 9996593Smarkm 10096593Smarkm static std::string getEdgeSourceLabel(const BasicBlock *Node, 10196593Smarkm succ_const_iterator I) { 10296593Smarkm // Label source of conditional branches with "T" or "F" 10396593Smarkm if (const BranchInst *BI = dyn_cast<BranchInst>(Node->getTerminator())) 10496593Smarkm if (BI->isConditional()) 10596593Smarkm return (I == succ_begin(Node)) ? "T" : "F"; 10696593Smarkm 10796593Smarkm // Label source of switch edges with the associated value. 10896593Smarkm if (const SwitchInst *SI = dyn_cast<SwitchInst>(Node->getTerminator())) { 10996593Smarkm unsigned SuccNo = I.getSuccessorIndex(); 11096593Smarkm 11196593Smarkm if (SuccNo == 0) return "def"; 11296593Smarkm 11396593Smarkm std::string Str; 11496593Smarkm raw_string_ostream OS(Str); 11596593Smarkm SwitchInst::ConstCaseIt Case = 11696593Smarkm SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo); 11796593Smarkm OS << Case.getCaseValue()->getValue(); 11896593Smarkm return OS.str(); 11996593Smarkm } 12096593Smarkm return ""; 12196593Smarkm } 12296593Smarkm}; 12396593Smarkm} // End llvm namespace 12496593Smarkm 12596593Smarkmnamespace llvm { 12696593Smarkm class FunctionPass; 12796593Smarkm FunctionPass *createCFGPrinterPass (); 12896593Smarkm FunctionPass *createCFGOnlyPrinterPass (); 12996593Smarkm} // End llvm namespace 13096593Smarkm 13196593Smarkm#endif 13296593Smarkm