SelectionDAGPrinter.cpp revision 01078fb7ec3b8f62679c49a147a69b3978092500
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/Assembly/Writer.h"
17#include "llvm/CodeGen/SelectionDAG.h"
18#include "llvm/CodeGen/MachineConstantPool.h"
19#include "llvm/CodeGen/MachineFunction.h"
20#include "llvm/Target/MRegisterInfo.h"
21#include "llvm/Target/TargetMachine.h"
22#include "llvm/Support/GraphWriter.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/Config/config.h"
25#include <fstream>
26#include <sstream>
27using namespace llvm;
28
29namespace llvm {
30  template<>
31  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
32    static std::string getGraphName(const SelectionDAG *G) {
33      return G->getMachineFunction().getFunction()->getName();
34    }
35
36    static bool renderGraphFromBottomUp() {
37      return true;
38    }
39
40    static bool hasNodeAddressLabel(const SDNode *Node,
41                                    const SelectionDAG *Graph) {
42      return true;
43    }
44
45    static std::string getNodeLabel(const SDNode *Node,
46                                    const SelectionDAG *Graph);
47    static std::string getNodeAttributes(const SDNode *N,
48                                         const SelectionDAG *Graph) {
49#ifndef NDEBUG
50      const std::string &Attrs = Graph->getGraphAttrs(N);
51      if (!Attrs.empty()) {
52        if (Attrs.find("shape=") == std::string::npos)
53          return std::string("shape=Mrecord,") + Attrs;
54        else
55          return Attrs;
56      }
57#endif
58      return "shape=Mrecord";
59    }
60
61    static void addCustomGraphFeatures(SelectionDAG *G,
62                                       GraphWriter<SelectionDAG*> &GW) {
63      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
64      GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
65    }
66  };
67}
68
69std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
70                                                        const SelectionDAG *G) {
71  std::string Op = Node->getOperationName(G);
72
73  for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
74    if (Node->getValueType(i) == MVT::Other)
75      Op += ":ch";
76    else
77      Op = Op + ":" + MVT::getValueTypeString(Node->getValueType(i));
78
79  if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
80    Op += ": " + utostr(CSDN->getValue());
81  } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
82    Op += ": " + ftostr(CSDN->getValue());
83  } else if (const GlobalAddressSDNode *GADN =
84             dyn_cast<GlobalAddressSDNode>(Node)) {
85    int offset = GADN->getOffset();
86    Op += ": " + GADN->getGlobal()->getName();
87    if (offset > 0)
88      Op += "+" + itostr(offset);
89    else
90      Op += itostr(offset);
91  } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
92    Op += " " + itostr(FIDN->getIndex());
93  } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
94    if (CP->isMachineConstantPoolEntry()) {
95      std::ostringstream SS;
96      CP->getMachineCPVal()->print(SS);
97      Op += "<" + SS.str() + ">";
98    } else {
99      if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
100        Op += "<" + ftostr(CFP->getValue()) + ">";
101      else if (ConstantInt *CI = dyn_cast<ConstantInt>(CP->getConstVal()))
102        Op += "<" + utostr(CI->getZExtValue()) + ">";
103      else {
104        std::ostringstream SS;
105        WriteAsOperand(SS, CP->getConstVal(), false);
106        Op += "<" + SS.str() + ">";
107      }
108    }
109  } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
110    Op = "BB: ";
111    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
112    if (LBB)
113      Op += LBB->getName();
114    //Op += " " + (const void*)BBDN->getBasicBlock();
115  } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node)) {
116    if (G && R->getReg() != 0 && MRegisterInfo::isPhysicalRegister(R->getReg())) {
117      Op = Op + " " + G->getTarget().getRegisterInfo()->getName(R->getReg());
118    } else {
119      Op += " #" + utostr(R->getReg());
120    }
121  } else if (const ExternalSymbolSDNode *ES =
122             dyn_cast<ExternalSymbolSDNode>(Node)) {
123    Op += "'" + std::string(ES->getSymbol()) + "'";
124  } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
125    if (M->getValue())
126      Op += "<" + M->getValue()->getName() + ":" + itostr(M->getOffset()) + ">";
127    else
128      Op += "<null:" + itostr(M->getOffset()) + ">";
129  } else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
130    Op = Op + " VT=" + getValueTypeString(N->getVT());
131  } else if (const StringSDNode *N = dyn_cast<StringSDNode>(Node)) {
132    Op = Op + "\"" + N->getValue() + "\"";
133  }
134
135  return Op;
136}
137
138
139/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
140/// rendered using 'dot'.
141///
142void SelectionDAG::viewGraph() {
143// This code is only for debugging!
144#ifndef NDEBUG
145  ViewGraph(this, "dag." + getMachineFunction().getFunction()->getName());
146#else
147  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
148            << "systems with Graphviz or gv!\n";
149#endif  // NDEBUG
150}
151
152
153/// clearGraphAttrs - Clear all previously defined node graph attributes.
154/// Intended to be used from a debugging tool (eg. gdb).
155void SelectionDAG::clearGraphAttrs() {
156#ifndef NDEBUG
157  NodeGraphAttrs.clear();
158#else
159  std::cerr << "SelectionDAG::clearGraphAttrs is only available in debug builds"
160            << " on systems with Graphviz or gv!\n";
161#endif
162}
163
164
165/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
166///
167void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
168#ifndef NDEBUG
169  NodeGraphAttrs[N] = Attrs;
170#else
171  std::cerr << "SelectionDAG::setGraphAttrs is only available in debug builds"
172            << " on systems with Graphviz or gv!\n";
173#endif
174}
175
176
177/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
178/// Used from getNodeAttributes.
179const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
180#ifndef NDEBUG
181  std::map<const SDNode *, std::string>::const_iterator I =
182    NodeGraphAttrs.find(N);
183
184  if (I != NodeGraphAttrs.end())
185    return I->second;
186  else
187    return "";
188#else
189  std::cerr << "SelectionDAG::getGraphAttrs is only available in debug builds"
190            << " on systems with Graphviz or gv!\n";
191  return std::string("");
192#endif
193}
194
195/// setGraphColor - Convenience for setting node color attribute.
196///
197void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
198#ifndef NDEBUG
199  NodeGraphAttrs[N] = std::string("color=") + Color;
200#else
201  std::cerr << "SelectionDAG::setGraphColor is only available in debug builds"
202            << " on systems with Graphviz or gv!\n";
203#endif
204}
205
206