23 #ifndef LLVM_SUPPORT_GRAPHWRITER_H 24 #define LLVM_SUPPORT_GRAPHWRITER_H 36 #include <type_traits> 51 namespace GraphProgram {
66 template<
typename GraphType>
73 using NodeRef =
typename GTraits::NodeRef;
74 using node_iterator =
typename GTraits::nodes_iterator;
75 using child_iterator =
typename GTraits::ChildIteratorType;
78 static_assert(std::is_pointer<NodeRef>::value,
79 "FIXME: Currently GraphWriter requires the NodeRef type to be " 80 "a pointer.\nThe pointer usage should be moved to " 81 "DOTGraphTraits, and removed from GraphWriter itself.");
85 bool getEdgeSourceLabels(
raw_ostream &O, NodeRef Node) {
86 child_iterator EI = GTraits::child_begin(Node);
87 child_iterator EE = GTraits::child_end(Node);
88 bool hasEdgeSourceLabels =
false;
90 for (
unsigned i = 0; EI != EE && i != 64; ++EI, ++i) {
91 std::string label = DTraits.getEdgeSourceLabel(Node, EI);
96 hasEdgeSourceLabels =
true;
104 if (EI != EE && hasEdgeSourceLabels)
105 O <<
"|<s64>truncated...";
107 return hasEdgeSourceLabels;
130 std::string GraphName = DTraits.getGraphName(G);
134 else if (!GraphName.empty())
137 O <<
"digraph unnamed {\n";
139 if (DTraits.renderGraphFromBottomUp())
140 O <<
"\trankdir=\"BT\";\n";
144 else if (!GraphName.empty())
146 O << DTraits.getGraphProperties(G);
157 for (
const auto Node : nodes<GraphType>(G))
158 if (!isNodeHidden(Node))
163 return DTraits.isNodeHidden(Node);
167 std::string NodeAttributes = DTraits.getNodeAttributes(Node, G);
169 O <<
"\tNode" <<
static_cast<const void*
>(Node) <<
" [shape=record,";
170 if (!NodeAttributes.empty()) O << NodeAttributes <<
",";
173 if (!DTraits.renderGraphFromBottomUp()) {
177 std::string
Id = DTraits.getNodeIdentifierLabel(Node, G);
181 std::string NodeDesc = DTraits.getNodeDescription(Node, G);
182 if (!NodeDesc.empty())
186 std::string edgeSourceLabels;
188 bool hasEdgeSourceLabels = getEdgeSourceLabels(EdgeSourceLabels, Node);
190 if (hasEdgeSourceLabels) {
191 if (!DTraits.renderGraphFromBottomUp()) O <<
"|";
193 O <<
"{" << EdgeSourceLabels.
str() <<
"}";
195 if (DTraits.renderGraphFromBottomUp()) O <<
"|";
198 if (DTraits.renderGraphFromBottomUp()) {
202 std::string
Id = DTraits.getNodeIdentifierLabel(Node, G);
206 std::string NodeDesc = DTraits.getNodeDescription(Node, G);
207 if (!NodeDesc.empty())
211 if (DTraits.hasEdgeDestLabels()) {
214 unsigned i = 0, e = DTraits.numEdgeDestLabels(Node);
215 for (; i != e && i != 64; ++i) {
217 O <<
"<d" << i <<
">" 222 O <<
"|<d64>truncated...";
229 child_iterator EI = GTraits::child_begin(Node);
230 child_iterator EE = GTraits::child_end(Node);
231 for (
unsigned i = 0; EI != EE && i != 64; ++EI, ++i)
232 if (!DTraits.isNodeHidden(*EI))
233 writeEdge(Node, i, EI);
234 for (; EI != EE; ++EI)
235 if (!DTraits.isNodeHidden(*EI))
236 writeEdge(Node, 64, EI);
239 void writeEdge(NodeRef Node,
unsigned edgeidx, child_iterator EI) {
240 if (NodeRef TargetNode = *EI) {
242 if (DTraits.edgeTargetsEdgeSource(Node, EI)) {
243 child_iterator TargetIt = DTraits.getEdgeTarget(Node, EI);
247 (
unsigned)std::distance(GTraits::child_begin(TargetNode), TargetIt);
248 DestPort =
static_cast<int>(
Offset);
251 if (DTraits.getEdgeSourceLabel(Node, EI).empty())
254 emitEdge(static_cast<const void*>(Node), edgeidx,
255 static_cast<const void*>(TargetNode), DestPort,
256 DTraits.getEdgeAttributes(Node, EI, G));
262 const std::string &Label,
unsigned NumEdgeSources = 0,
263 const std::vector<std::string> *EdgeSourceLabels =
nullptr) {
264 O <<
"\tNode" << ID <<
"[ ";
268 if (NumEdgeSources) O <<
"{";
270 if (NumEdgeSources) {
273 for (
unsigned i = 0; i != NumEdgeSources; ++i) {
275 O <<
"<s" << i <<
">";
284 void emitEdge(
const void *SrcNodeID,
int SrcNodePort,
285 const void *DestNodeID,
int DestNodePort,
286 const std::string &
Attrs) {
287 if (SrcNodePort > 64)
return;
288 if (DestNodePort > 64) DestNodePort = 64;
290 O <<
"\tNode" << SrcNodeID;
291 if (SrcNodePort >= 0)
292 O <<
":s" << SrcNodePort;
293 O <<
" -> Node" << DestNodeID;
294 if (DestNodePort >= 0 && DTraits.hasEdgeDestLabels())
295 O <<
":d" << DestNodePort;
298 O <<
"[" << Attrs <<
"]";
309 template<
typename GraphType>
311 bool ShortNames =
false,
312 const Twine &Title =
"") {
328 template <
typename GraphType>
330 bool ShortNames =
false,
331 const Twine &Title =
"",
332 std::string Filename =
"") {
335 std::string
N = Name.
str();
336 N = N.substr(0, std::min<std::size_t>(N.size(), 140));
337 if (Filename.empty()) {
343 if (EC == std::errc::file_exists) {
344 errs() <<
"file exists, overwriting" <<
"\n";
346 errs() <<
"error writing into file" <<
"\n";
353 errs() <<
"error opening file '" << Filename <<
"' for writing!\n";
358 errs() <<
" done. \n";
366 template<
typename GraphType>
368 bool ShortNames =
false,
const Twine &Title =
"",
372 if (Filename.empty())
380 #endif // LLVM_SUPPORT_GRAPHWRITER_H 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
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
This class represents lattice values for constants.
static void addCustomGraphFeatures(const GraphType &, GraphWriter &)
addCustomGraphFeatures - If a graph is made up of more than just straight-forward nodes and edges...
bool isNodeHidden(NodeRef Node)
void writeEdge(NodeRef Node, unsigned edgeidx, child_iterator EI)
*ViewGraph Emit a dot run run gv on the postscript *then cleanup For use from the debugger *void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
void writeGraph(const std::string &Title="")
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
std::string EscapeString(const std::string &Label)
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...
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
std::string createGraphFilename(const Twine &Name, int &FD)
StringRef getColorString(unsigned NodeNumber)
Get a color string for this node number.
raw_ostream & getOStream()
getOStream - Get the raw output stream into the graph file.
A raw_ostream that writes to a file descriptor.
bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
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...
std::string str() const
Return the twine contents as a std::string.
A raw_ostream that writes to an std::string.
void writeHeader(const std::string &Title)
This class implements an extremely fast bulk output stream that can only output to a stream...
void writeNode(NodeRef Node)
StringRef - Represent a constant reference to a string, i.e.
GraphWriter(raw_ostream &o, const GraphType &g, bool SN)