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