LLVM API Documentation

SelectionDAGPrinter.cpp

Go to the documentation of this file.
00001 //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This implements the SelectionDAG::viewGraph method.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Constants.h"
00015 #include "llvm/Function.h"
00016 #include "llvm/Assembly/Writer.h"
00017 #include "llvm/CodeGen/SelectionDAG.h"
00018 #include "llvm/CodeGen/ScheduleDAGSDNodes.h"
00019 #include "llvm/CodeGen/MachineConstantPool.h"
00020 #include "llvm/CodeGen/MachineFunction.h"
00021 #include "llvm/CodeGen/MachineModuleInfo.h"
00022 #include "llvm/CodeGen/PseudoSourceValue.h"
00023 #include "llvm/Target/TargetRegisterInfo.h"
00024 #include "llvm/Target/TargetMachine.h"
00025 #include "llvm/Support/Debug.h"
00026 #include "llvm/Support/GraphWriter.h"
00027 #include "llvm/Support/raw_ostream.h"
00028 #include "llvm/ADT/DenseSet.h"
00029 #include "llvm/ADT/StringExtras.h"
00030 #include "llvm/Config/config.h"
00031 #include <fstream>
00032 using namespace llvm;
00033 
00034 namespace llvm {
00035   template<>
00036   struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
00037     static bool hasEdgeDestLabels() {
00038       return true;
00039     }
00040 
00041     static unsigned numEdgeDestLabels(const void *Node) {
00042       return ((const SDNode *) Node)->getNumValues();
00043     }
00044 
00045     static std::string getEdgeDestLabel(const void *Node, unsigned i) {
00046       return ((const SDNode *) Node)->getValueType(i).getMVTString();
00047     }
00048 
00049     /// edgeTargetsEdgeSource - This method returns true if this outgoing edge
00050     /// should actually target another edge source, not a node.  If this method is
00051     /// implemented, getEdgeTarget should be implemented.
00052     template<typename EdgeIter>
00053     static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) {
00054       return true;
00055     }
00056 
00057     /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
00058     /// called to determine which outgoing edge of Node is the target of this
00059     /// edge.
00060     template<typename EdgeIter>
00061     static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) {
00062       SDNode *TargetNode = *I;
00063       SDNodeIterator NI = SDNodeIterator::begin(TargetNode);
00064       std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo());
00065       return NI;
00066     }
00067 
00068     static std::string getGraphName(const SelectionDAG *G) {
00069       return G->getMachineFunction().getFunction()->getName();
00070     }
00071 
00072     static bool renderGraphFromBottomUp() {
00073       return true;
00074     }
00075     
00076     static bool hasNodeAddressLabel(const SDNode *Node,
00077                                     const SelectionDAG *Graph) {
00078       return true;
00079     }
00080     
00081     /// If you want to override the dot attributes printed for a particular
00082     /// edge, override this method.
00083     template<typename EdgeIter>
00084     static std::string getEdgeAttributes(const void *Node, EdgeIter EI) {
00085       SDValue Op = EI.getNode()->getOperand(EI.getOperand());
00086       MVT VT = Op.getValueType();
00087       if (VT == MVT::Flag)
00088         return "color=red,style=bold";
00089       else if (VT == MVT::Other)
00090         return "color=blue,style=dashed";
00091       return "";
00092     }
00093     
00094 
00095     static std::string getNodeLabel(const SDNode *Node,
00096                                     const SelectionDAG *Graph);
00097     static std::string getNodeAttributes(const SDNode *N,
00098                                          const SelectionDAG *Graph) {
00099 #ifndef NDEBUG
00100       const std::string &Attrs = Graph->getGraphAttrs(N);
00101       if (!Attrs.empty()) {
00102         if (Attrs.find("shape=") == std::string::npos)
00103           return std::string("shape=Mrecord,") + Attrs;
00104         else
00105           return Attrs;
00106       }
00107 #endif
00108       return "shape=Mrecord";
00109     }
00110 
00111     static void addCustomGraphFeatures(SelectionDAG *G,
00112                                        GraphWriter<SelectionDAG*> &GW) {
00113       GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
00114       if (G->getRoot().getNode())
00115         GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(),
00116                     "color=blue,style=dashed");
00117     }
00118   };
00119 }
00120 
00121 std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
00122                                                         const SelectionDAG *G) {
00123   std::string Op = Node->getOperationName(G);
00124 
00125   if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(Node)) {
00126     Op += ": " + utostr(CSDN->getZExtValue());
00127   } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(Node)) {
00128     Op += ": " + ftostr(CSDN->getValueAPF());
00129   } else if (const GlobalAddressSDNode *GADN =
00130              dyn_cast<GlobalAddressSDNode>(Node)) {
00131     Op += ": " + GADN->getGlobal()->getName();
00132     if (int64_t Offset = GADN->getOffset()) {
00133       if (Offset > 0)
00134         Op += "+" + itostr(Offset);
00135       else
00136         Op += itostr(Offset);
00137     }
00138   } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
00139     Op += " " + itostr(FIDN->getIndex());
00140   } else if (const JumpTableSDNode *JTDN = dyn_cast<JumpTableSDNode>(Node)) {
00141     Op += " " + itostr(JTDN->getIndex());
00142   } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
00143     if (CP->isMachineConstantPoolEntry()) {
00144       Op += '<';
00145       {
00146         raw_string_ostream OSS(Op);
00147         OSS << *CP->getMachineCPVal();
00148       }
00149       Op += '>';
00150     } else {
00151       if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
00152         Op += "<" + ftostr(CFP->getValueAPF()) + ">";
00153       else if (ConstantInt *CI = dyn_cast<ConstantInt>(CP->getConstVal()))
00154         Op += "<" + utostr(CI->getZExtValue()) + ">";
00155       else {
00156         Op += '<';
00157         {
00158           raw_string_ostream OSS(Op);
00159           WriteAsOperand(OSS, CP->getConstVal(), false);
00160         }
00161         Op += '>';
00162       }
00163     }
00164     Op += " A=" + itostr(1 << CP->getAlignment());
00165   } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
00166     Op = "BB: ";
00167     const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock();
00168     if (LBB)
00169       Op += LBB->getName();
00170     //Op += " " + (const void*)BBDN->getBasicBlock();
00171   } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node)) {
00172     if (G && R->getReg() != 0 &&
00173         TargetRegisterInfo::isPhysicalRegister(R->getReg())) {
00174       Op = Op + " " +
00175         G->getTarget().getRegisterInfo()->getName(R->getReg());
00176     } else {
00177       Op += " #" + utostr(R->getReg());
00178     }
00179   } else if (const DbgStopPointSDNode *D = dyn_cast<DbgStopPointSDNode>(Node)) {
00180     Op += ": " + D->getCompileUnit()->getFileName();
00181     Op += ":" + utostr(D->getLine());
00182     if (D->getColumn() != 0)
00183       Op += ":" + utostr(D->getColumn());
00184   } else if (const LabelSDNode *L = dyn_cast<LabelSDNode>(Node)) {
00185     Op += ": LabelID=" + utostr(L->getLabelID());
00186   } else if (const CallSDNode *C = dyn_cast<CallSDNode>(Node)) {
00187     Op += ": CallingConv=" + utostr(C->getCallingConv());
00188     if (C->isVarArg())
00189       Op += ", isVarArg";
00190     if (C->isTailCall())
00191       Op += ", isTailCall";
00192   } else if (const ExternalSymbolSDNode *ES =
00193              dyn_cast<ExternalSymbolSDNode>(Node)) {
00194     Op += "'" + std::string(ES->getSymbol()) + "'";
00195   } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(Node)) {
00196     if (M->getValue())
00197       Op += "<" + M->getValue()->getName() + ">";
00198     else
00199       Op += "<null>";
00200   } else if (const MemOperandSDNode *M = dyn_cast<MemOperandSDNode>(Node)) {
00201     const Value *V = M->MO.getValue();
00202     Op += '<';
00203     if (!V) {
00204       Op += "(unknown)";
00205     } else if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V)) {
00206       // PseudoSourceValues don't have names, so use their print method.
00207       raw_string_ostream OSS(Op);
00208       PSV->print(OSS);
00209     } else {
00210       Op += V->getName();
00211     }
00212     Op += '+' + itostr(M->MO.getOffset()) + '>';
00213   } else if (const ARG_FLAGSSDNode *N = dyn_cast<ARG_FLAGSSDNode>(Node)) {
00214     Op = Op + " AF=" + N->getArgFlags().getArgFlagsString();
00215   } else if (const VTSDNode *N = dyn_cast<VTSDNode>(Node)) {
00216     Op = Op + " VT=" + N->getVT().getMVTString();
00217   } else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(Node)) {
00218     bool doExt = true;
00219     switch (LD->getExtensionType()) {
00220     default: doExt = false; break;
00221     case ISD::EXTLOAD:
00222       Op = Op + "<anyext ";
00223       break;
00224     case ISD::SEXTLOAD:
00225       Op = Op + " <sext ";
00226       break;
00227     case ISD::ZEXTLOAD:
00228       Op = Op + " <zext ";
00229       break;
00230     }
00231     if (doExt)
00232       Op += LD->getMemoryVT().getMVTString() + ">";
00233     if (LD->isVolatile())
00234       Op += "<V>";
00235     Op += LD->getIndexedModeName(LD->getAddressingMode());
00236     if (LD->getAlignment() > 1)
00237       Op += " A=" + utostr(LD->getAlignment());
00238   } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(Node)) {
00239     if (ST->isTruncatingStore())
00240       Op += "<trunc " + ST->getMemoryVT().getMVTString() + ">";
00241     if (ST->isVolatile())
00242       Op += "<V>";
00243     Op += ST->getIndexedModeName(ST->getAddressingMode());
00244     if (ST->getAlignment() > 1)
00245       Op += " A=" + utostr(ST->getAlignment());
00246   }
00247 
00248 #if 0
00249   Op += " Id=" + itostr(Node->getNodeId());
00250 #endif
00251   
00252   return Op;
00253 }
00254 
00255 
00256 /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
00257 /// rendered using 'dot'.
00258 ///
00259 void SelectionDAG::viewGraph(const std::string &Title) {
00260 // This code is only for debugging!
00261 #ifndef NDEBUG
00262   ViewGraph(this, "dag." + getMachineFunction().getFunction()->getName(),
00263             Title);
00264 #else
00265   cerr << "SelectionDAG::viewGraph is only available in debug builds on "
00266        << "systems with Graphviz or gv!\n";
00267 #endif  // NDEBUG
00268 }
00269 
00270 // This overload is defined out-of-line here instead of just using a
00271 // default parameter because this is easiest for gdb to call.
00272 void SelectionDAG::viewGraph() {
00273   viewGraph("");
00274 }
00275 
00276 /// clearGraphAttrs - Clear all previously defined node graph attributes.
00277 /// Intended to be used from a debugging tool (eg. gdb).
00278 void SelectionDAG::clearGraphAttrs() {
00279 #ifndef NDEBUG
00280   NodeGraphAttrs.clear();
00281 #else
00282   cerr << "SelectionDAG::clearGraphAttrs is only available in debug builds"
00283        << " on systems with Graphviz or gv!\n";
00284 #endif
00285 }
00286 
00287 
00288 /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
00289 ///
00290 void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
00291 #ifndef NDEBUG
00292   NodeGraphAttrs[N] = Attrs;
00293 #else
00294   cerr << "SelectionDAG::setGraphAttrs is only available in debug builds"
00295        << " on systems with Graphviz or gv!\n";
00296 #endif
00297 }
00298 
00299 
00300 /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
00301 /// Used from getNodeAttributes.
00302 const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
00303 #ifndef NDEBUG
00304   std::map<const SDNode *, std::string>::const_iterator I =
00305     NodeGraphAttrs.find(N);
00306     
00307   if (I != NodeGraphAttrs.end())
00308     return I->second;
00309   else
00310     return "";
00311 #else
00312   cerr << "SelectionDAG::getGraphAttrs is only available in debug builds"
00313        << " on systems with Graphviz or gv!\n";
00314   return std::string("");
00315 #endif
00316 }
00317 
00318 /// setGraphColor - Convenience for setting node color attribute.
00319 ///
00320 void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
00321 #ifndef NDEBUG
00322   NodeGraphAttrs[N] = std::string("color=") + Color;
00323 #else
00324   cerr << "SelectionDAG::setGraphColor is only available in debug builds"
00325        << " on systems with Graphviz or gv!\n";
00326 #endif
00327 }
00328 
00329 /// setSubgraphColorHelper - Implement setSubgraphColor.  Return
00330 /// whether we truncated the search.
00331 ///
00332 bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
00333                                           int level, bool &printed) {
00334   bool hit_limit = false;
00335 
00336 #ifndef NDEBUG
00337   if (level >= 20) {
00338     if (!printed) {
00339       printed = true;
00340       DOUT << "setSubgraphColor hit max level\n";
00341     }
00342     return true;
00343   }
00344 
00345   unsigned oldSize = visited.size();
00346   visited.insert(N);
00347   if (visited.size() != oldSize) {
00348     setGraphColor(N, Color);
00349     for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N);
00350         i != iend;
00351         ++i) {
00352       hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit;
00353     }
00354   }
00355 #else
00356   cerr << "SelectionDAG::setSubgraphColor is only available in debug builds"
00357        << " on systems with Graphviz or gv!\n";
00358 #endif
00359   return hit_limit;
00360 }
00361 
00362 /// setSubgraphColor - Convenience for setting subgraph color attribute.
00363 ///
00364 void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {
00365 #ifndef NDEBUG
00366   DenseSet<SDNode *> visited;
00367   bool printed = false;
00368   if (setSubgraphColorHelper(N, Color, visited, 0, printed)) {
00369     // Visually mark that we hit the limit
00370     if (strcmp(Color, "red") == 0) {
00371       setSubgraphColorHelper(N, "blue", visited, 0, printed);
00372     }
00373     else if (strcmp(Color, "yellow") == 0) {
00374       setSubgraphColorHelper(N, "green", visited, 0, printed);
00375     }
00376   }
00377 
00378 #else
00379   cerr << "SelectionDAG::setSubgraphColor is only available in debug builds"
00380        << " on systems with Graphviz or gv!\n";
00381 #endif
00382 }
00383 
00384 std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {
00385   std::string s;
00386   raw_string_ostream O(s);
00387   O << "SU(" << SU->NodeNum << "): ";
00388   if (SU->getNode()) {
00389     SmallVector<SDNode *, 4> FlaggedNodes;
00390     for (SDNode *N = SU->getNode(); N; N = N->getFlaggedNode())
00391       FlaggedNodes.push_back(N);
00392     while (!FlaggedNodes.empty()) {
00393       O << DOTGraphTraits<SelectionDAG*>::getNodeLabel(FlaggedNodes.back(), DAG);
00394       FlaggedNodes.pop_back();
00395       if (!FlaggedNodes.empty())
00396         O << "\n    ";
00397     }
00398   } else {
00399     O << "CROSS RC COPY";
00400   }
00401   return O.str();
00402 }
00403 
00404 void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const {
00405   if (DAG) {
00406     // Draw a special "GraphRoot" node to indicate the root of the graph.
00407     GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
00408     const SDNode *N = DAG->getRoot().getNode();
00409     if (N && N->getNodeId() != -1)
00410       GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1,
00411                   "color=blue,style=dashed");
00412   }
00413 }



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.