SelectionDAGPrinter.cpp revision 37345fe3cd2dd56c3711592a5af6c294c10c7aba
166328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
2edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman//
366328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//                     The LLVM Compiler Infrastructure
466328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//
566328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner// This file was developed by the LLVM research group and is distributed under
666328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner// the University of Illinois Open Source License. See LICENSE.TXT for details.
7edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman//
866328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//===----------------------------------------------------------------------===//
966328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//
1066328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner// This implements the SelectionDAG::viewGraph method.
1166328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//
1266328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner//===----------------------------------------------------------------------===//
1366328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner
145839bf2b3bd22689d9dd0e9de66c2dce71d130aeChris Lattner#include "llvm/Constants.h"
155839bf2b3bd22689d9dd0e9de66c2dce71d130aeChris Lattner#include "llvm/Function.h"
1666328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner#include "llvm/CodeGen/SelectionDAG.h"
1766328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner#include "llvm/CodeGen/MachineFunction.h"
187228aa78686c2920c0f8588628b1278698720d07Chris Lattner#include "llvm/Target/MRegisterInfo.h"
197228aa78686c2920c0f8588628b1278698720d07Chris Lattner#include "llvm/Target/TargetMachine.h"
2066328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner#include "llvm/Support/GraphWriter.h"
21e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner#include "llvm/ADT/StringExtras.h"
226e741f8842b5570e30f25912dbdaaa2edf36110cChris Lattner#include "llvm/Config/config.h"
2366328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner#include <fstream>
2466328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattnerusing namespace llvm;
2566328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner
26e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattnernamespace llvm {
27e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner  template<>
28e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
29e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner    static std::string getGraphName(const SelectionDAG *G) {
30e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner      return G->getMachineFunction().getFunction()->getName();
31e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner    }
32e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner
33e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    static bool renderGraphFromBottomUp() {
34e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner      return true;
35e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner    }
3637345fe3cd2dd56c3711592a5af6c294c10c7abaChris Lattner
3737345fe3cd2dd56c3711592a5af6c294c10c7abaChris Lattner    static bool hasNodeAddressLabel(const SDNode *Node,
3837345fe3cd2dd56c3711592a5af6c294c10c7abaChris Lattner                                    const SelectionDAG *Graph) {
3937345fe3cd2dd56c3711592a5af6c294c10c7abaChris Lattner      return true;
4037345fe3cd2dd56c3711592a5af6c294c10c7abaChris Lattner    }
41e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner
42e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    static std::string getNodeLabel(const SDNode *Node,
43e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner                                    const SelectionDAG *Graph);
44e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner    static std::string getNodeAttributes(const SDNode *N) {
45e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner      return "shape=Mrecord";
46e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner    }
47fc08d9c789b6698fe5f5904d573bb03fcc52a32dChris Lattner
48fc08d9c789b6698fe5f5904d573bb03fcc52a32dChris Lattner    static void addCustomGraphFeatures(SelectionDAG *G,
49fc08d9c789b6698fe5f5904d573bb03fcc52a32dChris Lattner                                       GraphWriter<SelectionDAG*> &GW) {
50fc08d9c789b6698fe5f5904d573bb03fcc52a32dChris Lattner      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
51fc08d9c789b6698fe5f5904d573bb03fcc52a32dChris Lattner      GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
52fc08d9c789b6698fe5f5904d573bb03fcc52a32dChris Lattner    }
53e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner  };
54e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner}
55e0646b86e3cdc35c5dd0e1c10b7ac564066e3bd6Chris Lattner
56e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattnerstd::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
57e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner                                                        const SelectionDAG *G) {
58ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner  std::string Op = Node->getOperationName(G);
59c871e1d56fa9e4c73f01419d4f1fef6d47f24d29Chris Lattner
60ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner  for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
61ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner    if (Node->getValueType(i) == MVT::Other)
62ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner      Op += ":ch";
63ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner    else
64ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner      Op = Op + ":" + MVT::getValueTypeString(Node->getValueType(i));
65ad95d6ab201bad53ae155a06d49cc16cfbebe507Chris Lattner
66e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner  if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
67e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    Op += ": " + utostr(CSDN->getValue());
68e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner  } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
69e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    Op += ": " + ftostr(CSDN->getValue());
70edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman  } else if (const GlobalAddressSDNode *GADN =
71e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner             dyn_cast<GlobalAddressSDNode>(Node)) {
72e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    Op += ": " + GADN->getGlobal()->getName();
73dedf2bd5a34dac25e4245f58bb902ced6b64edd9Misha Brukman  } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
74e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    Op += " " + itostr(FIDN->getIndex());
75e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner  } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
765839bf2b3bd22689d9dd0e9de66c2dce71d130aeChris Lattner    if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->get()))
775839bf2b3bd22689d9dd0e9de66c2dce71d130aeChris Lattner      Op += "<" + ftostr(CFP->getValue()) + ">";
78dedf2bd5a34dac25e4245f58bb902ced6b64edd9Misha Brukman  } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
79e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    Op = "BB: ";
80e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
81e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    if (LBB)
82e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner      Op += LBB->getName();
83e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    //Op += " " + (const void*)BBDN->getBasicBlock();
84d5d0f9bd20d9df07d6b4d41b7e8ed6d33b6a649dChris Lattner  } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node)) {
857228aa78686c2920c0f8588628b1278698720d07Chris Lattner    if (G && MRegisterInfo::isPhysicalRegister(R->getReg())) {
867228aa78686c2920c0f8588628b1278698720d07Chris Lattner      Op = Op + " " + G->getTarget().getRegisterInfo()->getName(R->getReg());
877228aa78686c2920c0f8588628b1278698720d07Chris Lattner    } else {
887228aa78686c2920c0f8588628b1278698720d07Chris Lattner      Op += " #" + utostr(R->getReg());
897228aa78686c2920c0f8588628b1278698720d07Chris Lattner    }
90e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner  } else if (const ExternalSymbolSDNode *ES =
91e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner             dyn_cast<ExternalSymbolSDNode>(Node)) {
92e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner    Op += "'" + std::string(ES->getSymbol()) + "'";
932bf3c26b2bb783aada259f1c70be6dd0798f6126Chris Lattner  } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
942bf3c26b2bb783aada259f1c70be6dd0798f6126Chris Lattner    if (M->getValue())
952bf3c26b2bb783aada259f1c70be6dd0798f6126Chris Lattner      Op += "<" + M->getValue()->getName() + ":" + itostr(M->getOffset()) + ">";
962bf3c26b2bb783aada259f1c70be6dd0798f6126Chris Lattner    else
972bf3c26b2bb783aada259f1c70be6dd0798f6126Chris Lattner      Op += "<null:" + itostr(M->getOffset()) + ">";
98a23e8154dc58a62225074bb4eb1633c363ce331bChris Lattner  } else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
99e39db07713641cb933d1183a343ffe4eb8f44492Chris Lattner    Op = Op + " VT=" + getValueTypeString(N->getVT());
100e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner  }
101e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner  return Op;
102e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner}
103edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman
104e9c44cdf18b1235841a5d8bfeb07bee9f5699b9aChris Lattner
10566328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
10666328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner/// rendered using 'dot'.
10766328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner///
10866328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattnervoid SelectionDAG::viewGraph() {
109e388b5ea2c599a1db72497bf2d2920895da28f47Chris Lattner// This code is only for debugging!
110c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner#ifndef NDEBUG
11166328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  std::string Filename = "/tmp/dag." +
11266328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner    getMachineFunction().getFunction()->getName() + ".dot";
11366328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  std::cerr << "Writing '" << Filename << "'... ";
11466328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  std::ofstream F(Filename.c_str());
11566328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner
11666328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  if (!F) {
11766328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner    std::cerr << "  error opening file for writing!\n";
11866328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner    return;
11966328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  }
12066328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner
12166328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  WriteGraph(F, this);
12266328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  F.close();
12366328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  std::cerr << "\n";
12466328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner
125f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner#ifdef HAVE_GRAPHVIZ
126f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner  std::cerr << "Running 'Graphviz' program... " << std::flush;
127c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner  if (system((LLVM_PATH_GRAPHVIZ " " + Filename).c_str())) {
128f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner    std::cerr << "Error viewing graph: 'Graphviz' not in path?\n";
129f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner  } else {
1304c64dd7977bc676399df0d5d2bf8016a3242780eChris Lattner    system(("rm " + Filename).c_str());
131f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner    return;
132f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner  }
133cd33eef1b2dc1e81ab57b4857cb63c47bb62a496Misha Brukman#endif  // HAVE_GRAPHVIZ
134f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner
135c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner#ifdef HAVE_GV
13666328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  std::cerr << "Running 'dot' program... " << std::flush;
13766328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
13866328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner              + " > /tmp/dag.tempgraph.ps").c_str())) {
139f1a2f15ed35c1cf987f6a1a703f855a3c61fdab6Chris Lattner    std::cerr << "Error viewing graph: 'dot' not in path?\n";
14066328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  } else {
14166328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner    std::cerr << "\n";
142c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner    system(LLVM_PATH_GV " /tmp/dag.tempgraph.ps");
14366328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  }
14466328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner  system(("rm " + Filename + " /tmp/dag.tempgraph.ps").c_str());
145c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner  return;
146cd33eef1b2dc1e81ab57b4857cb63c47bb62a496Misha Brukman#endif  // HAVE_GV
147cd33eef1b2dc1e81ab57b4857cb63c47bb62a496Misha Brukman#endif  // NDEBUG
148c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner  std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
149c5f44add43bf9ecb7f1f63a320e4440f8f0784c3Chris Lattner            << "systems with Graphviz or gv!\n";
150cd33eef1b2dc1e81ab57b4857cb63c47bb62a496Misha Brukman
151cd33eef1b2dc1e81ab57b4857cb63c47bb62a496Misha Brukman#ifndef NDEBUG
1524c64dd7977bc676399df0d5d2bf8016a3242780eChris Lattner  system(("rm " + Filename).c_str());
153cd33eef1b2dc1e81ab57b4857cb63c47bb62a496Misha Brukman#endif
15466328480bb3eb6aa52e2c155657f3d19d4efea7aChris Lattner}
155