Make error messages more useful than jsut an abort
[oota-llvm.git] / lib / Analysis / DataStructure / BottomUpClosure.cpp
index 8fa331c92d1773330aa405efc0540f4a05daced8..0833a029129095c78b86978ee2150c5325635ef5 100644 (file)
@@ -22,6 +22,13 @@ namespace {
 
 using namespace DS;
 
+static bool isVAHackFn(const Function *F) {
+  return F->getName() == "printf"  || F->getName() == "sscanf" ||
+         F->getName() == "fprintf" || F->getName() == "open" ||
+         F->getName() == "sprintf" || F->getName() == "fputs" ||
+         F->getName() == "fscanf";
+}
+
 // isCompleteNode - Return true if we know all of the targets of this node, and
 // if the call sites are not external.
 //
@@ -29,14 +36,9 @@ static inline bool isCompleteNode(DSNode *N) {
   if (N->NodeType & DSNode::Incomplete) return false;
   const std::vector<GlobalValue*> &Callees = N->getGlobals();
   for (unsigned i = 0, e = Callees.size(); i != e; ++i)
-    if (Callees[i]->isExternal()) {
-      GlobalValue &FI = cast<Function>(*Callees[i]);
-      if (FI.getName() != "printf"  && FI.getName() != "sscanf" &&
-          FI.getName() != "fprintf" && FI.getName() != "open" &&
-          FI.getName() != "sprintf" && FI.getName() != "fputs" &&
-          FI.getName() != "fscanf")
+    if (Callees[i]->isExternal())
+      if (!isVAHackFn(cast<Function>(Callees[i])))
         return false;  // External function found...
-    }
   return true;  // otherwise ok
 }
 
@@ -48,7 +50,7 @@ struct CallSiteIterator {
 
   CallSiteIterator(std::vector<DSCallSite> &CS) : FCs(&CS) {
     CallSite = 0; CallSiteEntry = 0;
-    advanceToNextValid();
+    advanceToValidCallee();
   }
 
   // End iterator ctor...
@@ -56,18 +58,24 @@ struct CallSiteIterator {
     CallSite = FCs->size(); CallSiteEntry = 0;
   }
 
-  void advanceToNextValid() {
+  void advanceToValidCallee() {
     while (CallSite < FCs->size()) {
-      if (DSNode *CalleeNode = (*FCs)[CallSite].getCallee().getNode()) {
+      if ((*FCs)[CallSite].isDirectCall()) {
+        if (CallSiteEntry == 0 &&        // direct call only has one target...
+            (!(*FCs)[CallSite].getCalleeFunc()->isExternal() ||
+             isVAHackFn((*FCs)[CallSite].getCalleeFunc()))) // If not external
+          return;
+      } else {
+        DSNode *CalleeNode = (*FCs)[CallSite].getCalleeNode();
         if (CallSiteEntry || isCompleteNode(CalleeNode)) {
           const std::vector<GlobalValue*> &Callees = CalleeNode->getGlobals();
           
           if (CallSiteEntry < Callees.size())
             return;
         }
-        CallSiteEntry = 0;
-        ++CallSite;
       }
+      CallSiteEntry = 0;
+      ++CallSite;
     }
   }
 public:
@@ -87,14 +95,18 @@ public:
   unsigned getCallSiteIdx() const { return CallSite; }
   DSCallSite &getCallSite() const { return (*FCs)[CallSite]; }
 
-  Function* operator*() const {
-    DSNode *Node = (*FCs)[CallSite].getCallee().getNode();
-    return cast<Function>(Node->getGlobals()[CallSiteEntry]);
+  Function *operator*() const {
+    if ((*FCs)[CallSite].isDirectCall()) {
+      return (*FCs)[CallSite].getCalleeFunc();
+    } else {
+      DSNode *Node = (*FCs)[CallSite].getCalleeNode();
+      return cast<Function>(Node->getGlobals()[CallSiteEntry]);
+    }
   }
 
   CallSiteIterator& operator++() {                // Preincrement
     ++CallSiteEntry;
-    advanceToNextValid();
+    advanceToValidCallee();
     return *this;
   }
   CallSiteIterator operator++(int) { // Postincrement
@@ -109,6 +121,7 @@ public:
 //
 bool BUDataStructures::run(Module &M) {
   GlobalsGraph = new DSGraph();
+  GlobalsGraph->setPrintAuxCalls();
 
   Function *MainFunc = M.getMainFunction();
   if (MainFunc)
@@ -336,9 +349,10 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
       DSGraph &GI = getDSGraph(*Callee);  // Graph to inline
       
       DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
-            << " in: " << F.getName() << "[" << GI.getGraphSize() << "+"
-            << GI.getAuxFunctionCalls().size() << "]\n");
-
+            << "[" << GI.getGraphSize() << "+"
+            << GI.getAuxFunctionCalls().size() << "] into: " << F.getName()
+            << "[" << Graph.getGraphSize() << "+"
+            << Graph.getAuxFunctionCalls().size() << "]\n");
 #if 0
       Graph.writeGraphToFile(std::cerr, "bu_" + F.getName() + "_before_" +
                              Callee->getName());
@@ -366,6 +380,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
   // now that are complete, we must loop!
   Graph.maskIncompleteMarkers();
   Graph.markIncompleteNodes(DSGraph::MarkFormalArgs);
+  // FIXME: materialize nodes from the globals graph as neccesary...
   Graph.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
 
   DEBUG(std::cerr << "  [BU] Done inlining: " << F.getName() << " ["
@@ -420,10 +435,12 @@ DSGraph &BUDataStructures::inlineNonSCCGraphs(Function &F,
       // Get the data structure graph for the called function.
       //
       DSGraph &GI = getDSGraph(*Callee);  // Graph to inline
-      
+
       DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
-            << " in: " << F.getName() << "[" << GI.getGraphSize() << "+"
-            << GI.getAuxFunctionCalls().size() << "]\n");
+            << "[" << GI.getGraphSize() << "+"
+            << GI.getAuxFunctionCalls().size() << "] into: " << F.getName()
+            << "[" << Graph.getGraphSize() << "+"
+            << Graph.getAuxFunctionCalls().size() << "]\n");
 
       // Handle self recursion by resolving the arguments and return value
       Graph.mergeInGraph(CS, GI,
@@ -447,7 +464,7 @@ DSGraph &BUDataStructures::inlineNonSCCGraphs(Function &F,
   DEBUG(std::cerr << "  [BU] Done Non-SCC inlining: " << F.getName() << " ["
         << Graph.getGraphSize() << "+" << Graph.getAuxFunctionCalls().size()
         << "]\n");
-
+  //Graph.writeGraphToFile(std::cerr, "nscc_" + F.getName());
   return Graph;
 }
 
@@ -466,7 +483,7 @@ DSGraph &BUDataStructures::calculateSCCGraph(Function &F,
     // the new call site list and doesn't invalidate our iterators!
     std::vector<DSCallSite> TempFCs;
     TempFCs.swap(AuxCallsList);
-    
+
     // Loop over all of the resolvable call sites
     unsigned LastCallSiteIdx = ~0U;
     CallSiteIterator I = CallSiteIterator::begin(TempFCs),
@@ -505,10 +522,11 @@ DSGraph &BUDataStructures::calculateSCCGraph(Function &F,
         // Get the data structure graph for the called function.
         //
         DSGraph &GI = getDSGraph(*Callee);  // Graph to inline
-        
         DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
-              << " in: " << F.getName() << "[" << GI.getGraphSize() << "+"
-              << GI.getAuxFunctionCalls().size() << "]\n");
+              << "[" << GI.getGraphSize() << "+"
+              << GI.getAuxFunctionCalls().size() << "] into: " << F.getName()
+              << "[" << Graph.getGraphSize() << "+"
+              << Graph.getAuxFunctionCalls().size() << "]\n");
         
         // Handle self recursion by resolving the arguments and return value
         Graph.mergeInGraph(CS, GI,
@@ -537,12 +555,14 @@ DSGraph &BUDataStructures::calculateSCCGraph(Function &F,
   // now that are complete, we must loop!
   Graph.maskIncompleteMarkers();
   Graph.markIncompleteNodes(DSGraph::MarkFormalArgs);
+
+  // FIXME: materialize nodes from the globals graph as neccesary...
+
   Graph.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
 
   DEBUG(std::cerr << "  [BU] Done inlining: " << F.getName() << " ["
         << Graph.getGraphSize() << "+" << Graph.getAuxFunctionCalls().size()
         << "]\n");
   //Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
-
   return Graph;
 }