GraphWriter.h revision 9d5b532de9bdca37810a59a93a69128441b02c55
1551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer//===-- llvm/Support/GraphWriter.h - Write graph to a .dot file -*- C++ -*-===// 263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman// 3b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// The LLVM Compiler Infrastructure 4b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// 5b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// This file was developed by the LLVM research group and is distributed under 6b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// the University of Illinois Open Source 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" 27551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/ADT/GraphTraits.h" 289d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#include "llvm/System/Path.h" 29a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner#include <vector> 30ab77194e2a895bd2862f3a23bcd9d31efb553a54Chris Lattner#include <iostream> 319d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer#include <fstream> 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 '\\': 5195b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (i+1 != Str.length() && Str[i+1] == 'l') 5295b923d548ed2e0f0993bb613868c871646f120cChris Lattner break; // don't disturb \l 5395b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '{': case '}': 5495b923d548ed2e0f0993bb613868c871646f120cChris Lattner case '<': case '>': 551926f69c53e4581ad10ba2e12eb2bbd21e4c06efChris Lattner case '"': 5695b923d548ed2e0f0993bb613868c871646f120cChris Lattner Str.insert(Str.begin()+i, '\\'); // Escape character... 5795b923d548ed2e0f0993bb613868c871646f120cChris Lattner ++i; // don't infinite loop 5895b923d548ed2e0f0993bb613868c871646f120cChris Lattner break; 5995b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 6095b923d548ed2e0f0993bb613868c871646f120cChris Lattner return Str; 6195b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 6295b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 6395b923d548ed2e0f0993bb613868c871646f120cChris Lattner 649d5b532de9bdca37810a59a93a69128441b02c55Reid Spencervoid DisplayGraph(const sys::Path& Filename); 659d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 6695b923d548ed2e0f0993bb613868c871646f120cChris Lattnertemplate<typename GraphType> 678c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerclass GraphWriter { 688c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner std::ostream &O; 698c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner const GraphType &G; 7095b923d548ed2e0f0993bb613868c871646f120cChris Lattner 718c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef DOTGraphTraits<GraphType> DOTTraits; 728c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef GraphTraits<GraphType> GTraits; 738c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::NodeType NodeType; 748c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::nodes_iterator node_iterator; 758c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner typedef typename GTraits::ChildIteratorType child_iterator; 768c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerpublic: 77dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner GraphWriter(std::ostream &o, const GraphType &g) : O(o), G(g) {} 78dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 79dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeHeader(const std::string &Name) { 808c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (Name.empty()) 818c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "digraph foo {\n"; // Graph name doesn't matter 828c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner else 838c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "digraph " << Name << " {\n"; 8495b923d548ed2e0f0993bb613868c871646f120cChris Lattner 8589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) 8689a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "\trankdir=\"BT\";\n"; 8789a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 888c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner std::string GraphName = DOTTraits::getGraphName(G); 898c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (!GraphName.empty()) 908c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; 918c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << DOTTraits::getGraphProperties(G); 928c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "\n"; 938c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 948c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 95dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner void writeFooter() { 968c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Finish off the graph 978c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner O << "}\n"; 988c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 9995b923d548ed2e0f0993bb613868c871646f120cChris Lattner 1008c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNodes() { 1018c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Loop over the graph, printing it out... 1028c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); 1038c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner I != E; ++I) 1048c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner writeNode(&*I); 1058c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 10663b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 107ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner void writeNode(NodeType *const *Node) { 108ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner writeNode(*Node); 109ce393a609ba1df701cfba9e96749275a16e22adeChris Lattner } 11063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1118c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeNode(NodeType *Node) { 1128c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner std::string NodeAttributes = DOTTraits::getNodeAttributes(Node); 11363b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1148b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner O << "\tNode" << reinterpret_cast<const void*>(Node) << " [shape=record,"; 11595b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (!NodeAttributes.empty()) O << NodeAttributes << ","; 11689a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "label=\"{"; 11789a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner 118f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (!DOTTraits::renderGraphFromBottomUp()) { 11989a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 12063b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 121f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 122f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 123f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 124f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 125f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 12695b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Print out the fields of the current node... 1278c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EI = GTraits::child_begin(Node); 1288c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator EE = GTraits::child_end(Node); 12995b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) { 13089a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (!DOTTraits::renderGraphFromBottomUp()) O << "|"; 13189a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << "{"; 13263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 13395b923d548ed2e0f0993bb613868c871646f120cChris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { 13495b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (i) O << "|"; 13595b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "<g" << i << ">" << DOTTraits::getEdgeSourceLabel(Node, EI); 13695b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 13763b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 13895b923d548ed2e0f0993bb613868c871646f120cChris Lattner if (EI != EE) 1396a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner O << "|<g64>truncated..."; 14095b923d548ed2e0f0993bb613868c871646f120cChris Lattner O << "}"; 14189a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner if (DOTTraits::renderGraphFromBottomUp()) O << "|"; 14295b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 143f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 144f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::renderGraphFromBottomUp()) { 14589a1ed58399045d2b2c7b246571945b068f2e5e1Chris Lattner O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); 14663b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 147f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner // If we should include the address of the node in the label, do so now. 148f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner if (DOTTraits::hasNodeAddressLabel(Node, G)) 149f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner O << "|" << (void*)Node; 150f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner } 151f85a55b09657094a1e3954728c7f4ca5bdb6f56aChris Lattner 152b78ea801cd762ede7586c6e8ae37f8009100289aJim Laskey O << "}\"];\n"; // Finish printing the "node" line 15363b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 15495b923d548ed2e0f0993bb613868c871646f120cChris Lattner // Output all of the edges now 15595b923d548ed2e0f0993bb613868c871646f120cChris Lattner EI = GTraits::child_begin(Node); 1568c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) 1578c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner writeEdge(Node, i, EI); 1586a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner for (; EI != EE; ++EI) 1596a6dd6f487bfda1fe8fbb4ab7cb0a9fa1fbadbcfChris Lattner writeEdge(Node, 64, EI); 1608c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner } 1618c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1628c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { 1638c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (NodeType *TargetNode = *EI) { 16496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner int DestPort = -1; 1658c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner if (DOTTraits::edgeTargetsEdgeSource(Node, EI)) { 1668c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner child_iterator TargetIt = DOTTraits::getEdgeTarget(Node, EI); 1678c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner 1688c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Figure out which edge this targets... 1698c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner unsigned Offset = std::distance(GTraits::child_begin(TargetNode), 1708c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner TargetIt); 1718b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner DestPort = static_cast<int>(Offset); 17295b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 17396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 1748b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner emitEdge(reinterpret_cast<const void*>(Node), edgeidx, 1758b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner reinterpret_cast<const void*>(TargetNode), DestPort, 17696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner DOTTraits::getEdgeAttributes(Node, EI)); 17795b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 17895b923d548ed2e0f0993bb613868c871646f120cChris Lattner } 17996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 18096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitSimpleNode - Outputs a simple (non-record) node 1817be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitSimpleNode(const void *ID, const std::string &Attr, 182a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::string &Label, unsigned NumEdgeSources = 0, 183a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner const std::vector<std::string> *EdgeSourceLabels = 0) { 18496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << ID << "[ "; 18596f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attr.empty()) 18696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << Attr << ","; 187137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << " label =\""; 188137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner if (NumEdgeSources) O << "{"; 189137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << DOT::EscapeString(Label); 1907be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (NumEdgeSources) { 1917be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "|{"; 19263b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman 1937be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner for (unsigned i = 0; i != NumEdgeSources; ++i) { 1947be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner if (i) O << "|"; 1957be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner O << "<g" << i << ">"; 196a329733f471a51d64dadbc4ac400c7e54d94358bChris Lattner if (EdgeSourceLabels) O << (*EdgeSourceLabels)[i]; 1977be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 198137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "}}"; 1997be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner } 200137d399faea745a9b75315fd1d5c4c1855fd6f4fChris Lattner O << "\"];\n"; 20196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 20296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 20396f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner /// emitEdge - Output an edge from a simple node into the graph... 2047be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner void emitEdge(const void *SrcNodeID, int SrcNodePort, 2057be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const void *DestNodeID, int DestNodePort, 2067be17dd23364e7f3bd63f5e765c9381bdb544cd5Chris Lattner const std::string &Attrs) { 207d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (SrcNodePort > 64) return; // Eminating from truncated part? 208d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? 209d8d97ce857121b31ce2508f48cb3d2e46f72ec4bChris Lattner 21096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "\tNode" << SrcNodeID; 21196f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (SrcNodePort >= 0) 21296f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ":g" << SrcNodePort; 2138b70b78ba489b090d9866e6a4084ab1e8613b527Chris Lattner O << " -> Node" << reinterpret_cast<const void*>(DestNodeID); 21496f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (DestNodePort >= 0) 21563b3afa98460ce38a1c48d3c44ef6edfdaf37b77Misha Brukman O << ":g" << DestNodePort; 21696f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner 21796f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner if (!Attrs.empty()) 21896f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << "[" << Attrs << "]"; 21996f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner O << ";\n"; 22096f549310013eaf751ff401b5ad3cbe01542e9b1Chris Lattner } 2218c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner}; 22295b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2238c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnertemplate<typename GraphType> 2248c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattnerstd::ostream &WriteGraph(std::ostream &O, const GraphType &G, 2258c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner const std::string &Name = "") { 2268c836ce4f86713376b626e30765494f0a4f7e4b3Chris Lattner // Start the graph emission process... 227dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner GraphWriter<GraphType> W(O, G); 228dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 229dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the header for the graph... 230dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeHeader(Name); 231dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 232dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Emit all of the nodes in the graph... 233dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeNodes(); 234dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 235dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output any customizations on the graph 236dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 237dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner 238dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner // Output the end of the graph 239dc05fffe2bbbdecf2e0dc0bb691b8967777edc9aChris Lattner W.writeFooter(); 24095b923d548ed2e0f0993bb613868c871646f120cChris Lattner return O; 24195b923d548ed2e0f0993bb613868c871646f120cChris Lattner} 24295b923d548ed2e0f0993bb613868c871646f120cChris Lattner 2439d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 2449d5b532de9bdca37810a59a93a69128441b02c55Reid Spencersys::Path WriteGraph(const GraphType &G, 2459d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 2469d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 2479d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path Filename = sys::Path::GetTemporaryDirectory();; 2489d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.appendComponent(Name + ".dot"); 2499d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.makeUnique(); 2509d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::cerr << "Writing '" << Filename << "'... "; 2519d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2529d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::ofstream O(Filename.c_str()); 2539d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2549d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (O.good()) { 2559d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Start the graph emission process... 2569d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer GraphWriter<GraphType> W(O, G); 2579d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2589d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output the header for the graph... 2599d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeHeader(Title); 2609d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2619d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Emit all of the nodes in the graph... 2629d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeNodes(); 2639d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2649d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output any customizations on the graph 2659d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); 2669d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2679d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer // Output the end of the graph 2689d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer W.writeFooter(); 2699d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::cerr << " done. \n"; 2709d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2719d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer O.close(); 2729d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2739d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } else { 2749d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer std::cerr << "error opening file for writing!\n"; 2759d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer Filename.clear(); 2769d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 2779d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2789d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return Filename; 2799d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 2809d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2819d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, 2829d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// then cleanup. For use from the debugger. 2839d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer/// 2849d5b532de9bdca37810a59a93a69128441b02c55Reid Spencertemplate<typename GraphType> 2859d5b532de9bdca37810a59a93a69128441b02c55Reid Spencervoid ViewGraph(const GraphType& G, 2869d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Name, 2879d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer const std::string& Title = "") { 2889d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer sys::Path Filename = WriteGraph(G, Name, Title); 2899d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2909d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer if (Filename.isEmpty()) { 2919d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer return; 2929d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer } 2939d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 2949d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer DisplayGraph(Filename); 2959d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer} 2969d5b532de9bdca37810a59a93a69128441b02c55Reid Spencer 297d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace 298d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 29995b923d548ed2e0f0993bb613868c871646f120cChris Lattner#endif 300