LLVM API Documentation

SelectionDAGPrinter.cpp

Go to the documentation of this file.
00001 //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This implements the SelectionDAG::viewGraph method.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Constants.h"
00015 #include "llvm/Function.h"
00016 #include "llvm/Assembly/Writer.h"
00017 #include "llvm/CodeGen/SelectionDAG.h"
00018 #include "llvm/CodeGen/MachineFunction.h"
00019 #include "llvm/Target/MRegisterInfo.h"
00020 #include "llvm/Target/TargetMachine.h"
00021 #include "llvm/Support/GraphWriter.h"
00022 #include "llvm/System/Path.h"
00023 #include "llvm/ADT/StringExtras.h"
00024 #include "llvm/Config/config.h"
00025 #include <fstream>
00026 #include <sstream>
00027 using namespace llvm;
00028 
00029 namespace llvm {
00030   template<>
00031   struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
00032     static std::string getGraphName(const SelectionDAG *G) {
00033       return G->getMachineFunction().getFunction()->getName();
00034     }
00035 
00036     static bool renderGraphFromBottomUp() {
00037       return true;
00038     }
00039     
00040     static bool hasNodeAddressLabel(const SDNode *Node,
00041                                     const SelectionDAG *Graph) {
00042       return true;
00043     }
00044 
00045     static std::string getNodeLabel(const SDNode *Node,
00046                                     const SelectionDAG *Graph);
00047     static std::string getNodeAttributes(const SDNode *N) {
00048       return "shape=Mrecord";
00049     }
00050 
00051     static void addCustomGraphFeatures(SelectionDAG *G,
00052                                        GraphWriter<SelectionDAG*> &GW) {
00053       GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
00054       GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
00055     }
00056   };
00057 }
00058 
00059 std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
00060                                                         const SelectionDAG *G) {
00061   std::string Op = Node->getOperationName(G);
00062 
00063   for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
00064     if (Node->getValueType(i) == MVT::Other)
00065       Op += ":ch";
00066     else
00067       Op = Op + ":" + MVT::getValueTypeString(Node->getValueType(i));
00068     
00069   if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
00070     Op += ": " + utostr(CSDN->getValue());
00071   } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
00072     Op += ": " + ftostr(CSDN->getValue());
00073   } else if (const GlobalAddressSDNode *GADN =
00074              dyn_cast<GlobalAddressSDNode>(Node)) {
00075     int offset = GADN->getOffset();
00076     Op += ": " + GADN->getGlobal()->getName();
00077     if (offset > 0)
00078       Op += "+" + itostr(offset);
00079     else
00080       Op += itostr(offset);
00081   } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
00082     Op += " " + itostr(FIDN->getIndex());
00083   } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
00084     if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->get()))
00085       Op += "<" + ftostr(CFP->getValue()) + ">";
00086     else if (ConstantInt *CI = dyn_cast<ConstantInt>(CP->get()))
00087       Op += "<" + utostr(CI->getZExtValue()) + ">";
00088     else {
00089       std::ostringstream SS;
00090       WriteAsOperand(SS, CP->get(), false);
00091       Op += "<" + SS.str() + ">";
00092     }
00093   } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
00094     Op = "BB: ";
00095     const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
00096     if (LBB)
00097       Op += LBB->getName();
00098     //Op += " " + (const void*)BBDN->getBasicBlock();
00099   } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node)) {
00100     if (G && R->getReg() != 0 && MRegisterInfo::isPhysicalRegister(R->getReg())) {
00101       Op = Op + " " + G->getTarget().getRegisterInfo()->getName(R->getReg());
00102     } else {
00103       Op += " #" + utostr(R->getReg());
00104     }
00105   } else if (const ExternalSymbolSDNode *ES =
00106              dyn_cast<ExternalSymbolSDNode>(Node)) {
00107     Op += "'" + std::string(ES->getSymbol()) + "'";
00108   } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
00109     if (M->getValue())
00110       Op += "<" + M->getValue()->getName() + ":" + itostr(M->getOffset()) + ">";
00111     else
00112       Op += "<null:" + itostr(M->getOffset()) + ">";
00113   } else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
00114     Op = Op + " VT=" + getValueTypeString(N->getVT());
00115   } else if (const StringSDNode *N = dyn_cast<StringSDNode>(Node)) {
00116     Op = Op + "\"" + N->getValue() + "\"";
00117   }
00118   
00119   return Op;
00120 }
00121 
00122 
00123 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
00124 /// rendered using 'dot'.
00125 ///
00126 void SelectionDAG::viewGraph() {
00127 // This code is only for debugging!
00128 #ifndef NDEBUG
00129   sys::Path TempDir = sys::Path::GetTemporaryDirectory();
00130   sys::Path Filename = TempDir;
00131   Filename.appendComponent("dag." + getMachineFunction().getFunction()->getName() + ".dot");
00132   std::cerr << "Writing '" << Filename.toString() << "'... ";
00133   std::ofstream F(Filename.toString().c_str());
00134 
00135   if (!F) {
00136     std::cerr << "  error opening file for writing!\n";
00137     return;
00138   }
00139 
00140   WriteGraph(F, this);
00141   F.close();
00142   std::cerr << "\n";
00143 
00144 #ifdef HAVE_GRAPHVIZ
00145   std::cerr << "Running 'Graphviz' program... " << std::flush;
00146   if (system((LLVM_PATH_GRAPHVIZ " " + Filename.toString()).c_str())) {
00147     std::cerr << "Error viewing graph: 'Graphviz' not in path?\n";
00148   } else {
00149   Filename.eraseFromDisk();
00150     return;
00151   }
00152 #endif  // HAVE_GRAPHVIZ
00153 
00154 #ifdef HAVE_GV
00155   std::cerr << "Running 'dot' program... " << std::flush;
00156   sys::Path PSFilename = TempDir;
00157   PSFilename.appendComponent("dag.tempgraph.ps");
00158   if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename.toString()
00159               + " > " + PSFilename.toString()).c_str())) {
00160     std::cerr << "Error viewing graph: 'dot' not in path?\n";
00161   } else {
00162     std::cerr << "\n";
00163     system((LLVM_PATH_GV " " + PSFilename.toString()).c_str());
00164     system((LLVM_PATH_GV " "+TempDir.toString()+ "dag.tempgraph.ps").c_str());
00165   }
00166   Filename.eraseFromDisk();
00167   PSFilename.eraseFromDisk();
00168   return;
00169 #endif  // HAVE_GV
00170 #endif  // NDEBUG
00171   std::cerr << "SelectionDAG::viewGraph is only available in debug builds on "
00172             << "systems with Graphviz or gv!\n";
00173 
00174 #ifndef NDEBUG
00175   Filename.eraseFromDisk();
00176   TempDir.eraseFromDisk(true);
00177 #endif
00178 }