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