22#ifndef LLVM_SUPPORT_GRAPHWRITER_H
23#define LLVM_SUPPORT_GRAPHWRITER_H
48namespace GraphProgram {
63template<
typename GraphType>
67 bool RenderUsingHTML =
false;
72 using node_iterator =
typename GTraits::nodes_iterator;
73 using child_iterator =
typename GTraits::ChildIteratorType;
76 static_assert(std::is_pointer_v<NodeRef>,
77 "FIXME: Currently GraphWriter requires the NodeRef type to be "
78 "a pointer.\nThe pointer usage should be moved to "
79 "DOTGraphTraits, and removed from GraphWriter itself.");
84 child_iterator EI = GTraits::child_begin(
Node);
85 child_iterator EE = GTraits::child_end(
Node);
86 bool hasEdgeSourceLabels =
false;
91 for (
unsigned i = 0; EI != EE && i != 64; ++EI, ++i) {
97 hasEdgeSourceLabels =
true;
100 O <<
"<td colspan=\"1\" port=\"s" << i <<
"\">" << label <<
"</td>";
109 if (EI != EE && hasEdgeSourceLabels) {
111 O <<
"<td colspan=\"1\" port=\"s64\">truncated...</td>";
113 O <<
"|<s64>truncated...";
116 return hasEdgeSourceLabels;
144 else if (!GraphName.empty())
147 O <<
"digraph unnamed {\n";
150 O <<
"\trankdir=\"BT\";\n";
154 else if (!GraphName.empty())
167 for (
const auto Node : nodes<GraphType>(
G))
177 O <<
"\tNode" <<
static_cast<const void *
>(
Node) <<
" [shape=";
183 if (!NodeAttributes.empty()) O << NodeAttributes <<
",";
186 if (RenderUsingHTML) {
189 unsigned ColSpan = 0;
190 child_iterator EI = GTraits::child_begin(
Node);
191 child_iterator EE = GTraits::child_end(
Node);
192 for (; EI != EE && ColSpan != 64; ++EI, ++ColSpan)
199 O <<
"<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\""
200 <<
" cellpadding=\"0\"><tr><td align=\"text\" colspan=\"" << ColSpan
217 if (!NodeDesc.empty())
221 std::string edgeSourceLabels;
223 bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels,
Node);
225 if (hasEdgeSourceLabels) {
227 if (!RenderUsingHTML)
231 O << edgeSourceLabels;
233 O <<
"{" << edgeSourceLabels <<
"}";
236 if (!RenderUsingHTML)
252 if (!NodeDesc.empty())
260 for (; i != e && i != 64; ++i) {
262 O <<
"<d" << i <<
">"
267 O <<
"|<d64>truncated...";
272 O <<
"</tr></table>>";
278 child_iterator EI = GTraits::child_begin(
Node);
279 child_iterator EE = GTraits::child_end(
Node);
280 for (
unsigned i = 0; EI != EE && i != 64; ++EI, ++i)
283 for (; EI != EE; ++EI)
289 if (NodeRef TargetNode = *EI) {
296 (
unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt);
297 DestPort =
static_cast<int>(
Offset);
304 static_cast<const void*
>(TargetNode), DestPort,
311 const std::string &Label,
unsigned NumEdgeSources = 0,
312 const std::vector<std::string> *EdgeSourceLabels =
nullptr) {
313 O <<
"\tNode" <<
ID <<
"[ ";
317 if (NumEdgeSources) O <<
"{";
319 if (NumEdgeSources) {
322 for (
unsigned i = 0; i != NumEdgeSources; ++i) {
324 O <<
"<s" << i <<
">";
333 void emitEdge(
const void *SrcNodeID,
int SrcNodePort,
334 const void *DestNodeID,
int DestNodePort,
335 const std::string &Attrs) {
336 if (SrcNodePort > 64)
return;
337 if (DestNodePort > 64) DestNodePort = 64;
339 O <<
"\tNode" << SrcNodeID;
340 if (SrcNodePort >= 0)
341 O <<
":s" << SrcNodePort;
342 O <<
" -> Node" << DestNodeID;
344 O <<
":d" << DestNodePort;
347 O <<
"[" << Attrs <<
"]";
358template<
typename GraphType>
360 bool ShortNames =
false,
361 const Twine &Title =
"") {
366 W.writeGraph(Title.str());
377template <
typename GraphType>
379 bool ShortNames =
false,
380 const Twine &Title =
"",
381 std::string Filename =
"") {
383 if (Filename.empty()) {
390 if (EC == std::errc::file_exists) {
391 errs() <<
"file exists, overwriting" <<
"\n";
393 errs() <<
"error writing into file" <<
"\n";
396 errs() <<
"writing to the newly created file " << Filename <<
"\n";
402 errs() <<
"error opening file '" << Filename <<
"' for writing!\n";
407 errs() <<
" done. \n";
413#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
414template <
typename GraphType>
417 const Twine &Title,
bool ShortNames =
false,
426template<
typename GraphType>
428 bool ShortNames =
false,
const Twine &Title =
"",
432 if (Filename.empty())
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y)
void writeNode(NodeRef Node)
void writeEdge(NodeRef Node, unsigned edgeidx, child_iterator EI)
void emitSimpleNode(const void *ID, const std::string &Attr, const std::string &Label, unsigned NumEdgeSources=0, const std::vector< std::string > *EdgeSourceLabels=nullptr)
emitSimpleNode - Outputs a simple (non-record) node
void writeGraph(const std::string &Title="")
GraphWriter(raw_ostream &o, const GraphType &g, bool SN)
void emitEdge(const void *SrcNodeID, int SrcNodePort, const void *DestNodeID, int DestNodePort, const std::string &Attrs)
emitEdge - Output an edge from a simple node into the graph...
bool isNodeHidden(NodeRef Node)
raw_ostream & getOStream()
getOStream - Get the raw output stream into the graph file.
void writeHeader(const std::string &Title)
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
std::string EscapeString(const std::string &Label)
StringRef getColorString(unsigned NodeNumber)
Get a color string for this node number.
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
@ CD_CreateAlways
CD_CreateAlways - When opening a file:
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
This is an optimization pass for GlobalISel generic memory operations.
bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
LLVM_DUMP_METHOD void dumpDotGraphToFile(const GraphType &G, const Twine &FileName, const Twine &Title, bool ShortNames=false, const Twine &Name="")
DumpDotGraph - Just dump a dot graph to the user-provided file name.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
std::string createGraphFilename(const Twine &Name, int &FD)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
static std::string getNodeIdentifierLabel(const void *, const GraphType &)
static bool isNodeHidden(const void *, const GraphType &)
isNodeHidden - If the function returns true, the given node is not displayed in the graph.
static std::string getGraphName(const GraphType &)
getGraphName - Return the label for the graph as a whole.
static EdgeIter getEdgeTarget(const void *, EdgeIter I)
getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is called to determine which outgo...
static std::string getGraphProperties(const GraphType &)
getGraphProperties - Return any custom properties that should be included in the top level graph stru...
static std::string getEdgeAttributes(const void *, EdgeIter, const GraphType &)
If you want to override the dot attributes printed for a particular edge, override this method.
std::string getNodeLabel(const void *, const GraphType &)
getNodeLabel - Given a node and a pointer to the top level graph, return the label to print in the no...
static bool edgeTargetsEdgeSource(const void *, EdgeIter)
edgeTargetsEdgeSource - This method returns true if this outgoing edge should actually target another...
static bool renderGraphFromBottomUp()
renderGraphFromBottomUp - If this function returns true, the graph is emitted bottom-up instead of to...
static std::string getEdgeDestLabel(const void *, unsigned)
getEdgeDestLabel - If hasEdgeDestLabels, this function returns the incoming edge label with the given...
static std::string getEdgeSourceLabel(const void *, EdgeIter)
getEdgeSourceLabel - If you want to label the edge source itself, implement this method.
static bool hasEdgeDestLabels()
hasEdgeDestLabels - If this function returns true, the graph is able to provide labels for edge desti...
static bool renderNodesUsingHTML()
static void addCustomGraphFeatures(const GraphType &, GraphWriter &)
addCustomGraphFeatures - If a graph is made up of more than just straight-forward nodes and edges,...
static std::string getNodeDescription(const void *, const GraphType &)
static std::string getNodeAttributes(const void *, const GraphType &)
If you want to specify custom node attributes, this is the place to do so.
static unsigned numEdgeDestLabels(const void *)
numEdgeDestLabels - If hasEdgeDestLabels, this function returns the number of incoming edge labels th...
typename GraphType::UnknownGraphTypeError NodeRef