LLVM API Documentation
00001 //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This implements the SelectionDAG::viewGraph method. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/CodeGen/SelectionDAG.h" 00015 #include "ScheduleDAGSDNodes.h" 00016 #include "llvm/ADT/DenseSet.h" 00017 #include "llvm/ADT/StringExtras.h" 00018 #include "llvm/Assembly/Writer.h" 00019 #include "llvm/CodeGen/MachineConstantPool.h" 00020 #include "llvm/CodeGen/MachineFunction.h" 00021 #include "llvm/CodeGen/MachineModuleInfo.h" 00022 #include "llvm/DebugInfo.h" 00023 #include "llvm/IR/Constants.h" 00024 #include "llvm/Support/Debug.h" 00025 #include "llvm/Support/GraphWriter.h" 00026 #include "llvm/Support/raw_ostream.h" 00027 #include "llvm/Target/TargetMachine.h" 00028 #include "llvm/Target/TargetRegisterInfo.h" 00029 using namespace llvm; 00030 00031 namespace llvm { 00032 template<> 00033 struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits { 00034 00035 explicit DOTGraphTraits(bool isSimple=false) : 00036 DefaultDOTGraphTraits(isSimple) {} 00037 00038 static bool hasEdgeDestLabels() { 00039 return true; 00040 } 00041 00042 static unsigned numEdgeDestLabels(const void *Node) { 00043 return ((const SDNode *) Node)->getNumValues(); 00044 } 00045 00046 static std::string getEdgeDestLabel(const void *Node, unsigned i) { 00047 return ((const SDNode *) Node)->getValueType(i).getEVTString(); 00048 } 00049 00050 template<typename EdgeIter> 00051 static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) { 00052 return itostr(I - SDNodeIterator::begin((const SDNode *) Node)); 00053 } 00054 00055 /// edgeTargetsEdgeSource - This method returns true if this outgoing edge 00056 /// should actually target another edge source, not a node. If this method 00057 /// is implemented, getEdgeTarget should be implemented. 00058 template<typename EdgeIter> 00059 static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { 00060 return true; 00061 } 00062 00063 /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is 00064 /// called to determine which outgoing edge of Node is the target of this 00065 /// edge. 00066 template<typename EdgeIter> 00067 static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { 00068 SDNode *TargetNode = *I; 00069 SDNodeIterator NI = SDNodeIterator::begin(TargetNode); 00070 std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo()); 00071 return NI; 00072 } 00073 00074 static std::string getGraphName(const SelectionDAG *G) { 00075 return G->getMachineFunction().getName(); 00076 } 00077 00078 static bool renderGraphFromBottomUp() { 00079 return true; 00080 } 00081 00082 static bool hasNodeAddressLabel(const SDNode *Node, 00083 const SelectionDAG *Graph) { 00084 return true; 00085 } 00086 00087 /// If you want to override the dot attributes printed for a particular 00088 /// edge, override this method. 00089 template<typename EdgeIter> 00090 static std::string getEdgeAttributes(const void *Node, EdgeIter EI, 00091 const SelectionDAG *Graph) { 00092 SDValue Op = EI.getNode()->getOperand(EI.getOperand()); 00093 EVT VT = Op.getValueType(); 00094 if (VT == MVT::Glue) 00095 return "color=red,style=bold"; 00096 else if (VT == MVT::Other) 00097 return "color=blue,style=dashed"; 00098 return ""; 00099 } 00100 00101 00102 static std::string getSimpleNodeLabel(const SDNode *Node, 00103 const SelectionDAG *G) { 00104 std::string Result = Node->getOperationName(G); 00105 { 00106 raw_string_ostream OS(Result); 00107 Node->print_details(OS, G); 00108 } 00109 return Result; 00110 } 00111 std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph); 00112 static std::string getNodeAttributes(const SDNode *N, 00113 const SelectionDAG *Graph) { 00114 #ifndef NDEBUG 00115 const std::string &Attrs = Graph->getGraphAttrs(N); 00116 if (!Attrs.empty()) { 00117 if (Attrs.find("shape=") == std::string::npos) 00118 return std::string("shape=Mrecord,") + Attrs; 00119 else 00120 return Attrs; 00121 } 00122 #endif 00123 return "shape=Mrecord"; 00124 } 00125 00126 static void addCustomGraphFeatures(SelectionDAG *G, 00127 GraphWriter<SelectionDAG*> &GW) { 00128 GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); 00129 if (G->getRoot().getNode()) 00130 GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(), 00131 "color=blue,style=dashed"); 00132 } 00133 }; 00134 } 00135 00136 std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node, 00137 const SelectionDAG *G) { 00138 return DOTGraphTraits<SelectionDAG*>::getSimpleNodeLabel(Node, G); 00139 } 00140 00141 00142 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG 00143 /// rendered using 'dot'. 00144 /// 00145 void SelectionDAG::viewGraph(const std::string &Title) { 00146 // This code is only for debugging! 00147 #ifndef NDEBUG 00148 ViewGraph(this, "dag." + getMachineFunction().getName(), 00149 false, Title); 00150 #else 00151 errs() << "SelectionDAG::viewGraph is only available in debug builds on " 00152 << "systems with Graphviz or gv!\n"; 00153 #endif // NDEBUG 00154 } 00155 00156 // This overload is defined out-of-line here instead of just using a 00157 // default parameter because this is easiest for gdb to call. 00158 void SelectionDAG::viewGraph() { 00159 viewGraph(""); 00160 } 00161 00162 /// clearGraphAttrs - Clear all previously defined node graph attributes. 00163 /// Intended to be used from a debugging tool (eg. gdb). 00164 void SelectionDAG::clearGraphAttrs() { 00165 #ifndef NDEBUG 00166 NodeGraphAttrs.clear(); 00167 #else 00168 errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds" 00169 << " on systems with Graphviz or gv!\n"; 00170 #endif 00171 } 00172 00173 00174 /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) 00175 /// 00176 void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) { 00177 #ifndef NDEBUG 00178 NodeGraphAttrs[N] = Attrs; 00179 #else 00180 errs() << "SelectionDAG::setGraphAttrs is only available in debug builds" 00181 << " on systems with Graphviz or gv!\n"; 00182 #endif 00183 } 00184 00185 00186 /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) 00187 /// Used from getNodeAttributes. 00188 const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const { 00189 #ifndef NDEBUG 00190 std::map<const SDNode *, std::string>::const_iterator I = 00191 NodeGraphAttrs.find(N); 00192 00193 if (I != NodeGraphAttrs.end()) 00194 return I->second; 00195 else 00196 return ""; 00197 #else 00198 errs() << "SelectionDAG::getGraphAttrs is only available in debug builds" 00199 << " on systems with Graphviz or gv!\n"; 00200 return std::string(); 00201 #endif 00202 } 00203 00204 /// setGraphColor - Convenience for setting node color attribute. 00205 /// 00206 void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) { 00207 #ifndef NDEBUG 00208 NodeGraphAttrs[N] = std::string("color=") + Color; 00209 #else 00210 errs() << "SelectionDAG::setGraphColor is only available in debug builds" 00211 << " on systems with Graphviz or gv!\n"; 00212 #endif 00213 } 00214 00215 /// setSubgraphColorHelper - Implement setSubgraphColor. Return 00216 /// whether we truncated the search. 00217 /// 00218 bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited, 00219 int level, bool &printed) { 00220 bool hit_limit = false; 00221 00222 #ifndef NDEBUG 00223 if (level >= 20) { 00224 if (!printed) { 00225 printed = true; 00226 DEBUG(dbgs() << "setSubgraphColor hit max level\n"); 00227 } 00228 return true; 00229 } 00230 00231 unsigned oldSize = visited.size(); 00232 visited.insert(N); 00233 if (visited.size() != oldSize) { 00234 setGraphColor(N, Color); 00235 for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N); 00236 i != iend; 00237 ++i) { 00238 hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit; 00239 } 00240 } 00241 #else 00242 errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" 00243 << " on systems with Graphviz or gv!\n"; 00244 #endif 00245 return hit_limit; 00246 } 00247 00248 /// setSubgraphColor - Convenience for setting subgraph color attribute. 00249 /// 00250 void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) { 00251 #ifndef NDEBUG 00252 DenseSet<SDNode *> visited; 00253 bool printed = false; 00254 if (setSubgraphColorHelper(N, Color, visited, 0, printed)) { 00255 // Visually mark that we hit the limit 00256 if (strcmp(Color, "red") == 0) { 00257 setSubgraphColorHelper(N, "blue", visited, 0, printed); 00258 } else if (strcmp(Color, "yellow") == 0) { 00259 setSubgraphColorHelper(N, "green", visited, 0, printed); 00260 } 00261 } 00262 00263 #else 00264 errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" 00265 << " on systems with Graphviz or gv!\n"; 00266 #endif 00267 } 00268 00269 std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const { 00270 std::string s; 00271 raw_string_ostream O(s); 00272 O << "SU(" << SU->NodeNum << "): "; 00273 if (SU->getNode()) { 00274 SmallVector<SDNode *, 4> GluedNodes; 00275 for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) 00276 GluedNodes.push_back(N); 00277 while (!GluedNodes.empty()) { 00278 O << DOTGraphTraits<SelectionDAG*> 00279 ::getSimpleNodeLabel(GluedNodes.back(), DAG); 00280 GluedNodes.pop_back(); 00281 if (!GluedNodes.empty()) 00282 O << "\n "; 00283 } 00284 } else { 00285 O << "CROSS RC COPY"; 00286 } 00287 return O.str(); 00288 } 00289 00290 void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const { 00291 if (DAG) { 00292 // Draw a special "GraphRoot" node to indicate the root of the graph. 00293 GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); 00294 const SDNode *N = DAG->getRoot().getNode(); 00295 if (N && N->getNodeId() != -1) 00296 GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1, 00297 "color=blue,style=dashed"); 00298 } 00299 }