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