GraphWriter.h revision 34cd4a484e532cc463fd5a4bf59b88d13c5467c1
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 2652883e7a9a637c0d6dea091917090a8ac63e7736Bill Wendling#include "llvm/Support/Debug.h" 27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/DOTGraphTraits.h" 28551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/GraphTraits.h" 299d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#include "llvm/System/Path.h" 309d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#include <fstream> 3152883e7a9a637c0d6dea091917090a8ac63e7736Bill Wendling#include <vector> 3295b923d548ed2e0f0993bb613868c871646f120cChris Lattner 33d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekenamespace llvm { 34d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 3595b923d548ed2e0f0993bb613868c871646f120cChris Lattnernamespace DOT { // Private functions... 3695b923d548ed2e0f0993bb613868c871646f120cChris Lattner inline std::string EscapeString(const std::string &Label) { 3795b923d548ed2e0f0993bb613868c871646f120cChris Lattner std::string Str(Label); 3895b923d548ed2e0f0993bb613868c871646f120cChris Lattner for (unsigned i = 0; i != Str.length(); ++i) 3995b923d548ed2e0f0993bb613868c871646f120cChris Lattner switch (Str[i]) { 4095b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '\n': 4195b923d548ed2e0f0993bb613868c871646f120cChris Lattner Str.insert(Str.begin()+i, '\\'); // Escape character... 4295b923d548ed2e0f0993bb613868c871646f120cChris Lattner ++i; 4395b923d548ed2e0f0993bb613868c871646f120cChris Lattner Str[i] = 'n'; 4495b923d548ed2e0f0993bb613868c871646f120cChris Lattner break; 4595b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '\t': 4695b923d548ed2e0f0993bb613868c871646f120cChris Lattner Str.insert(Str.begin()+i, ' '); // Convert to two spaces 4795b923d548ed2e0f0993bb613868c871646f120cChris Lattner ++i; 4895b923d548ed2e0f0993bb613868c871646f120cChris Lattner Str[i] = ' '; 4995b923d548ed2e0f0993bb613868c871646f120cChris Lattner break; 5095b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '\\': 51f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek if (i+1 != Str.length()) 52f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek switch (Str[i+1]) { 53f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek case 'l': continue; // don't disturb \l 54f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek case '|': case '{': case '}': 55f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek Str.erase(Str.begin()+i); continue; 56f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek default: break; 57f02e26abc04c95be6be02b614ea68616ed5c0927Ted Kremenek } 5895b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '{': case '}': 5995b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '<': case '>': 601a0190f4f0deafddc107c45784ebc543666e909aTed Kremenek case '|': case '"': 6195b923d548ed2e0f0993bb613868c871646f120cChris Lattner Str.insert(Str.begin()+i, '\\'); // Escape character... 6295b923d548ed2e0f0993bb613868c871646f120cChris Lattner ++i; // don't infinite loop 6395b923d548ed2e0f0993bb613868c871646f120cChris Lattner break; 6495b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 6595b923d548ed2e0f0993bb613868c871646f120cChris Lattner return Str; 6695b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 6795b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 6895b923d548ed2e0f0993bb613868c871646f120cChris Lattner 699d5b532de9bdca37810a59a93a69128441b02c55Reid Spencervoid DisplayGraph(const sys::Path& Filename); 709d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 7195b923d548ed2e0f0993bb613868c871646f120cChris Lattnertemplate<typename GraphType> 728c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerclass GraphWriter { 738c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner std::ostream &O; 748c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner const GraphType &G; 7595b923d548ed2e0f0993bb613868c871646f120cChris Lattner 768c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef DOTGraphTraits<GraphType> DOTTraits; 778c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef GraphTraits<GraphType> GTraits; 788c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::NodeType NodeType; 798c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::nodes_iterator node_iterator; 808c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::ChildIteratorType child_iterator; 818c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerpublic: 82dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner GraphWriter(std::ostream &o, const GraphType &g) : O(o), G(g) {} 83dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 84dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeHeader(const std::string &Name) { 858c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (Name.empty()) 868c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "digraph foo {\n"; // Graph name doesn't matter 878c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner else 888c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "digraph " << Name << " {\n"; 8995b923d548ed2e0f0993bb613868c871646f120cChris Lattner 9089a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) 9189a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "\trankdir=\"BT\";\n"; 9289a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 938c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner std::string GraphName = DOTTraits::getGraphName(G); 948c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (!GraphName.empty()) 958c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; 968c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << DOTTraits::getGraphProperties(G); 978c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\n"; 988c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 998c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 100dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeFooter() { 1018c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Finish off the graph 1028c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "}\n"; 1038c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 10495b923d548ed2e0f0993bb613868c871646f120cChris Lattner 1058c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNodes() { 1068c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Loop over the graph, printing it out... 1078c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); 1088c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner I != E; ++I) 10996345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(*I); 11096345186a5fefff5c88195f6f2505232215b258eTed Kremenek } 11196345186a5fefff5c88195f6f2505232215b258eTed Kremenek 11296345186a5fefff5c88195f6f2505232215b258eTed Kremenek void writeNode(NodeType& Node) { 11396345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(&Node); 1148c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 11563b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 116ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner void writeNode(NodeType *const *Node) { 117ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner writeNode(*Node); 118ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner } 11963b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1208c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNode(NodeType *Node) { 121ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey std::string NodeAttributes = DOTTraits::getNodeAttributes(Node, G); 12263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1238b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner O << "\tNode" << reinterpret_cast<const void*>(Node) << " [shape=record,"; 12495b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (!NodeAttributes.empty()) O << NodeAttributes << ","; 12589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "label=\"{"; 12689a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 127f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (!DOTTraits::renderGraphFromBottomUp()) { 12889a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 12963b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 130f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 131f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 132f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 133f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 134f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 13595b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Print out the fields of the current node... 1368c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EI = GTraits::child_begin(Node); 1378c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EE = GTraits::child_end(Node); 13895b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) { 13989a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (!DOTTraits::renderGraphFromBottomUp()) O << "|"; 14089a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "{"; 14163b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 14295b923d548ed2e0f0993bb613868c871646f120cChris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { 14395b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (i) O << "|"; 14495b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "<g" << i << ">" << DOTTraits::getEdgeSourceLabel(Node, EI); 14595b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 14663b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 14795b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) 1486a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner O << "|<g64>truncated..."; 14995b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "}"; 15089a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) O << "|"; 15195b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 152f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 153f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::renderGraphFromBottomUp()) { 15489a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 15563b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 156f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 157f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 158f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 159f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 160f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 161b78ea801cd762ede7586c6e8ae37f8009100289aJim Laskey O << "}\"];\n"; // Finish printing the "node" line 16263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 16395b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Output all of the edges now 16495b923d548ed2e0f0993bb613868c871646f120cChris Lattner EI = GTraits::child_begin(Node); 1658c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) 1668c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner writeEdge(Node, i, EI); 1676a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner for (; EI != EE; ++EI) 1686a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner writeEdge(Node, 64, EI); 1698c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1708c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1718c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { 1728c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (NodeType *TargetNode = *EI) { 17396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner int DestPort = -1; 1748c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (DOTTraits::edgeTargetsEdgeSource(Node, EI)) { 1758c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator TargetIt = DOTTraits::getEdgeTarget(Node, EI); 1768c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1778c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Figure out which edge this targets... 17834cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng unsigned Offset = 17934cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng (unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt); 1808b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner DestPort = static_cast<int>(Offset); 18195b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 18296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 1838b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner emitEdge(reinterpret_cast<const void*>(Node), edgeidx, 1848b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner reinterpret_cast<const void*>(TargetNode), DestPort, 18596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner DOTTraits::getEdgeAttributes(Node, EI)); 18695b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 18795b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 18896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 18996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitSimpleNode - Outputs a simple (non-record) node 1907be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitSimpleNode(const void *ID, const std::string &Attr, 191a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::string &Label, unsigned NumEdgeSources = 0, 192a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::vector<std::string> *EdgeSourceLabels = 0) { 19396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << ID << "[ "; 19496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attr.empty()) 19596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << Attr << ","; 196137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << " label =\""; 197137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner if (NumEdgeSources) O << "{"; 198137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << DOT::EscapeString(Label); 1997be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (NumEdgeSources) { 2007be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "|{"; 20163b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 2027be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner for (unsigned i = 0; i != NumEdgeSources; ++i) { 2037be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (i) O << "|"; 2047be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "<g" << i << ">"; 205a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner if (EdgeSourceLabels) O << (*EdgeSourceLabels)[i]; 2067be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 207137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "}}"; 2087be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 209137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "\"];\n"; 21096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 21196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 21296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitEdge - Output an edge from a simple node into the graph... 2137be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitEdge(const void *SrcNodeID, int SrcNodePort, 2147be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const void *DestNodeID, int DestNodePort, 2157be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const std::string &Attrs) { 216d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (SrcNodePort > 64) return; // Eminating from truncated part? 217d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? 218d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner 21996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << SrcNodeID; 22096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (SrcNodePort >= 0) 22196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ":g" << SrcNodePort; 2228b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner O << " -> Node" << reinterpret_cast<const void*>(DestNodeID); 22396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (DestNodePort >= 0) 22463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman O << ":g" << DestNodePort; 22596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 22696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attrs.empty()) 22796f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "[" << Attrs << "]"; 22896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ";\n"; 22996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 2308c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner}; 23195b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2328c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnertemplate<typename GraphType> 2338c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerstd::ostream &WriteGraph(std::ostream &O, const GraphType &G, 2348c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner const std::string &Name = "") { 2358c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Start the graph emission process... 236dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner GraphWriter<GraphType> W(O, G); 237dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 238dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the header for the graph... 239dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeHeader(Name); 240dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 241dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Emit all of the nodes in the graph... 242dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeNodes(); 243dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 244dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output any customizations on the graph 245dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 246dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 247dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the end of the graph 248dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeFooter(); 24995b923d548ed2e0f0993bb613868c871646f120cChris Lattner return O; 25095b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 25195b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2529d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 2539d5b532de9bdca37810a59a93a69128441b02c55Reid Spencersys::Path WriteGraph(const GraphType &G, 2549d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 2559d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 256487447626c273962744820a370d93ddef961c3f2Reid Spencer std::string ErrMsg; 257487447626c273962744820a370d93ddef961c3f2Reid Spencer sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); 258487447626c273962744820a370d93ddef961c3f2Reid Spencer if (Filename.isEmpty()) { 259e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Error: " << ErrMsg << "\n"; 260487447626c273962744820a370d93ddef961c3f2Reid Spencer return Filename; 261487447626c273962744820a370d93ddef961c3f2Reid Spencer } 2629d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.appendComponent(Name + ".dot"); 26351c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer if (Filename.makeUnique(true,&ErrMsg)) { 264e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Error: " << ErrMsg << "\n"; 26551c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer return sys::Path(); 26651c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer } 26751c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer 268e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Writing '" << Filename << "'... "; 2699d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2709d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::ofstream O(Filename.c_str()); 2719d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2729d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (O.good()) { 2739d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Start the graph emission process... 2749d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer GraphWriter<GraphType> W(O, G); 2759d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2769d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output the header for the graph... 2779d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeHeader(Title); 2789d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2799d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Emit all of the nodes in the graph... 2809d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeNodes(); 2819d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2829d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output any customizations on the graph 2839d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 2849d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2859d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output the end of the graph 2869d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeFooter(); 287e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << " done. \n"; 2889d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2899d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer O.close(); 2909d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2919d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } else { 292e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "error opening file for writing!\n"; 2939d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.clear(); 2949d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 2959d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2969d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return Filename; 2979d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 2989d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2999d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, 3009d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// then cleanup. For use from the debugger. 3019d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// 3029d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 3039d5b532de9bdca37810a59a93a69128441b02c55Reid Spencervoid ViewGraph(const GraphType& G, 3049d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 3059d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 3069d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path Filename = WriteGraph(G, Name, Title); 3079d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3089d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (Filename.isEmpty()) { 3099d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return; 3109d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 3119d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3129d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DisplayGraph(Filename); 3139d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 3149d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 315d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace 316d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 31795b923d548ed2e0f0993bb613868c871646f120cChris Lattner#endif 318