Index: llvm/include/llvm/Support/DOTGraphTraits.h =================================================================== --- llvm/include/llvm/Support/DOTGraphTraits.h +++ llvm/include/llvm/Support/DOTGraphTraits.h @@ -64,6 +64,11 @@ return false; } + // renderNodeUsingHTML - If the function returns true, this node will be + // rendered using HTML-like labels which allows colors, etc in the node + // and the edge source labels. + static bool renderNodeUsingHTML(const void *) { return false; } + /// getNodeLabel - Given a node and a pointer to the top level graph, return /// the label to print in the node. template Index: llvm/include/llvm/Support/GraphWriter.h =================================================================== --- llvm/include/llvm/Support/GraphWriter.h +++ llvm/include/llvm/Support/GraphWriter.h @@ -86,6 +86,10 @@ child_iterator EE = GTraits::child_end(Node); bool hasEdgeSourceLabels = false; + bool renderNodeUsingHTML = DTraits.renderNodeUsingHTML(Node); + if (renderNodeUsingHTML) + O << ""; + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { std::string label = DTraits.getEdgeSourceLabel(Node, EI); @@ -94,14 +98,23 @@ hasEdgeSourceLabels = true; - if (i) - O << "|"; + if (renderNodeUsingHTML) + O << "" + << label << ""; + else { + if (i) + O << "|"; - O << "" << DOT::EscapeString(label); + O << "" << DOT::EscapeString(label); + } } - if (EI != EE && hasEdgeSourceLabels) - O << "|truncated..."; + if (EI != EE && hasEdgeSourceLabels) { + if (renderNodeUsingHTML) + O << "truncated..."; + else + O << "|truncated..."; + } return hasEdgeSourceLabels; } @@ -165,12 +178,40 @@ void writeNode(NodeRef Node) { std::string NodeAttributes = DTraits.getNodeAttributes(Node, G); - O << "\tNode" << static_cast(Node) << " [shape=record,"; + O << "\tNode" << static_cast(Node) << " [shape="; + bool renderNodeUsingHTML = DTraits.renderNodeUsingHTML(Node); + if (renderNodeUsingHTML) + O << "none,"; + else + O << "record,"; + if (!NodeAttributes.empty()) O << NodeAttributes << ","; - O << "label=\"{"; + O << "label="; + + if (renderNodeUsingHTML) { + // Count the numbewr of edges out of the node to determine how + // many columns to span (max 64) + unsigned ColSpan = 0; + child_iterator EI = GTraits::child_begin(Node); + child_iterator EE = GTraits::child_end(Node); + for (; EI != EE && ColSpan != 64; ++EI, ++ColSpan) + ; + if (ColSpan == 0) + ColSpan = 1; + // Include truncated messages when counting. + if (EI != EE) + ++ColSpan; + O << "<"; + else + O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); // If we should include the address of the node in the label, do so now. std::string Id = DTraits.getNodeIdentifierLabel(Node, G); @@ -187,15 +228,25 @@ bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels, Node); if (hasEdgeSourceLabels) { - if (!DTraits.renderGraphFromBottomUp()) O << "|"; - - O << "{" << EdgeSourceLabels.str() << "}"; - - if (DTraits.renderGraphFromBottomUp()) O << "|"; + if (!DTraits.renderGraphFromBottomUp()) + if (!renderNodeUsingHTML) + O << "|"; + + if (renderNodeUsingHTML) + O << EdgeSourceLabels.str(); + else + O << "{" << EdgeSourceLabels.str() << "}"; + + if (DTraits.renderGraphFromBottomUp()) + if (!renderNodeUsingHTML) + O << "|"; } if (DTraits.renderGraphFromBottomUp()) { - O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); + if (renderNodeUsingHTML) + O << DTraits.getNodeLabel(Node, G); + else + O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); // If we should include the address of the node in the label, do so now. std::string Id = DTraits.getNodeIdentifierLabel(Node, G); @@ -217,12 +268,18 @@ << DOT::EscapeString(DTraits.getEdgeDestLabel(Node, i)); } - if (i != e) - O << "|truncated..."; - O << "}"; + if (renderNodeUsingHTML) + O << ""; + else + if (i != e) + O << "|truncated...}"; } - O << "}\"];\n"; // Finish printing the "node" line + if (renderNodeUsingHTML) + O << "
"; + } else + O << "\"{"; if (!DTraits.renderGraphFromBottomUp()) { - O << DOT::EscapeString(DTraits.getNodeLabel(Node, G)); + if (renderNodeUsingHTML) + O << DTraits.getNodeLabel(Node, G) << "... truncated
>"; + else + O << "}\""; + O << "];\n"; // Finish printing the "node" line // Output all of the edges now child_iterator EI = GTraits::child_begin(Node);