ADD MORE FUNCTIONS!
[oota-llvm.git] / lib / Analysis / DataStructure / GraphChecker.cpp
index 7bfbf7d44cdfa159175a131d772c11607942cb23..af8731eb05c01934e7c166891be26d97d6ff6257 100644 (file)
@@ -1,14 +1,23 @@
 //===- GraphChecker.cpp - Assert that various graph properties hold -------===//
+// 
+//                     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 pass is used to test DSA with regression tests.  It can be used to check
 // that certain graph properties hold, such as two nodes being disjoint, whether
 // or not a node is collapsed, etc.  These are the command line arguments that
 // it supports:
 //
-//   --dsgc-dsapass={local,bu,td}     - Specify what flavor of graph to check
+//   --dsgc-dspass={local,bu,td}      - Specify what flavor of graph to check
 //   --dsgc-abort-if-any-collapsed    - Abort if any collapsed nodes are found
 //   --dsgc-abort-if-collapsed=<list> - Abort if a node pointed to by an SSA
 //                                      value with name in <list> is collapsed
+//   --dsgc-check-flags=<list>        - Abort if the specified nodes have flags
+//                                      that are not specified.
 //   --dsgc-abort-if-merged=<list>    - Abort if any of the named SSA values
 //                                      point to the same node.
 //
@@ -20,6 +29,8 @@
 #include "llvm/Value.h"
 #include <set>
 
+using namespace llvm;
+
 namespace {
   enum DSPass { local, bu, td };
   cl::opt<DSPass>
@@ -36,6 +47,9 @@ namespace {
   AbortIfCollapsed("dsgc-abort-if-collapsed", cl::Hidden, cl::CommaSeparated,
                    cl::desc("Abort if any of the named symbols is collapsed"));
   cl::list<std::string>
+  CheckFlags("dsgc-check-flags", cl::Hidden, cl::CommaSeparated,
+             cl::desc("Check that flags are specified for nodes"));
+  cl::list<std::string>
   AbortIfMerged("dsgc-abort-if-merged", cl::Hidden, cl::CommaSeparated,
              cl::desc("Abort if any of the named symbols are merged together"));
 
@@ -52,6 +66,7 @@ namespace {
       }
       AU.setPreservesAll();
     }
+    void print(std::ostream &O, const Module *M) const {}
 
   private:
     void verify(const DSGraph &G);
@@ -62,7 +77,7 @@ namespace {
 
 DSGC::DSGC() {
   if (!AbortIfAnyCollapsed && AbortIfCollapsed.empty() &&
-      AbortIfMerged.empty()) {
+      CheckFlags.empty() && AbortIfMerged.empty()) {
     std::cerr << "The -datastructure-gc is useless if you don't specify any"
                  " -dsgc-* options.  See the -help-hidden output for a list.\n";
     abort();
@@ -99,22 +114,47 @@ bool DSGC::runOnFunction(Function &F) {
 void DSGC::verify(const DSGraph &G) {
   // Loop over all of the nodes, checking to see if any are collapsed...
   if (AbortIfAnyCollapsed) {
-    const std::vector<DSNode*> &Nodes = G.getNodes();
-    for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-      if (Nodes[i]->isNodeCompletelyFolded()) {
+    for (DSGraph::node_iterator I = G.node_begin(), E = G.node_end(); I!=E; ++I)
+      if ((*I)->isNodeCompletelyFolded()) {
         std::cerr << "Node is collapsed: ";
-        Nodes[i]->print(std::cerr, &G);
+        (*I)->print(std::cerr, &G);
         abort();
       }
   }
 
-  if (!AbortIfCollapsed.empty() || !AbortIfMerged.empty()) {
+  if (!AbortIfCollapsed.empty() || !CheckFlags.empty() ||
+      !AbortIfMerged.empty()) {
     // Convert from a list to a set, because we don't have cl::set's yet.  FIXME
     std::set<std::string> AbortIfCollapsedS(AbortIfCollapsed.begin(),
                                             AbortIfCollapsed.end());
-    std::set<std::string> AbortIfMerged(AbortIfMerged.begin(),
-                                        AbortIfMerged.end());
+    std::set<std::string> AbortIfMergedS(AbortIfMerged.begin(),
+                                         AbortIfMerged.end());
+    std::map<std::string, unsigned> CheckFlagsM;
     
+    for (cl::list<std::string>::iterator I = CheckFlags.begin(),
+           E = CheckFlags.end(); I != E; ++I) {
+      std::string::size_type ColonPos = I->rfind(':');
+      if (ColonPos == std::string::npos) {
+        std::cerr << "Error: '" << *I
+               << "' is an invalid value for the --dsgc-check-flags option!\n";
+        abort();
+      }
+
+      unsigned Flags = 0;
+      for (unsigned C = ColonPos+1; C != I->size(); ++C)
+        switch ((*I)[C]) {
+        case 'S': Flags |= DSNode::AllocaNode;  break;
+        case 'H': Flags |= DSNode::HeapNode;    break;
+        case 'G': Flags |= DSNode::GlobalNode;  break;
+        case 'U': Flags |= DSNode::UnknownNode; break;
+        case 'I': Flags |= DSNode::Incomplete;  break;
+        case 'M': Flags |= DSNode::Modified;    break;
+        case 'R': Flags |= DSNode::Read;        break;
+        case 'A': Flags |= DSNode::Array;       break;
+        default: std::cerr << "Invalid DSNode flag!\n"; abort();
+        }
+      CheckFlagsM[std::string(I->begin(), I->begin()+ColonPos)] = Flags;
+    }
     
     // Now we loop over all of the scalars, checking to see if any are collapsed
     // that are not supposed to be, or if any are merged together.
@@ -124,26 +164,32 @@ void DSGC::verify(const DSGraph &G) {
     for (DSGraph::ScalarMapTy::const_iterator I = SM.begin(), E = SM.end();
          I != E; ++I)
       if (I->first->hasName() && I->second.getNode()) {
+        const std::string &Name = I->first->getName();
         DSNode *N = I->second.getNode();
         
         // Verify it is not collapsed if it is not supposed to be...
-        if (N->isNodeCompletelyFolded() &&
-            AbortIfCollapsedS.count(I->first->getName())) {
-          std::cerr << "Node for value '%" << I->first->getName()
-                    << "' is collapsed: ";
+        if (N->isNodeCompletelyFolded() && AbortIfCollapsedS.count(Name)) {
+          std::cerr << "Node for value '%" << Name << "' is collapsed: ";
+          N->print(std::cerr, &G);
+          abort();
+        }
+
+        if (CheckFlagsM.count(Name) && CheckFlagsM[Name] != N->getNodeFlags()) {
+          std::cerr << "Node flags are not as expected for node: " << Name
+                    << "\n";
           N->print(std::cerr, &G);
           abort();
         }
 
         // Verify that it is not merged if it is not supposed to be...
-        if (AbortIfMerged.count(I->first->getName())) {
+        if (AbortIfMergedS.count(Name)) {
           if (AbortIfMergedNodes.count(N)) {
-            std::cerr << "Nodes for values '%" << I->first->getName()
-                      << "' and '%" << AbortIfMergedNodes[N] << "' is merged: ";
+            std::cerr << "Nodes for values '%" << Name << "' and '%"
+                      << AbortIfMergedNodes[N] << "' is merged: ";
             N->print(std::cerr, &G);
             abort();
           }
-          AbortIfMergedNodes[N] = I->first->getName();
+          AbortIfMergedNodes[N] = Name;
         }
       }
   }