SelectionDAGPrinter.cpp revision 6bf234c4a894b898954f8be3fb5973caba241012
1//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This implements the SelectionDAG::viewGraph method.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Constants.h"
15#include "llvm/Function.h"
16#include "llvm/CodeGen/SelectionDAG.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/Target/MRegisterInfo.h"
19#include "llvm/Target/TargetMachine.h"
20#include "llvm/Support/GraphWriter.h"
21#include "llvm/System/Path.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Config/config.h"
24#include <fstream>
25using namespace llvm;
26
27namespace llvm {
28  template<>
29  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
30    static std::string getGraphName(const SelectionDAG *G) {
31      return G->getMachineFunction().getFunction()->getName();
32    }
33
34    static bool renderGraphFromBottomUp() {
35      return true;
36    }
37
38    static bool hasNodeAddressLabel(const SDNode *Node,
39                                    const SelectionDAG *Graph) {
40      return true;
41    }
42
43    static std::string getNodeLabel(const SDNode *Node,
44                                    const SelectionDAG *Graph);
45    static std::string getNodeAttributes(const SDNode *N) {
46      return "shape=Mrecord";
47    }
48
49    static void addCustomGraphFeatures(SelectionDAG *G,
50                                       GraphWriter<SelectionDAG*> &GW) {
51      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
52      GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
53    }
54  };
55}
56
57std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
58                                                        const SelectionDAG *G) {
59  std::string Op = Node->getOperationName(G);
60
61  for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
62    if (Node->getValueType(i) == MVT::Other)
63      Op += ":ch";
64    else
65      Op = Op + ":" + MVT::getValueTypeString(Node->getValueType(i));
66
67  if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
68    Op += ": " + utostr(CSDN->getValue());
69  } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
70    Op += ": " + ftostr(CSDN->getValue());
71  } else if (const GlobalAddressSDNode *GADN =
72             dyn_cast<GlobalAddressSDNode>(Node)) {
73    Op += ": " + GADN->getGlobal()->getName();
74  } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
75    Op += " " + itostr(FIDN->getIndex());
76  } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
77    if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->get()))
78      Op += "<" + ftostr(CFP->getValue()) + ">";
79  } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
80    Op = "BB: ";
81    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
82    if (LBB)
83      Op += LBB->getName();
84    //Op += " " + (const void*)BBDN->getBasicBlock();
85  } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node)) {
86    if (G && R->getReg() != 0 && MRegisterInfo::isPhysicalRegister(R->getReg())) {
87      Op = Op + " " + G->getTarget().getRegisterInfo()->getName(R->getReg());
88    } else {
89      Op += " #" + utostr(R->getReg());
90    }
91  } else if (const ExternalSymbolSDNode *ES =
92             dyn_cast<ExternalSymbolSDNode>(Node)) {
93    Op += "'" + std::string(ES->getSymbol()) + "'";
94  } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
95    if (M->getValue())
96      Op += "<" + M->getValue()->getName() + ":" + itostr(M->getOffset()) + ">";
97    else
98      Op += "<null:" + itostr(M->getOffset()) + ">";
99  } else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
100    Op = Op + " VT=" + getValueTypeString(N->getVT());
101  }
102  return Op;
103}
104
105
106/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
107/// rendered using 'dot'.
108///
109void SelectionDAG::viewGraph() {
110// This code is only for debugging!
111#ifndef NDEBUG
112  sys::Path TempDir = sys::Path::GetTemporaryDirectory();
113  sys::Path Filename = TempDir;
114  Filename.appendComponent("dag." + getMachineFunction().getFunction()->getName() + ".dot");
115  std::cerr << "Writing '" << Filename.toString() << "'... ";
116  std::ofstream F(Filename.toString().c_str());
117
118  if (!F) {
119    std::cerr << "  error opening file for writing!\n";
120    return;
121  }
122
123  WriteGraph(F, this);
124  F.close();
125  std::cerr << "\n";
126
127#ifdef HAVE_GRAPHVIZ
128  std::cerr << "Running 'Graphviz' program... " << std::flush;
129  if (system((LLVM_PATH_GRAPHVIZ " " + Filename.toString()).c_str())) {
130    std::cerr << "Error viewing graph: 'Graphviz' not in path?\n";
131  } else {
132	Filename.eraseFromDisk();
133    return;
134  }
135#endif  // HAVE_GRAPHVIZ
136
137#ifdef HAVE_GV
138  std::cerr << "Running 'dot' program... " << std::flush;
139  sys::Path PSFilename = TempDir;
140  PSFilename.appendComponent("dag.tempgraph.ps");
141  if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename.toString()
142              + " > " + PSFilename.toString()).c_str())) {
143    std::cerr << "Error viewing graph: 'dot' not in path?\n";
144  } else {
145    std::cerr << "\n";
146    system((LLVM_PATH_GV " " + PSFilename.toString()).c_str());
147    system((LLVM_PATH_GV " "+TempDir.toString()+ "dag.tempgraph.ps").c_str());
148  }
149  Filename.eraseFromDisk();
150  PSFilename.eraseFromDisk();
151  return;
152#endif  // HAVE_GV
153#endif  // NDEBUG
154  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
155            << "systems with Graphviz or gv!\n";
156
157#ifndef NDEBUG
158  Filename.eraseFromDisk();
159  TempDir.eraseFromDisk(true);
160#endif
161}
162