Add support for memmove
[oota-llvm.git] / lib / Analysis / DataStructure / Printer.cpp
index 50d893366b7f3fd2449a4df4e7ec318d0d58e944..95879795601e35d59540040f16e847a6bc936f4b 100644 (file)
@@ -1,4 +1,11 @@
 //===- Printer.cpp - Code for printing data structure graphs nicely -------===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
 //
 // This file implements the 'dot' graph printer.
 //
@@ -8,6 +15,7 @@
 #include "llvm/Analysis/DSGraph.h"
 #include "llvm/Analysis/DSGraphTraits.h"
 #include "llvm/Module.h"
+#include "llvm/Constants.h"
 #include "llvm/Assembly/Writer.h"
 #include "Support/CommandLine.h"
 #include "Support/GraphWriter.h"
@@ -29,10 +37,13 @@ void DSNode::dump() const { print(std::cerr, 0); }
 
 static std::string getCaption(const DSNode *N, const DSGraph *G) {
   std::stringstream OS;
-  Module *M = G && G->hasFunction() ? G->getFunction().getParent() : 0;
+  Module *M = 0;
+  // Get the module from ONE of the functions in the graph it is available.
+  if (G && !G->getReturnNodes().empty())
+    M = G->getReturnNodes().begin()->first->getParent();
 
   if (N->isNodeCompletelyFolded())
-    OS << "FOLDED";
+    OS << "COLLAPSED";
   else {
     WriteTypeSymbolic(OS, N->getType(), M);
     if (N->isArray())
@@ -64,10 +75,11 @@ static std::string getCaption(const DSNode *N, const DSGraph *G) {
 template<>
 struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
   static std::string getGraphName(const DSGraph *G) {
-    if (G->hasFunction())
-      return "Function " + G->getFunction().getName();
-    else
-      return "Global graph";
+    switch (G->getReturnNodes().size()) {
+    case 0: return G->getFunctionNames();
+    case 1: return "Function " + G->getFunctionNames();
+    default: return "Functions: " + G->getFunctionNames();
+    }
   }
 
   static const char *getGraphProperties(const DSGraph *G) {
@@ -88,13 +100,14 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
   ///
   static void addCustomGraphFeatures(const DSGraph *G,
                                      GraphWriter<const DSGraph*> &GW) {
-    Module *CurMod = G->hasFunction() ? G->getFunction().getParent() : 0;
+    Module *CurMod = 0;
+    if (!G->getReturnNodes().empty())
+      CurMod = G->getReturnNodes().begin()->first->getParent();
 
     // Add scalar nodes to the graph...
-    const hash_map<Value*, DSNodeHandle> &VM = G->getScalarMap();
-    for (hash_map<Value*, DSNodeHandle>::const_iterator I = VM.begin();
-         I != VM.end(); ++I)
-      if (!isa<GlobalValue>(I->first)) {
+    const DSGraph::ScalarMapTy &VM = G->getScalarMap();
+    for (DSGraph::ScalarMapTy::const_iterator I = VM.begin(); I != VM.end();++I)
+      if (!isa<GlobalValue>(I->first) && !isa<ConstantPointerRef>(I->first)) {
         std::stringstream OS;
         WriteAsOperand(OS, I->first, false, true, CurMod);
         GW.emitSimpleNode(I->first, "", OS.str());
@@ -108,16 +121,24 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
 
 
     // Output the returned value pointer...
-    if (G->getRetNode().getNode() != 0) {
-      // Output the return node...
-      GW.emitSimpleNode((void*)1, "plaintext=circle", "returning");
-
-      // Add edge from return node to real destination
-      int RetEdgeDest = G->getRetNode().getOffset() >> DS::PointerShift;;
-      if (RetEdgeDest == 0) RetEdgeDest = -1;
-      GW.emitEdge((void*)1, -1, G->getRetNode().getNode(),
-                  RetEdgeDest, "arrowtail=tee,color=gray63");
-    }
+    const DSGraph::ReturnNodesTy &RetNodes = G->getReturnNodes();
+    for (DSGraph::ReturnNodesTy::const_iterator I = RetNodes.begin(),
+           E = RetNodes.end(); I != E; ++I)
+      if (I->second.getNode()) {
+        std::string Label;
+        if (RetNodes.size() == 1)
+          Label = "returning";
+        else
+          Label = I->first->getName() + " ret node";
+        // Output the return node...
+        GW.emitSimpleNode((void*)1, "plaintext=circle", Label);
+
+        // Add edge from return node to real destination
+        int RetEdgeDest = I->second.getOffset() >> DS::PointerShift;;
+        if (RetEdgeDest == 0) RetEdgeDest = -1;
+        GW.emitEdge((void*)1, -1, I->second.getNode(),
+                    RetEdgeDest, "arrowtail=tee,color=gray63");
+      }
 
     // Output all of the call nodes...
     const std::vector<DSCallSite> &FCs =