GraphWriter.h revision 7953f3781077b6feaba3708fb96ef917f8e8fc89
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()) 882d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman O << "digraph \"" << DOT::EscapeString(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 972d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman if (!Name.empty()) 982d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman O << "\tlabel=\"" << DOT::EscapeString(Name) << "\";\n"; 992d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman else if (!GraphName.empty()) 1008c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; 1018c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << DOTTraits::getGraphProperties(G); 1028c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\n"; 1038c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1048c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 105dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeFooter() { 1068c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Finish off the graph 1078c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "}\n"; 1088c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 10995b923d548ed2e0f0993bb613868c871646f120cChris Lattner 1108c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNodes() { 1118c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Loop over the graph, printing it out... 1128c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); 1138c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner I != E; ++I) 11496345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(*I); 11596345186a5fefff5c88195f6f2505232215b258eTed Kremenek } 11696345186a5fefff5c88195f6f2505232215b258eTed Kremenek 11796345186a5fefff5c88195f6f2505232215b258eTed Kremenek void writeNode(NodeType& Node) { 11896345186a5fefff5c88195f6f2505232215b258eTed Kremenek writeNode(&Node); 1198c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 12063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 121ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner void writeNode(NodeType *const *Node) { 122ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner writeNode(*Node); 123ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner } 12463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1258c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNode(NodeType *Node) { 126ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey std::string NodeAttributes = DOTTraits::getNodeAttributes(Node, G); 12763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1287953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman O << "\tNode" << static_cast<const void*>(Node) << " [shape=record,"; 12995b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (!NodeAttributes.empty()) O << NodeAttributes << ","; 13089a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "label=\"{"; 13189a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 132f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (!DOTTraits::renderGraphFromBottomUp()) { 13389a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 13463b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 135f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 136f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 137f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 138f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 139f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 14095b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Print out the fields of the current node... 1418c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EI = GTraits::child_begin(Node); 1428c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EE = GTraits::child_end(Node); 14395b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) { 14489a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (!DOTTraits::renderGraphFromBottomUp()) O << "|"; 14589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "{"; 14663b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 14795b923d548ed2e0f0993bb613868c871646f120cChris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { 14895b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (i) O << "|"; 149358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "<s" << i << ">" << DOTTraits::getEdgeSourceLabel(Node, EI); 15095b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 15163b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 15295b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) 153358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "|<s64>truncated..."; 15495b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "}"; 15589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) O << "|"; 15695b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 157f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 158f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::renderGraphFromBottomUp()) { 15989a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 16063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 161f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 162f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 163f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 164f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 165f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 166358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman if (DOTTraits::hasEdgeDestLabels()) { 167358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "|{"; 168358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman 169358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman unsigned i = 0, e = DOTTraits::numEdgeDestLabels(Node); 170358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman for (; i != e && i != 64; ++i) { 171358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman if (i) O << "|"; 172358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "<d" << i << ">" << DOTTraits::getEdgeDestLabel(Node, i); 173358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman } 174358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman 175358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman if (i != e) 176358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "|<d64>truncated..."; 177358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << "}"; 178358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman } 179358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman 180b78ea801cd762ede7586c6e8ae37f8009100289aJim Laskey O << "}\"];\n"; // Finish printing the "node" line 18163b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 18295b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Output all of the edges now 18395b923d548ed2e0f0993bb613868c871646f120cChris Lattner EI = GTraits::child_begin(Node); 1848c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) 1858c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner writeEdge(Node, i, EI); 1866a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner for (; EI != EE; ++EI) 1876a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner writeEdge(Node, 64, EI); 1888c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1898c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1908c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { 1918c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (NodeType *TargetNode = *EI) { 19296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner int DestPort = -1; 1938c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (DOTTraits::edgeTargetsEdgeSource(Node, EI)) { 1948c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator TargetIt = DOTTraits::getEdgeTarget(Node, EI); 1958c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1968c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Figure out which edge this targets... 19734cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng unsigned Offset = 19834cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng (unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt); 1998b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner DestPort = static_cast<int>(Offset); 20095b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 20196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 2027953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman emitEdge(static_cast<const void*>(Node), edgeidx, 2037953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman static_cast<const void*>(TargetNode), DestPort, 20496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner DOTTraits::getEdgeAttributes(Node, EI)); 20595b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 20695b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 20796f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 20896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitSimpleNode - Outputs a simple (non-record) node 2097be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitSimpleNode(const void *ID, const std::string &Attr, 210a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::string &Label, unsigned NumEdgeSources = 0, 211a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::vector<std::string> *EdgeSourceLabels = 0) { 21296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << ID << "[ "; 21396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attr.empty()) 21496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << Attr << ","; 215137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << " label =\""; 216137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner if (NumEdgeSources) O << "{"; 217137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << DOT::EscapeString(Label); 2187be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (NumEdgeSources) { 2197be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "|{"; 22063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 2217be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner for (unsigned i = 0; i != NumEdgeSources; ++i) { 2227be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (i) O << "|"; 2237be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "<g" << i << ">"; 224a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner if (EdgeSourceLabels) O << (*EdgeSourceLabels)[i]; 2257be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 226137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "}}"; 2277be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 228137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "\"];\n"; 22996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 23096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 23196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitEdge - Output an edge from a simple node into the graph... 2327be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitEdge(const void *SrcNodeID, int SrcNodePort, 2337be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const void *DestNodeID, int DestNodePort, 2347be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const std::string &Attrs) { 235d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (SrcNodePort > 64) return; // Eminating from truncated part? 236d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? 237d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner 23896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << SrcNodeID; 23996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (SrcNodePort >= 0) 240358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << ":s" << SrcNodePort; 2417953f3781077b6feaba3708fb96ef917f8e8fc89Dan Gohman O << " -> Node" << DestNodeID; 24296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (DestNodePort >= 0) 243358033102ffaef4d1afb1c0b7e96440906f0b48fDan Gohman O << ":d" << DestNodePort; 24496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 24596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attrs.empty()) 24696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "[" << Attrs << "]"; 24796f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ";\n"; 24896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 2498c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner}; 25095b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2518c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnertemplate<typename GraphType> 2528c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerstd::ostream &WriteGraph(std::ostream &O, const GraphType &G, 2532d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman const std::string &Name = "", 2542d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman const std::string &Title = "") { 2558c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Start the graph emission process... 256dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner GraphWriter<GraphType> W(O, G); 257dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 258dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the header for the graph... 2592d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman W.writeHeader(Title); 260dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 261dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Emit all of the nodes in the graph... 262dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeNodes(); 263dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 264dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output any customizations on the graph 265dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 266dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 267dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the end of the graph 268dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeFooter(); 26995b923d548ed2e0f0993bb613868c871646f120cChris Lattner return O; 27095b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 27195b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2729d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 2739d5b532de9bdca37810a59a93a69128441b02c55Reid Spencersys::Path WriteGraph(const GraphType &G, 2749d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 2759d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 276487447626c273962744820a370d93ddef961c3f2Reid Spencer std::string ErrMsg; 277487447626c273962744820a370d93ddef961c3f2Reid Spencer sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); 278487447626c273962744820a370d93ddef961c3f2Reid Spencer if (Filename.isEmpty()) { 279e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Error: " << ErrMsg << "\n"; 280487447626c273962744820a370d93ddef961c3f2Reid Spencer return Filename; 281487447626c273962744820a370d93ddef961c3f2Reid Spencer } 2829d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.appendComponent(Name + ".dot"); 28351c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer if (Filename.makeUnique(true,&ErrMsg)) { 284e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Error: " << ErrMsg << "\n"; 28551c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer return sys::Path(); 28651c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer } 28751c5a286bae5ad27ddc49602f44b7ea7253a4cc9Reid Spencer 288e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "Writing '" << Filename << "'... "; 2899d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2909d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::ofstream O(Filename.c_str()); 2919d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2929d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (O.good()) { 2932d3ff5a7aee24024765629d17ebff351ea11c9bbDan Gohman WriteGraph(O, G, Name, Title); 294e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << " done. \n"; 2959d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2969d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer O.close(); 2979d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } else { 298e81561909d128c6e2d8033cb5465a49b2596b26aBill Wendling cerr << "error opening file for writing!\n"; 2999d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.clear(); 3009d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 3019d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3029d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return Filename; 3039d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 3049d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3059d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, 3069d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// then cleanup. For use from the debugger. 3079d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// 3089d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 3099d5b532de9bdca37810a59a93a69128441b02c55Reid Spencervoid ViewGraph(const GraphType& G, 3109d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 3119d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 3129d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path Filename = WriteGraph(G, Name, Title); 3139d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3149d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (Filename.isEmpty()) { 3159d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return; 3169d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 3179d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 3189d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DisplayGraph(Filename); 3199d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 3209d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 321d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace 322d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 32395b923d548ed2e0f0993bb613868c871646f120cChris Lattner#endif 324