1 //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This implements the SelectionDAG::viewGraph method. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/CodeGen/SelectionDAG.h" 15 #include "ScheduleDAGSDNodes.h" 16 #include "llvm/ADT/DenseSet.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/Assembly/Writer.h" 19 #include "llvm/CodeGen/MachineConstantPool.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineModuleInfo.h" 22 #include "llvm/DebugInfo.h" 23 #include "llvm/IR/Constants.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/GraphWriter.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include "llvm/Target/TargetMachine.h" 28 #include "llvm/Target/TargetRegisterInfo.h" 29 using namespace llvm; 30 31 namespace llvm { 32 template<> 33 struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits { 34 35 explicit DOTGraphTraits(bool isSimple=false) : 36 DefaultDOTGraphTraits(isSimple) {} 37 38 static bool hasEdgeDestLabels() { 39 return true; 40 } 41 42 static unsigned numEdgeDestLabels(const void *Node) { 43 return ((const SDNode *) Node)->getNumValues(); 44 } 45 46 static std::string getEdgeDestLabel(const void *Node, unsigned i) { 47 return ((const SDNode *) Node)->getValueType(i).getEVTString(); 48 } 49 50 template<typename EdgeIter> 51 static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) { 52 return itostr(I - SDNodeIterator::begin((const SDNode *) Node)); 53 } 54 55 /// edgeTargetsEdgeSource - This method returns true if this outgoing edge 56 /// should actually target another edge source, not a node. If this method 57 /// is implemented, getEdgeTarget should be implemented. 58 template<typename EdgeIter> 59 static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { 60 return true; 61 } 62 63 /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is 64 /// called to determine which outgoing edge of Node is the target of this 65 /// edge. 66 template<typename EdgeIter> 67 static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { 68 SDNode *TargetNode = *I; 69 SDNodeIterator NI = SDNodeIterator::begin(TargetNode); 70 std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo()); 71 return NI; 72 } 73 74 static std::string getGraphName(const SelectionDAG *G) { 75 return G->getMachineFunction().getName(); 76 } 77 78 static bool renderGraphFromBottomUp() { 79 return true; 80 } 81 82 static bool hasNodeAddressLabel(const SDNode *Node, 83 const SelectionDAG *Graph) { 84 return true; 85 } 86 87 /// If you want to override the dot attributes printed for a particular 88 /// edge, override this method. 89 template<typename EdgeIter> 90 static std::string getEdgeAttributes(const void *Node, EdgeIter EI, 91 const SelectionDAG *Graph) { 92 SDValue Op = EI.getNode()->getOperand(EI.getOperand()); 93 EVT VT = Op.getValueType(); 94 if (VT == MVT::Glue) 95 return "color=red,style=bold"; 96 else if (VT == MVT::Other) 97 return "color=blue,style=dashed"; 98 return ""; 99 } 100 101 102 static std::string getSimpleNodeLabel(const SDNode *Node, 103 const SelectionDAG *G) { 104 std::string Result = Node->getOperationName(G); 105 { 106 raw_string_ostream OS(Result); 107 Node->print_details(OS, G); 108 } 109 return Result; 110 } 111 std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph); 112 static std::string getNodeAttributes(const SDNode *N, 113 const SelectionDAG *Graph) { 114 #ifndef NDEBUG 115 const std::string &Attrs = Graph->getGraphAttrs(N); 116 if (!Attrs.empty()) { 117 if (Attrs.find("shape=") == std::string::npos) 118 return std::string("shape=Mrecord,") + Attrs; 119 else 120 return Attrs; 121 } 122 #endif 123 return "shape=Mrecord"; 124 } 125 126 static void addCustomGraphFeatures(SelectionDAG *G, 127 GraphWriter<SelectionDAG*> &GW) { 128 GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); 129 if (G->getRoot().getNode()) 130 GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(), 131 "color=blue,style=dashed"); 132 } 133 }; 134 } 135 136 std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node, 137 const SelectionDAG *G) { 138 return DOTGraphTraits<SelectionDAG*>::getSimpleNodeLabel(Node, G); 139 } 140 141 142 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG 143 /// rendered using 'dot'. 144 /// 145 void SelectionDAG::viewGraph(const std::string &Title) { 146 // This code is only for debugging! 147 #ifndef NDEBUG 148 ViewGraph(this, "dag." + getMachineFunction().getName(), 149 false, Title); 150 #else 151 errs() << "SelectionDAG::viewGraph is only available in debug builds on " 152 << "systems with Graphviz or gv!\n"; 153 #endif // NDEBUG 154 } 155 156 // This overload is defined out-of-line here instead of just using a 157 // default parameter because this is easiest for gdb to call. 158 void SelectionDAG::viewGraph() { 159 viewGraph(""); 160 } 161 162 /// clearGraphAttrs - Clear all previously defined node graph attributes. 163 /// Intended to be used from a debugging tool (eg. gdb). 164 void SelectionDAG::clearGraphAttrs() { 165 #ifndef NDEBUG 166 NodeGraphAttrs.clear(); 167 #else 168 errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds" 169 << " on systems with Graphviz or gv!\n"; 170 #endif 171 } 172 173 174 /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) 175 /// 176 void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) { 177 #ifndef NDEBUG 178 NodeGraphAttrs[N] = Attrs; 179 #else 180 errs() << "SelectionDAG::setGraphAttrs is only available in debug builds" 181 << " on systems with Graphviz or gv!\n"; 182 #endif 183 } 184 185 186 /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) 187 /// Used from getNodeAttributes. 188 const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const { 189 #ifndef NDEBUG 190 std::map<const SDNode *, std::string>::const_iterator I = 191 NodeGraphAttrs.find(N); 192 193 if (I != NodeGraphAttrs.end()) 194 return I->second; 195 else 196 return ""; 197 #else 198 errs() << "SelectionDAG::getGraphAttrs is only available in debug builds" 199 << " on systems with Graphviz or gv!\n"; 200 return std::string(); 201 #endif 202 } 203 204 /// setGraphColor - Convenience for setting node color attribute. 205 /// 206 void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) { 207 #ifndef NDEBUG 208 NodeGraphAttrs[N] = std::string("color=") + Color; 209 #else 210 errs() << "SelectionDAG::setGraphColor is only available in debug builds" 211 << " on systems with Graphviz or gv!\n"; 212 #endif 213 } 214 215 /// setSubgraphColorHelper - Implement setSubgraphColor. Return 216 /// whether we truncated the search. 217 /// 218 bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited, 219 int level, bool &printed) { 220 bool hit_limit = false; 221 222 #ifndef NDEBUG 223 if (level >= 20) { 224 if (!printed) { 225 printed = true; 226 DEBUG(dbgs() << "setSubgraphColor hit max level\n"); 227 } 228 return true; 229 } 230 231 unsigned oldSize = visited.size(); 232 visited.insert(N); 233 if (visited.size() != oldSize) { 234 setGraphColor(N, Color); 235 for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N); 236 i != iend; 237 ++i) { 238 hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit; 239 } 240 } 241 #else 242 errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" 243 << " on systems with Graphviz or gv!\n"; 244 #endif 245 return hit_limit; 246 } 247 248 /// setSubgraphColor - Convenience for setting subgraph color attribute. 249 /// 250 void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) { 251 #ifndef NDEBUG 252 DenseSet<SDNode *> visited; 253 bool printed = false; 254 if (setSubgraphColorHelper(N, Color, visited, 0, printed)) { 255 // Visually mark that we hit the limit 256 if (strcmp(Color, "red") == 0) { 257 setSubgraphColorHelper(N, "blue", visited, 0, printed); 258 } else if (strcmp(Color, "yellow") == 0) { 259 setSubgraphColorHelper(N, "green", visited, 0, printed); 260 } 261 } 262 263 #else 264 errs() << "SelectionDAG::setSubgraphColor is only available in debug builds" 265 << " on systems with Graphviz or gv!\n"; 266 #endif 267 } 268 269 std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const { 270 std::string s; 271 raw_string_ostream O(s); 272 O << "SU(" << SU->NodeNum << "): "; 273 if (SU->getNode()) { 274 SmallVector<SDNode *, 4> GluedNodes; 275 for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) 276 GluedNodes.push_back(N); 277 while (!GluedNodes.empty()) { 278 O << DOTGraphTraits<SelectionDAG*> 279 ::getSimpleNodeLabel(GluedNodes.back(), DAG); 280 GluedNodes.pop_back(); 281 if (!GluedNodes.empty()) 282 O << "\n "; 283 } 284 } else { 285 O << "CROSS RC COPY"; 286 } 287 return O.str(); 288 } 289 290 void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const { 291 if (DAG) { 292 // Draw a special "GraphRoot" node to indicate the root of the graph. 293 GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); 294 const SDNode *N = DAG->getRoot().getNode(); 295 if (N && N->getNodeId() != -1) 296 GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1, 297 "color=blue,style=dashed"); 298 } 299 } 300