a9b07afc90f87445a3a41805345d615c48a6ce7e
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAGPrinter.cpp
1 //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This implements the SelectionDAG::viewGraph method.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Constants.h"
15 #include "llvm/Function.h"
16 #include "llvm/Assembly/Writer.h"
17 #include "llvm/CodeGen/SelectionDAG.h"
18 #include "llvm/CodeGen/ScheduleDAG.h"
19 #include "llvm/CodeGen/MachineConstantPool.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineModuleInfo.h"
22 #include "llvm/CodeGen/PseudoSourceValue.h"
23 #include "llvm/Target/TargetRegisterInfo.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "llvm/Support/GraphWriter.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/Config/config.h"
28 #include <fstream>
29 #include <sstream>
30 using namespace llvm;
31
32 namespace llvm {
33   template<>
34   struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
35     static std::string getGraphName(const SelectionDAG *G) {
36       return G->getMachineFunction().getFunction()->getName();
37     }
38
39     static bool renderGraphFromBottomUp() {
40       return true;
41     }
42     
43     static bool hasNodeAddressLabel(const SDNode *Node,
44                                     const SelectionDAG *Graph) {
45       return true;
46     }
47     
48     /// If you want to override the dot attributes printed for a particular
49     /// edge, override this method.
50     template<typename EdgeIter>
51     static std::string getEdgeAttributes(const void *Node, EdgeIter EI) {
52       SDOperand Op = EI.getNode()->getOperand(EI.getOperand());
53       MVT VT = Op.getValueType();
54       if (VT == MVT::Flag)
55         return "color=red,style=bold";
56       else if (VT == MVT::Other)
57         return "color=blue,style=dashed";
58       return "";
59     }
60     
61
62     static std::string getNodeLabel(const SDNode *Node,
63                                     const SelectionDAG *Graph);
64     static std::string getNodeAttributes(const SDNode *N,
65                                          const SelectionDAG *Graph) {
66 #ifndef NDEBUG
67       const std::string &Attrs = Graph->getGraphAttrs(N);
68       if (!Attrs.empty()) {
69         if (Attrs.find("shape=") == std::string::npos)
70           return std::string("shape=Mrecord,") + Attrs;
71         else
72           return Attrs;
73       }
74 #endif
75       return "shape=Mrecord";
76     }
77
78     static void addCustomGraphFeatures(SelectionDAG *G,
79                                        GraphWriter<SelectionDAG*> &GW) {
80       GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
81       if (G->getRoot().Val)
82         GW.emitEdge(0, -1, G->getRoot().Val, -1, "");
83     }
84   };
85 }
86
87 std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
88                                                         const SelectionDAG *G) {
89   std::string Op = Node->getOperationName(G);
90
91   for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i)
92     if (Node->getValueType(i) == MVT::Other)
93       Op += ":ch";
94     else
95       Op = Op + ":" + Node->getValueType(i).getMVTString();
96     
97   if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
98     Op += ": " + utostr(CSDN->getValue());
99   } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
100     Op += ": " + ftostr(CSDN->getValueAPF());
101   } else if (const GlobalAddressSDNode *GADN =
102              dyn_cast<GlobalAddressSDNode>(Node)) {
103     int offset = GADN->getOffset();
104     Op += ": " + GADN->getGlobal()->getName();
105     if (offset > 0)
106       Op += "+" + itostr(offset);
107     else
108       Op += itostr(offset);
109   } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
110     Op += " " + itostr(FIDN->getIndex());
111   } else if (const JumpTableSDNode *JTDN = dyn_cast<JumpTableSDNode>(Node)) {
112     Op += " " + itostr(JTDN->getIndex());
113   } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
114     if (CP->isMachineConstantPoolEntry()) {
115       std::ostringstream SS;
116       CP->getMachineCPVal()->print(SS);
117       Op += "<" + SS.str() + ">";
118     } else {
119       if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
120         Op += "<" + ftostr(CFP->getValueAPF()) + ">";
121       else if (ConstantInt *CI = dyn_cast<ConstantInt>(CP->getConstVal()))
122         Op += "<" + utostr(CI->getZExtValue()) + ">";
123       else {
124         std::ostringstream SS;
125         WriteAsOperand(SS, CP->getConstVal(), false);
126         Op += "<" + SS.str() + ">";
127       }
128     }
129   } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
130     Op = "BB: ";
131     const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
132     if (LBB)
133       Op += LBB->getName();
134     //Op += " " + (const void*)BBDN->getBasicBlock();
135   } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node)) {
136     if (G && R->getReg() != 0 &&
137         TargetRegisterInfo::isPhysicalRegister(R->getReg())) {
138       Op = Op + " " +
139         G->getTarget().getRegisterInfo()->getName(R->getReg());
140     } else {
141       Op += " #" + utostr(R->getReg());
142     }
143   } else if (const DbgStopPointSDNode *D = dyn_cast<DbgStopPointSDNode>(Node)) {
144     Op += ": " + D->getCompileUnit()->getFileName();
145     Op += ":" + utostr(D->getLine());
146     if (D->getColumn() != 0)
147       Op += ":" + utostr(D->getColumn());
148   } else if (const LabelSDNode *L = dyn_cast<LabelSDNode>(Node)) {
149     Op += ": LabelID=" + utostr(L->getLabelID());
150   } else if (const ExternalSymbolSDNode *ES =
151              dyn_cast<ExternalSymbolSDNode>(Node)) {
152     Op += "'" + std::string(ES->getSymbol()) + "'";
153   } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
154     if (M->getValue())
155       Op += "<" + M->getValue()->getName() + ">";
156     else
157       Op += "<null>";
158   } else if (const MemOperandSDNode *M = dyn_cast<MemOperandSDNode>(Node)) {
159     const Value *V = M->MO.getValue();
160     Op += '<';
161     if (!V) {
162       Op += "(unknown)";
163     } else if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V)) {
164       // PseudoSourceValues don't have names, so use their print method.
165       std::ostringstream SS;
166       M->MO.getValue()->print(SS);
167       Op += SS.str();
168     } else {
169       Op += V->getName();
170     }
171     Op += '+' + itostr(M->MO.getOffset()) + '>';
172   } else if (const ARG_FLAGSSDNode *N = dyn_cast<ARG_FLAGSSDNode>(Node)) {
173     Op = Op + " AF=" + N->getArgFlags().getArgFlagsString();
174   } else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
175     Op = Op + " VT=" + N->getVT().getMVTString();
176   } else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(Node)) {
177     bool doExt = true;
178     switch (LD->getExtensionType()) {
179     default: doExt = false; break;
180     case ISD::EXTLOAD:
181       Op = Op + "<anyext ";
182       break;
183     case ISD::SEXTLOAD:
184       Op = Op + " <sext ";
185       break;
186     case ISD::ZEXTLOAD:
187       Op = Op + " <zext ";
188       break;
189     }
190     if (doExt)
191       Op += LD->getMemoryVT().getMVTString() + ">";
192     if (LD->isVolatile())
193       Op += "<V>";
194     Op += LD->getIndexedModeName(LD->getAddressingMode());
195     if (LD->getAlignment() > 1)
196       Op += " A=" + utostr(LD->getAlignment());
197   } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(Node)) {
198     if (ST->isTruncatingStore())
199       Op += "<trunc " + ST->getMemoryVT().getMVTString() + ">";
200     if (ST->isVolatile())
201       Op += "<V>";
202     Op += ST->getIndexedModeName(ST->getAddressingMode());
203     if (ST->getAlignment() > 1)
204       Op += " A=" + utostr(ST->getAlignment());
205   }
206
207 #if 0
208   Op += " Id=" + itostr(Node->getNodeId());
209 #endif
210   
211   return Op;
212 }
213
214
215 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
216 /// rendered using 'dot'.
217 ///
218 void SelectionDAG::viewGraph() {
219 // This code is only for debugging!
220 #ifndef NDEBUG
221   ViewGraph(this, "dag." + getMachineFunction().getFunction()->getName());
222 #else
223   cerr << "SelectionDAG::viewGraph is only available in debug builds on "
224        << "systems with Graphviz or gv!\n";
225 #endif  // NDEBUG
226 }
227
228
229 /// clearGraphAttrs - Clear all previously defined node graph attributes.
230 /// Intended to be used from a debugging tool (eg. gdb).
231 void SelectionDAG::clearGraphAttrs() {
232 #ifndef NDEBUG
233   NodeGraphAttrs.clear();
234 #else
235   cerr << "SelectionDAG::clearGraphAttrs is only available in debug builds"
236        << " on systems with Graphviz or gv!\n";
237 #endif
238 }
239
240
241 /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
242 ///
243 void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
244 #ifndef NDEBUG
245   NodeGraphAttrs[N] = Attrs;
246 #else
247   cerr << "SelectionDAG::setGraphAttrs is only available in debug builds"
248        << " on systems with Graphviz or gv!\n";
249 #endif
250 }
251
252
253 /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
254 /// Used from getNodeAttributes.
255 const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
256 #ifndef NDEBUG
257   std::map<const SDNode *, std::string>::const_iterator I =
258     NodeGraphAttrs.find(N);
259     
260   if (I != NodeGraphAttrs.end())
261     return I->second;
262   else
263     return "";
264 #else
265   cerr << "SelectionDAG::getGraphAttrs is only available in debug builds"
266        << " on systems with Graphviz or gv!\n";
267   return std::string("");
268 #endif
269 }
270
271 /// setGraphColor - Convenience for setting node color attribute.
272 ///
273 void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
274 #ifndef NDEBUG
275   NodeGraphAttrs[N] = std::string("color=") + Color;
276 #else
277   cerr << "SelectionDAG::setGraphColor is only available in debug builds"
278        << " on systems with Graphviz or gv!\n";
279 #endif
280 }
281
282 namespace llvm {
283   template<>
284   struct DOTGraphTraits<ScheduleDAG*> : public DefaultDOTGraphTraits {
285     static std::string getGraphName(const ScheduleDAG *G) {
286       return DOTGraphTraits<SelectionDAG*>::getGraphName(&G->DAG);
287     }
288
289     static bool renderGraphFromBottomUp() {
290       return true;
291     }
292     
293     static bool hasNodeAddressLabel(const SUnit *Node,
294                                     const ScheduleDAG *Graph) {
295       return true;
296     }
297     
298     /// If you want to override the dot attributes printed for a particular
299     /// edge, override this method.
300     template<typename EdgeIter>
301     static std::string getEdgeAttributes(const void *Node, EdgeIter EI) {
302       if (EI.isSpecialDep())
303         return "color=cyan,style=dashed";
304       if (EI.isCtrlDep())
305         return "color=blue,style=dashed";
306       return "";
307     }
308     
309
310     static std::string getNodeLabel(const SUnit *Node,
311                                     const ScheduleDAG *Graph);
312     static std::string getNodeAttributes(const SUnit *N,
313                                          const ScheduleDAG *Graph) {
314       return "shape=Mrecord";
315     }
316
317     static void addCustomGraphFeatures(ScheduleDAG *G,
318                                        GraphWriter<ScheduleDAG*> &GW) {
319       GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
320       const SDNode *N = G->DAG.getRoot().Val;
321       if (N && N->getNodeId() != -1)
322         GW.emitEdge(0, -1, &G->SUnits[N->getNodeId()], -1, "");
323     }
324   };
325 }
326
327 std::string DOTGraphTraits<ScheduleDAG*>::getNodeLabel(const SUnit *SU,
328                                                        const ScheduleDAG *G) {
329   std::string Op;
330
331   for (unsigned i = 0; i < SU->FlaggedNodes.size(); ++i) {
332     Op += DOTGraphTraits<SelectionDAG*>::getNodeLabel(SU->FlaggedNodes[i],
333                                                       &G->DAG) + "\n";
334   }
335
336   if (SU->Node)
337     Op += DOTGraphTraits<SelectionDAG*>::getNodeLabel(SU->Node, &G->DAG);
338   else
339     Op += "<CROSS RC COPY>";
340
341   return Op;
342 }
343
344
345 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
346 /// rendered using 'dot'.
347 ///
348 void ScheduleDAG::viewGraph() {
349 // This code is only for debugging!
350 #ifndef NDEBUG
351   ViewGraph(this, "dag." + DAG.getMachineFunction().getFunction()->getName());
352 #else
353   cerr << "ScheduleDAG::viewGraph is only available in debug builds on "
354        << "systems with Graphviz or gv!\n";
355 #endif  // NDEBUG
356 }