llvm.org GIT mirror llvm / 71bf404
Add viewCFG() and viewCFGOnly() APIs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14679 91177308-0d34-0410-b5e6-96231b3b80d8 Alkis Evlogimenos 16 years ago
2 changed file(s) with 143 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
133133 /// to the specified stream.
134134 ///
135135 void print(std::ostream &OS) const;
136
137 /// viewCFG - This function is meant for use from the debugger. You can just
138 /// say 'call F->viewCFG()' and a ghostview window should pop up from the
139 /// program, displaying the CFG of the current function with the code for each
140 /// basic block inside. This depends on there being a 'dot' and 'gv' program
141 /// in your path.
142 ///
143 void viewCFG() const;
144
145 /// viewCFGOnly - This function is meant for use from the debugger. It works
146 /// just like viewCFG, but it does not include the contents of basic blocks
147 /// into the nodes, just the label. If you are only interested in the CFG
148 /// this can make the graph smaller.
149 ///
150 void viewCFGOnly() const;
136151
137152 /// dump - Print the current MachineFunction to cerr, useful for debugger use.
138153 ///
205220 }
206221 };
207222
223 //===--------------------------------------------------------------------===//
224 // GraphTraits specializations for function basic block graphs (CFGs)
225 //===--------------------------------------------------------------------===//
226
227 // Provide specializations of GraphTraits to be able to treat a
228 // machine function as a graph of machine basic blocks... these are
229 // the same as the machine basic block iterators, except that the root
230 // node is implicitly the first node of the function.
231 //
232 template <> struct GraphTraits :
233 public GraphTraits {
234 static NodeType *getEntryNode(MachineFunction *F) {
235 return &F->front();
236 }
237
238 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
239 typedef MachineFunction::iterator nodes_iterator;
240 static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); }
241 static nodes_iterator nodes_end (MachineFunction *F) { return F->end(); }
242 };
243 template <> struct GraphTraits :
244 public GraphTraits {
245 static NodeType *getEntryNode(const MachineFunction *F) {
246 return &F->front();
247 }
248
249 // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
250 typedef MachineFunction::const_iterator nodes_iterator;
251 static nodes_iterator nodes_begin(const MachineFunction *F) { return F->begin(); }
252 static nodes_iterator nodes_end (const MachineFunction *F) { return F->end(); }
253 };
254
255
256 // Provide specializations of GraphTraits to be able to treat a function as a
257 // graph of basic blocks... and to walk it in inverse order. Inverse order for
258 // a function is considered to be when traversing the predecessor edges of a BB
259 // instead of the successor edges.
260 //
261 template <> struct GraphTraits > :
262 public GraphTraits > {
263 static NodeType *getEntryNode(Inverse G) {
264 return &G.Graph->front();
265 }
266 };
267 template <> struct GraphTraits > :
268 public GraphTraits > {
269 static NodeType *getEntryNode(Inverse G) {
270 return &G.Graph->front();
271 }
272 };
273
208274 } // End llvm namespace
209275
210276 #endif
2525 #include "llvm/iOther.h"
2626 #include "llvm/Type.h"
2727 #include "Support/LeakDetector.h"
28 #include "Support/GraphWriter.h"
29 #include
2830 #include
31 #include
2932
3033 using namespace llvm;
3134
137140 BB->print(OS);
138141
139142 OS << "\n# End machine code for " << Fn->getName () << "().\n\n";
143 }
144
145 /// CFGOnly flag - This is used to control whether or not the CFG graph printer
146 /// prints out the contents of basic blocks or not. This is acceptable because
147 /// this code is only really used for debugging purposes.
148 ///
149 static bool CFGOnly = false;
150
151 namespace llvm {
152 template<>
153 struct DOTGraphTraits : public DefaultDOTGraphTraits {
154 static std::string getGraphName(const MachineFunction *F) {
155 return "CFG for '" + F->getFunction()->getName() + "' function";
156 }
157
158 static std::string getNodeLabel(const MachineBasicBlock *Node,
159 const MachineFunction *Graph) {
160 if (CFGOnly && Node->getBasicBlock() &&
161 !Node->getBasicBlock()->getName().empty())
162 return Node->getBasicBlock()->getName() + ":";
163
164 std::ostringstream Out;
165 if (CFGOnly) {
166 Out << Node->getNumber() << ':';
167 return Out.str();
168 }
169
170 Node->print(Out);
171
172 std::string OutStr = Out.str();
173 if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
174
175 // Process string output to make it nicer...
176 for (unsigned i = 0; i != OutStr.length(); ++i)
177 if (OutStr[i] == '\n') { // Left justify
178 OutStr[i] = '\\';
179 OutStr.insert(OutStr.begin()+i+1, 'l');
180 }
181 return OutStr;
182 }
183 };
184 }
185
186 void MachineFunction::viewCFG() const
187 {
188 std::string Filename = "/tmp/cfg." + getFunction()->getName() + ".dot";
189 std::cerr << "Writing '" << Filename << "'... ";
190 std::ofstream F(Filename.c_str());
191
192 if (!F) {
193 std::cerr << " error opening file for writing!\n";
194 return;
195 }
196
197 WriteGraph(F, this);
198 F.close();
199 std::cerr << "\n";
200
201 std::cerr << "Running 'dot' program... " << std::flush;
202 if (system(("dot -Tps -Nfontname=Courier -Gsize=7.5,10 " + Filename
203 + " > /tmp/cfg.tempgraph.ps").c_str())) {
204 std::cerr << "Error running dot: 'dot' not in path?\n";
205 } else {
206 std::cerr << "\n";
207 system("gv /tmp/cfg.tempgraph.ps");
208 }
209 system(("rm " + Filename + " /tmp/cfg.tempgraph.ps").c_str());
210 }
211
212 void MachineFunction::viewCFGOnly() const
213 {
214 CFGOnly = true;
215 viewCFG();
216 CFGOnly = false;
140217 }
141218
142219 // The next two methods are used to construct and to retrieve
404481 void MachineFunctionInfo::popAllTempValues() {
405482 resetTmpAreaSize(); // clear tmp area to reuse
406483 }
407