blob: c0caaa07d751e8e1ba614ff93d2a3a83eedcd02f [file] [log] [blame]
Chris Lattnerc68c31b2002-07-10 22:38:08 +00001//===- Printer.cpp - Code for printing data structure graphs nicely -------===//
2//
3// This file implements the 'dot' graph printer.
4//
5//===----------------------------------------------------------------------===//
6
7#include "llvm/Analysis/DataStructure.h"
8#include "llvm/Module.h"
9#include "llvm/Assembly/Writer.h"
10#include <fstream>
11#include <sstream>
12
13void DSNode::dump() const { print(std::cerr, 0); }
14
15std::string DSNode::getCaption(Function *F) const {
16 std::stringstream OS;
17 WriteTypeSymbolic(OS, getType(), F ? F->getParent() : 0);
18
19 OS << " ";
20 if (NodeType & ScalarNode) OS << "S";
21 if (NodeType & AllocaNode) OS << "A";
22 if (NodeType & NewNode ) OS << "N";
23 if (NodeType & GlobalNode) OS << "G";
24 if (NodeType & SubElement) OS << "E";
25 if (NodeType & CastNode ) OS << "C";
26
27 return OS.str();
28}
29
30static std::string getValueName(Value *V, Function &F) {
31 std::stringstream OS;
32 WriteAsOperand(OS, V, true, true, F.getParent());
33 return OS.str();
34}
35
36
37
38static void replaceIn(std::string &S, char From, const std::string &To) {
39 for (unsigned i = 0; i < S.size(); )
40 if (S[i] == From) {
41 S.replace(S.begin()+i, S.begin()+i+1,
42 To.begin(), To.end());
43 i += To.size();
44 } else {
45 ++i;
46 }
47}
48
49static string escapeLabel(const string &In) {
50 string Label(In);
51 replaceIn(Label, '\\', "\\\\"); // Escape caption...
52 replaceIn(Label, ' ', "\\ ");
53 replaceIn(Label, '{', "\\{");
54 replaceIn(Label, '}', "\\}");
55 return Label;
56}
57
58static void writeEdge(std::ostream &O, const void *SrcNode,
59 const char *SrcNodePortName, int SrcNodeIdx,
60 const DSNode *VS, const string &EdgeAttr = "") {
61 O << "\tNode" << SrcNode << SrcNodePortName;
62 if (SrcNodeIdx != -1) O << SrcNodeIdx;
63 O << " -> Node" << (void*)VS;
64
65 if (!EdgeAttr.empty())
66 O << "[" << EdgeAttr << "]";
67 O << ";\n";
68}
69
70void DSNode::print(std::ostream &O, Function *F) const {
71 string Caption = escapeLabel(getCaption(F));
72
73 O << "\tNode" << (void*)this << " [ label =\"{" << Caption;
74
75 if (!Links.empty()) {
76 O << "|{";
77 for (unsigned i = 0; i < Links.size(); ++i) {
78 if (i) O << "|";
79 O << "<g" << i << ">";
80 }
81 O << "}";
82 }
83 O << "}\"];\n";
84
85 for (unsigned i = 0; i < Links.size(); ++i)
86 if (Links[i])
87 writeEdge(O, this, ":g", i, Links[i]);
88}
89
90void DSGraph::print(std::ostream &O) const {
91 O << "digraph DataStructures {\n"
92 << "\tnode [shape=Mrecord];\n"
93 << "\tedge [arrowtail=\"dot\"];\n"
94 << "\tsize=\"10,7.5\";\n"
95 << "\trotate=\"90\";\n"
96 << "\tlabel=\"Function\\ " << Func.getName() << "\";\n\n";
97
98 // Output all of the nodes...
99 for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
100 Nodes[i]->print(O, &Func);
101
102 O << "\n";
103 // Output all of the nodes edges for scalar labels
104 for (std::map<Value*, DSNodeHandle>::const_iterator I = ValueMap.begin(),
105 E = ValueMap.end(); I != E; ++I) {
106 O << "\tNode" << (void*)I->first << "[ shape=circle, label =\""
107 << escapeLabel(getValueName(I->first, Func)) << "\",style=dotted];\n";
108 writeEdge(O, I->first, "",-1, I->second.get(),"arrowtail=tee,style=dotted");
109 }
110
111 // Output the returned value pointer...
112 if (RetNode != 0) {
113 O << "\tNode0x1" << "[ shape=circle, label =\""
114 << escapeLabel("Return") << "\"];\n";
115 writeEdge(O, (void*)1, "", -1, RetNode, "arrowtail=tee,style=dotted");
116 }
117
118 // Output all of the call nodes...
119 for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) {
120 const std::vector<DSNodeHandle> &Call = FunctionCalls[i];
121 O << "\tNode" << (void*)&Call << " [shape=record,label=\"{call|{";
122 for (unsigned j = 0, e = Call.size(); j != e; ++j) {
123 if (j) O << "|";
124 O << "<g" << j << ">";
125 }
126 O << "}}\"];\n";
127
128 for (unsigned j = 0, e = Call.size(); j != e; ++j)
129 if (Call[j])
130 writeEdge(O, &Call, ":g", j, Call[j]);
131 }
132
133
134 O << "}\n";
135}
136
137
138
139
140// print - Print out the analysis results...
141void LocalDataStructures::print(std::ostream &O, Module *M) const {
142 for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
143 if (!I->isExternal()) {
144 std::string Filename = "ds." + I->getName() + ".dot";
145 O << "Writing '" << Filename << "'...";
146 std::ofstream F(Filename.c_str());
147
148 if (F.good()) {
149 DSGraph &Graph = getDSGraph(*I);
150 Graph.print(F);
151 O << " [" << Graph.getGraphSize() << "]\n";
152 } else {
153 O << " error opening file for writing!\n";
154 }
155 }
156}