1551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer//===-- llvm/Support/GraphWriter.h - Write graph to a .dot file -*- C++ -*-===// 263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman// 3b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// The LLVM Compiler Infrastructure 4b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// 57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source 67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details. 763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman// 8b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//===----------------------------------------------------------------------===// 995b923d548ed2e0f0993bb613868c871646f120cChris Lattner// 1095b923d548ed2e0f0993bb613868c871646f120cChris Lattner// This file defines a simple interface that can be used to print out generic 1195b923d548ed2e0f0993bb613868c871646f120cChris Lattner// LLVM graphs to ".dot" files. "dot" is a tool that is part of the AT&T 1295b923d548ed2e0f0993bb613868c871646f120cChris Lattner// graphviz package (http://www.research.att.com/sw/tools/graphviz/) which can 1395b923d548ed2e0f0993bb613868c871646f120cChris Lattner// be used to turn the files output by this interface into a variety of 1495b923d548ed2e0f0993bb613868c871646f120cChris Lattner// different graphics formats. 1595b923d548ed2e0f0993bb613868c871646f120cChris Lattner// 1695b923d548ed2e0f0993bb613868c871646f120cChris Lattner// Graphs do not need to implement any interface past what is already required 1795b923d548ed2e0f0993bb613868c871646f120cChris Lattner// by the GraphTraits template, but they can choose to implement specializations 1895b923d548ed2e0f0993bb613868c871646f120cChris Lattner// of the DOTGraphTraits template if they want to customize the graphs output in 1995b923d548ed2e0f0993bb613868c871646f120cChris Lattner// any way. 2095b923d548ed2e0f0993bb613868c871646f120cChris Lattner// 2195b923d548ed2e0f0993bb613868c871646f120cChris Lattner//===----------------------------------------------------------------------===// 2295b923d548ed2e0f0993bb613868c871646f120cChris Lattner 23551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#ifndef LLVM_SUPPORT_GRAPHWRITER_H 24551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#define LLVM_SUPPORT_GRAPHWRITER_H 2595b923d548ed2e0f0993bb613868c871646f120cChris Lattner 26551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/GraphTraits.h" 27255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "llvm/Support/DOTGraphTraits.h" 281f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Path.h" 29255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "llvm/Support/raw_ostream.h" 30229509a8bc2390c4c9c1bd20f777acf29911d452David Greene#include <cassert> 31255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include <vector> 3295b923d548ed2e0f0993bb613868c871646f120cChris Lattner 33d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekenamespace llvm { 34d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 3595b923d548ed2e0f0993bb613868c871646f120cChris Lattnernamespace DOT { // Private functions... 36103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner std::string EscapeString(const std::string &Label); 37c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick 38c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick /// \brief Get a color string for this node number. Simply round-robin selects 39c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick /// from a reasonable number of colors. 40c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick StringRef getColorString(unsigned NodeNumber); 4195b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 4295b923d548ed2e0f0993bb613868c871646f120cChris Lattner 4300ad26ff5760ff2d1b24acb18718e63541088923David Greenenamespace GraphProgram { 4400ad26ff5760ff2d1b24acb18718e63541088923David Greene enum Name { 4500ad26ff5760ff2d1b24acb18718e63541088923David Greene DOT, 4600ad26ff5760ff2d1b24acb18718e63541088923David Greene FDP, 4700ad26ff5760ff2d1b24acb18718e63541088923David Greene NEATO, 4800ad26ff5760ff2d1b24acb18718e63541088923David Greene TWOPI, 4900ad26ff5760ff2d1b24acb18718e63541088923David Greene CIRCO 5000ad26ff5760ff2d1b24acb18718e63541088923David Greene }; 5100ad26ff5760ff2d1b24acb18718e63541088923David Greene} 5265b660743ccce5393f70d3667ac4e2b0b76e5236Daniel Dunbar 53cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool DisplayGraph(StringRef Filename, bool wait = true, 544d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola GraphProgram::Name program = GraphProgram::DOT); 55ba0e380ea9eaf051c45ce072f4cac7dccc867c90Rafael Espindola 5695b923d548ed2e0f0993bb613868c871646f120cChris Lattnertemplate<typename GraphType> 578c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerclass GraphWriter { 58103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner raw_ostream &O; 598c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner const GraphType &G; 6095b923d548ed2e0f0993bb613868c871646f120cChris Lattner 618c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef DOTGraphTraits<GraphType> DOTTraits; 628c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef GraphTraits<GraphType> GTraits; 638c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::NodeType NodeType; 648c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::nodes_iterator node_iterator; 658c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::ChildIteratorType child_iterator; 66a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser DOTTraits DTraits; 67c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 68c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser // Writes the edge labels of the node to O and returns true if there are any 69c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser // edge labels not equal to the empty string "". 70c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser bool getEdgeSourceLabels(raw_ostream &O, NodeType *Node) { 71c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser child_iterator EI = GTraits::child_begin(Node); 72c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser child_iterator EE = GTraits::child_end(Node); 73c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser bool hasEdgeSourceLabels = false; 74c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 75c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { 76a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser std::string label = DTraits.getEdgeSourceLabel(Node, EI); 77c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 78b0cdabb6c2413dff2a8d68b30ff31fd5920c4b37Dan Gohman if (label.empty()) 79c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser continue; 80c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 81c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser hasEdgeSourceLabels = true; 82c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 83c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser if (i) 84c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser O << "|"; 85c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 867ee42e6a28784dcf6a6fa25c776362044eea6a91Dan Gohman O << "<s" << i << ">" << DOT::EscapeString(label); 87c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser } 88c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 89c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser if (EI != EE && hasEdgeSourceLabels) 90c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser O << "|<s64>truncated..."; 91c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 92c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser return hasEdgeSourceLabels; 93c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser } 94c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 958c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerpublic: 9656f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser GraphWriter(raw_ostream &o, const GraphType &g, bool SN) : O(o), G(g) { 97640e74207eb75ebc1f22b3cf1c1c39b32bbf232dDan Gohman DTraits = DOTTraits(SN); 98640e74207eb75ebc1f22b3cf1c1c39b32bbf232dDan Gohman } 99dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 100cce563cf1cdbdcb470a1823f1e917960dde3aad6Dan Gohman void writeGraph(const std::string &Title = "") { 101f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman // Output the header for the graph... 102d73b908f263d538f380e7fbee508d4e9a1a71791Dan Gohman writeHeader(Title); 103f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman 104f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman // Emit all of the nodes in the graph... 105d73b908f263d538f380e7fbee508d4e9a1a71791Dan Gohman writeNodes(); 106f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman 107f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman // Output any customizations on the graph 108d73b908f263d538f380e7fbee508d4e9a1a71791Dan Gohman DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, *this); 109f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman 110f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman // Output the end of the graph 111d73b908f263d538f380e7fbee508d4e9a1a71791Dan Gohman writeFooter(); 112f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman } 113f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman 1144c6809d8e38b9690898700085ebbd913e035c2e2Dan Gohman void writeHeader(const std::string &Title) { 115a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser std::string GraphName = DTraits.getGraphName(G); 116afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman 1174c6809d8e38b9690898700085ebbd913e035c2e2Dan Gohman if (!Title.empty()) 1184c6809d8e38b9690898700085ebbd913e035c2e2Dan Gohman O << "digraph \"" << DOT::EscapeString(Title) << "\" {\n"; 119afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman else if (!GraphName.empty()) 120358f5ac9721f02eec68145bba012322ebc78d58cDan Gohman O << "digraph \"" << DOT::EscapeString(GraphName) << "\" {\n"; 121afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman else 122afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman O << "digraph unnamed {\n"; 12395b923d548ed2e0f0993bb613868c871646f120cChris Lattner 124a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.renderGraphFromBottomUp()) 12589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "\trankdir=\"BT\";\n"; 12689a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 1274c6809d8e38b9690898700085ebbd913e035c2e2Dan Gohman if (!Title.empty()) 1284c6809d8e38b9690898700085ebbd913e035c2e2Dan Gohman O << "\tlabel=\"" << DOT::EscapeString(Title) << "\";\n"; 1292d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman else if (!GraphName.empty()) 1308c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; 131a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser O << DTraits.getGraphProperties(G); 1328c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\n"; 1338c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1348c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 135dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeFooter() { 1368c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Finish off the graph 1378c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "}\n"; 1388c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 13995b923d548ed2e0f0993bb613868c871646f120cChris Lattner 1408c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNodes() { 1418c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Loop over the graph, printing it out... 1428c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); 1438c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner I != E; ++I) 14489938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman if (!isNodeHidden(*I)) 14589938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman writeNode(*I); 14689938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman } 14789938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman 14889938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman bool isNodeHidden(NodeType &Node) { 14989938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman return isNodeHidden(&Node); 15089938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman } 15189938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman 15289938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman bool isNodeHidden(NodeType *const *Node) { 15389938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman return isNodeHidden(*Node); 15489938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman } 15589938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman 15689938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman bool isNodeHidden(NodeType *Node) { 15789938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman return DTraits.isNodeHidden(Node); 15896345186a5fefff5c88195f6f2505232215b258eTed Kremenek } 159fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman 16096345186a5fefff5c88195f6f2505232215b258eTed Kremenek void writeNode(NodeType& Node) { 16196345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(&Node); 1628c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 16363b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 164ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner void writeNode(NodeType *const *Node) { 165ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner writeNode(*Node); 166ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner } 16763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1688c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNode(NodeType *Node) { 169a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser std::string NodeAttributes = DTraits.getNodeAttributes(Node, G); 17063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1717953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman O << "\tNode" << static_cast<const void*>(Node) << " [shape=record,"; 17295b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (!NodeAttributes.empty()) O << NodeAttributes << ","; 17389a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "label=\"{"; 17489a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 175a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (!DTraits.renderGraphFromBottomUp()) { 17656f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); 17763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 178f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 179a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.hasNodeAddressLabel(Node, G)) 18072ea0c9ffaa1700730c8ce36e9b73aef4b914988Galina Kistanova O << "|" << static_cast<const void*>(Node); 181c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick 182c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick std::string NodeDesc = DTraits.getNodeDescription(Node, G); 183c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick if (!NodeDesc.empty()) 184c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick O << "|" << DOT::EscapeString(NodeDesc); 185f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 186f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 187c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser std::string edgeSourceLabels; 188795eb2ae8eacba3d9d9e55353475b94de5d5d94cBenjamin Kramer raw_string_ostream EdgeSourceLabels(edgeSourceLabels); 189c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels, Node); 190c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 191c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser if (hasEdgeSourceLabels) { 192a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (!DTraits.renderGraphFromBottomUp()) O << "|"; 19363b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 194c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser O << "{" << EdgeSourceLabels.str() << "}"; 19563b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 196a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.renderGraphFromBottomUp()) O << "|"; 19795b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 198f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 199a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.renderGraphFromBottomUp()) { 20056f4ef3232850e29c4635d0923910acce8887bd0Tobias Grosser O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); 20163b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 202f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 203a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.hasNodeAddressLabel(Node, G)) 20472ea0c9ffaa1700730c8ce36e9b73aef4b914988Galina Kistanova O << "|" << static_cast<const void*>(Node); 205c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick 206c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick std::string NodeDesc = DTraits.getNodeDescription(Node, G); 207c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick if (!NodeDesc.empty()) 208c6ada8e5f38168f13830e448f2b9e2d8e3eac72bAndrew Trick O << "|" << DOT::EscapeString(NodeDesc); 209f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 210f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 211a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.hasEdgeDestLabels()) { 212358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "|{"; 213358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman 214a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser unsigned i = 0, e = DTraits.numEdgeDestLabels(Node); 215358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman for (; i != e && i != 64; ++i) { 216358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman if (i) O << "|"; 2175b296e307f71bcaf3d31eff4a04ba5d2016eb628Dan Gohman O << "<d" << i << ">" 2185b296e307f71bcaf3d31eff4a04ba5d2016eb628Dan Gohman << DOT::EscapeString(DTraits.getEdgeDestLabel(Node, i)); 219358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman } 220358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman 221358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman if (i != e) 222358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "|<d64>truncated..."; 223358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "}"; 224358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman } 225358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman 226b78ea801cd762ede7586c6e8ae37f8009100289aJim Laskey O << "}\"];\n"; // Finish printing the "node" line 22763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 22895b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Output all of the edges now 229c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser child_iterator EI = GTraits::child_begin(Node); 230c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser child_iterator EE = GTraits::child_end(Node); 2318c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) 23289938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman if (!DTraits.isNodeHidden(*EI)) 23389938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman writeEdge(Node, i, EI); 2346a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner for (; EI != EE; ++EI) 23589938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman if (!DTraits.isNodeHidden(*EI)) 23689938ce0ad6a0c13104495e2a00d3cc745e34068Dan Gohman writeEdge(Node, 64, EI); 2378c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 2388c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 2398c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { 2408c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (NodeType *TargetNode = *EI) { 24196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner int DestPort = -1; 242a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DTraits.edgeTargetsEdgeSource(Node, EI)) { 243a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser child_iterator TargetIt = DTraits.getEdgeTarget(Node, EI); 2448c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 2458c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Figure out which edge this targets... 24634cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng unsigned Offset = 24734cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng (unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt); 2488b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner DestPort = static_cast<int>(Offset); 24995b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 25096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 251b0cdabb6c2413dff2a8d68b30ff31fd5920c4b37Dan Gohman if (DTraits.getEdgeSourceLabel(Node, EI).empty()) 252c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser edgeidx = -1; 253c500566d9fb70472a17f62b4cf1689062c52e095Tobias Grosser 2547953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman emitEdge(static_cast<const void*>(Node), edgeidx, 2557953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman static_cast<const void*>(TargetNode), DestPort, 256a91f86c49a63f7a37c662c3a9553055bff33a84bTobias Grosser DTraits.getEdgeAttributes(Node, EI, G)); 25795b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 25895b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 25996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 26096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitSimpleNode - Outputs a simple (non-record) node 2617be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitSimpleNode(const void *ID, const std::string &Attr, 262dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const std::string &Label, unsigned NumEdgeSources = 0, 263dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const std::vector<std::string> *EdgeSourceLabels = nullptr) { 26496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << ID << "[ "; 26596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attr.empty()) 26696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << Attr << ","; 267137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << " label =\""; 268137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner if (NumEdgeSources) O << "{"; 269137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << DOT::EscapeString(Label); 2707be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (NumEdgeSources) { 2717be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "|{"; 27263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 2737be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner for (unsigned i = 0; i != NumEdgeSources; ++i) { 2747be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (i) O << "|"; 275787b0db33c0aed66e74ec826809f8ff2fa174349Andrew Lenharth O << "<s" << i << ">"; 2765b296e307f71bcaf3d31eff4a04ba5d2016eb628Dan Gohman if (EdgeSourceLabels) O << DOT::EscapeString((*EdgeSourceLabels)[i]); 2777be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 278137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "}}"; 2797be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 280137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "\"];\n"; 28196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 28296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 28396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitEdge - Output an edge from a simple node into the graph... 2847be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitEdge(const void *SrcNodeID, int SrcNodePort, 2857be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const void *DestNodeID, int DestNodePort, 2867be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const std::string &Attrs) { 287d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (SrcNodePort > 64) return; // Eminating from truncated part? 2887a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner if (DestNodePort > 64) DestNodePort = 64; // Targeting the truncated part? 289d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner 29096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << SrcNodeID; 29196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (SrcNodePort >= 0) 292358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << ":s" << SrcNodePort; 2937953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman O << " -> Node" << DestNodeID; 294a10d598602308549d87d2c5d9848f5a72fda2b43Tobias Grosser if (DestNodePort >= 0 && DTraits.hasEdgeDestLabels()) 295ce4edd647bddec0be61df39962f1a697068891f2Tobias Grosser O << ":d" << DestNodePort; 29696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 29796f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attrs.empty()) 29896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "[" << Attrs << "]"; 29996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ";\n"; 30096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 301f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 302f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser /// getOStream - Get the raw output stream into the graph file. Useful to 303f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser /// write fancy things using addCustomGraphFeatures(). 304f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser raw_ostream &getOStream() { 305f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return O; 306f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 3078c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner}; 30895b923d548ed2e0f0993bb613868c871646f120cChris Lattner 3098c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnertemplate<typename GraphType> 310103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattnerraw_ostream &WriteGraph(raw_ostream &O, const GraphType &G, 311103289e9383ad1eb66caf28c9b166aebce963a35Chris Lattner bool ShortNames = false, 31225ad1cc32af8d526eb72893a513a486bc28c5106Benjamin Kramer const Twine &Title = "") { 3138c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Start the graph emission process... 3148cbc94afb71fd2da72d8f1284f7f53e39019fdecOwen Anderson GraphWriter<GraphType> W(O, G, ShortNames); 315dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 316f7e2ca9e161140f658a2ae65ad67e508b703ac8cDan Gohman // Emit the graph. 31725ad1cc32af8d526eb72893a513a486bc28c5106Benjamin Kramer W.writeGraph(Title.str()); 318dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 31995b923d548ed2e0f0993bb613868c871646f120cChris Lattner return O; 32095b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 32195b923d548ed2e0f0993bb613868c871646f120cChris Lattner 322a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindolastd::string createGraphFilename(const Twine &Name, int &FD); 32351c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer 3244d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindolatemplate <typename GraphType> 3254d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindolastd::string WriteGraph(const GraphType &G, const Twine &Name, 3264d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola bool ShortNames = false, const Twine &Title = "") { 327a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola int FD; 328dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Windows can't always handle long paths, so limit the length of the name. 329dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::string N = Name.str(); 330dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines N = N.substr(0, std::min<std::size_t>(N.size(), 140)); 331dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines std::string Filename = createGraphFilename(N, FD); 332a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola raw_fd_ostream O(FD, /*shouldClose=*/ true); 3335860c6c09e58c3f6d19cee4458320c42a5d17298Devang Patel 334a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola if (FD == -1) { 3354d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola errs() << "error opening file '" << Filename << "' for writing!\n"; 3364d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola return ""; 3375860c6c09e58c3f6d19cee4458320c42a5d17298Devang Patel } 338fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman 339a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola llvm::WriteGraph(O, G, ShortNames, Title); 340a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola errs() << " done. \n"; 341a54ba12ae7a8cf826b65d2e4a882258e952c35b1Rafael Espindola 3425860c6c09e58c3f6d19cee4458320c42a5d17298Devang Patel return Filename; 3439d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 344fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman 3459d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, 3469d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// then cleanup. For use from the debugger. 3479d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// 3489d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 34925ad1cc32af8d526eb72893a513a486bc28c5106Benjamin Kramervoid ViewGraph(const GraphType &G, const Twine &Name, 35025ad1cc32af8d526eb72893a513a486bc28c5106Benjamin Kramer bool ShortNames = false, const Twine &Title = "", 35100ad26ff5760ff2d1b24acb18718e63541088923David Greene GraphProgram::Name Program = GraphProgram::DOT) { 3524d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola std::string Filename = llvm::WriteGraph(G, Name, ShortNames, Title); 3539d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3544d39727eaee3e7cb5c72dba469855cb538110782Rafael Espindola if (Filename.empty()) 3559d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return; 356fe2cce63aa26d0916fa7be32c6bf7fa8fb059ee7Misha Brukman 35700ad26ff5760ff2d1b24acb18718e63541088923David Greene DisplayGraph(Filename, true, Program); 3589d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 3599d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 360d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace 361d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 36295b923d548ed2e0f0993bb613868c871646f120cChris Lattner#endif 363