LLVM API Documentation
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 }