GraphWriter.h revision 358f5ac9721f02eec68145bba012322ebc78d58c
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/Support/DOTGraphTraits.h" 27e4706a0b51cbb6ba74844dd70a51a5fea0d2c336Dan Gohman#include "llvm/Support/Streams.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) { 85afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman std::string GraphName = DOTTraits::getGraphName(G); 86afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman 87afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman if (!Name.empty()) 888c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "digraph " << Name << " {\n"; 89afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman else if (!GraphName.empty()) 90358f5ac9721f02eec68145bba012322ebc78d58cDan Gohman O << "digraph \"" << DOT::EscapeString(GraphName) << "\" {\n"; 91afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman else 92afbd0737e7593f1b79ed5060e506749558e82ab9Dan Gohman O << "digraph unnamed {\n"; 9395b923d548ed2e0f0993bb613868c871646f120cChris Lattner 9489a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) 9589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "\trankdir=\"BT\";\n"; 9689a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 978c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (!GraphName.empty()) 988c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; 998c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << DOTTraits::getGraphProperties(G); 1008c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\n"; 1018c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1028c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 103dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeFooter() { 1048c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Finish off the graph 1058c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "}\n"; 1068c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 10795b923d548ed2e0f0993bb613868c871646f120cChris Lattner 1088c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNodes() { 1098c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Loop over the graph, printing it out... 1108c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); 1118c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner I != E; ++I) 11296345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(*I); 11396345186a5fefff5c88195f6f2505232215b258eTed Kremenek } 11496345186a5fefff5c88195f6f2505232215b258eTed Kremenek 11596345186a5fefff5c88195f6f2505232215b258eTed Kremenek void writeNode(NodeType& Node) { 11696345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(&Node); 1178c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 11863b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 119ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner void writeNode(NodeType *const *Node) { 120ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner writeNode(*Node); 121ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner } 12263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1238c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNode(NodeType *Node) { 124ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey std::string NodeAttributes = DOTTraits::getNodeAttributes(Node, G); 12563b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1268b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner O << "\tNode" << reinterpret_cast<const void*>(Node) << " [shape=record,"; 12795b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (!NodeAttributes.empty()) O << NodeAttributes << ","; 12889a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "label=\"{"; 12989a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 130f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (!DOTTraits::renderGraphFromBottomUp()) { 13189a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 13263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 133f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 134f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 135f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 136f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 137f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 13895b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Print out the fields of the current node... 1398c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EI = GTraits::child_begin(Node); 1408c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EE = GTraits::child_end(Node); 14195b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) { 14289a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (!DOTTraits::renderGraphFromBottomUp()) O << "|"; 14389a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "{"; 14463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 14595b923d548ed2e0f0993bb613868c871646f120cChris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { 14695b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (i) O << "|"; 14795b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "<g" << i << ">" << DOTTraits::getEdgeSourceLabel(Node, EI); 14895b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 14963b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 15095b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) 1516a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner O << "|<g64>truncated..."; 15295b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "}"; 15389a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) O << "|"; 15495b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 155f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 156f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::renderGraphFromBottomUp()) { 15789a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 15863b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 159f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 160f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 161f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 162f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 163f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 164b78ea801cd762ede7586c6e8ae37f8009100289aJim Laskey O << "}\"];\n"; // Finish printing the "node" line 16563b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 16695b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Output all of the edges now 16795b923d548ed2e0f0993bb613868c871646f120cChris Lattner EI = GTraits::child_begin(Node); 1688c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) 1698c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner writeEdge(Node, i, EI); 1706a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner for (; EI != EE; ++EI) 1716a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner writeEdge(Node, 64, EI); 1728c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1738c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1748c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { 1758c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (NodeType *TargetNode = *EI) { 17696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner int DestPort = -1; 1778c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (DOTTraits::edgeTargetsEdgeSource(Node, EI)) { 1788c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator TargetIt = DOTTraits::getEdgeTarget(Node, EI); 1798c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1808c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Figure out which edge this targets... 18134cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng unsigned Offset = 18234cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng (unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt); 1838b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner DestPort = static_cast<int>(Offset); 18495b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 18596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 1868b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner emitEdge(reinterpret_cast<const void*>(Node), edgeidx, 1878b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner reinterpret_cast<const void*>(TargetNode), DestPort, 18896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner DOTTraits::getEdgeAttributes(Node, EI)); 18995b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 19095b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 19196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 19296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitSimpleNode - Outputs a simple (non-record) node 1937be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitSimpleNode(const void *ID, const std::string &Attr, 194a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::string &Label, unsigned NumEdgeSources = 0, 195a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::vector<std::string> *EdgeSourceLabels = 0) { 19696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << ID << "[ "; 19796f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attr.empty()) 19896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << Attr << ","; 199137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << " label =\""; 200137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner if (NumEdgeSources) O << "{"; 201137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << DOT::EscapeString(Label); 2027be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (NumEdgeSources) { 2037be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "|{"; 20463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 2057be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner for (unsigned i = 0; i != NumEdgeSources; ++i) { 2067be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (i) O << "|"; 2077be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "<g" << i << ">"; 208a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner if (EdgeSourceLabels) O << (*EdgeSourceLabels)[i]; 2097be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 210137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "}}"; 2117be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 212137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "\"];\n"; 21396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 21496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 21596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitEdge - Output an edge from a simple node into the graph... 2167be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitEdge(const void *SrcNodeID, int SrcNodePort, 2177be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const void *DestNodeID, int DestNodePort, 2187be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const std::string &Attrs) { 219d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (SrcNodePort > 64) return; // Eminating from truncated part? 220d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? 221d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner 22296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << SrcNodeID; 22396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (SrcNodePort >= 0) 22496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ":g" << SrcNodePort; 2258b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner O << " -> Node" << reinterpret_cast<const void*>(DestNodeID); 22696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (DestNodePort >= 0) 22763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman O << ":g" << DestNodePort; 22896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 22996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attrs.empty()) 23096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "[" << Attrs << "]"; 23196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ";\n"; 23296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 2338c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner}; 23495b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2358c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnertemplate<typename GraphType> 2368c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerstd::ostream &WriteGraph(std::ostream &O, const GraphType &G, 2378c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner const std::string &Name = "") { 2388c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Start the graph emission process... 239dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner GraphWriter<GraphType> W(O, G); 240dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 241dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the header for the graph... 242dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeHeader(Name); 243dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 244dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Emit all of the nodes in the graph... 245dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeNodes(); 246dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 247dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output any customizations on the graph 248dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 249dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 250dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the end of the graph 251dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeFooter(); 25295b923d548ed2e0f0993bb613868c871646f120cChris Lattner return O; 25395b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 25495b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2559d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 2569d5b532de9bdca37810a59a93a69128441b02c55Reid Spencersys::Path WriteGraph(const GraphType &G, 2579d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 2589d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 259487447626c273962744820a370d93ddef961c3f2Reid Spencer std::string ErrMsg; 260487447626c273962744820a370d93ddef961c3f2Reid Spencer sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); 261487447626c273962744820a370d93ddef961c3f2Reid Spencer if (Filename.isEmpty()) { 262e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Error: " << ErrMsg << "\n"; 263487447626c273962744820a370d93ddef961c3f2Reid Spencer return Filename; 264487447626c273962744820a370d93ddef961c3f2Reid Spencer } 2659d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.appendComponent(Name + ".dot"); 26651c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer if (Filename.makeUnique(true,&ErrMsg)) { 267e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Error: " << ErrMsg << "\n"; 26851c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer return sys::Path(); 26951c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer } 27051c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer 271e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Writing '" << Filename << "'... "; 2729d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2739d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::ofstream O(Filename.c_str()); 2749d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2759d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (O.good()) { 2769d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Start the graph emission process... 2779d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer GraphWriter<GraphType> W(O, G); 2789d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2799d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output the header for the graph... 2809d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeHeader(Title); 2819d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2829d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Emit all of the nodes in the graph... 2839d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeNodes(); 2849d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2859d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output any customizations on the graph 2869d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 2879d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2889d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output the end of the graph 2899d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeFooter(); 290e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << " done. \n"; 2919d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2929d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer O.close(); 2939d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2949d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } else { 295e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "error opening file for writing!\n"; 2969d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.clear(); 2979d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 2989d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2999d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return Filename; 3009d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 3019d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3029d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, 3039d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// then cleanup. For use from the debugger. 3049d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// 3059d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 3069d5b532de9bdca37810a59a93a69128441b02c55Reid Spencervoid ViewGraph(const GraphType& G, 3079d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 3089d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 3099d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path Filename = WriteGraph(G, Name, Title); 3109d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3119d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (Filename.isEmpty()) { 3129d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return; 3139d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 3149d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3159d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DisplayGraph(Filename); 3169d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 3179d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 318d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace 319d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 32095b923d548ed2e0f0993bb613868c871646f120cChris Lattner#endif 321