Fix name collision
[oota-llvm.git] / lib / Analysis / DataStructure / TopDownClosure.cpp
index 13535e3f8014bcc84a107794c255d5dedac8e09e..d30c441ce4f7e949d791adafa197c9373ac6a588 100644 (file)
@@ -1,4 +1,11 @@
 //===- TopDownClosure.cpp - Compute the top-down interprocedure closure ---===//
+// 
+//                     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 TDDataStructures class, which represents the
 // Top-down Interprocedural closure of the data structure graph over the
@@ -21,27 +28,59 @@ namespace {
   Statistic<> NumTDInlines("tddatastructures", "Number of graphs inlined");
 }
 
-/// FunctionHasCompleteArguments - This function returns true if it is safe not
-/// to mark arguments to the function complete.
-///
-/// FIXME: Need to check if all callers have been found, or rather if a
-/// funcpointer escapes!
-///
-static bool FunctionHasCompleteArguments(Function &F) {
-  return F.hasInternalLinkage();
+void TDDataStructures::markReachableFunctionsExternallyAccessible(DSNode *N,
+                                                   hash_set<DSNode*> &Visited) {
+  if (!N || Visited.count(N)) return;
+  Visited.insert(N);
+
+  for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) {
+    DSNodeHandle &NH = N->getLink(i*N->getPointerSize());
+    if (DSNode *NN = NH.getNode()) {
+      const std::vector<GlobalValue*> &Globals = NN->getGlobals();
+      for (unsigned G = 0, e = Globals.size(); G != e; ++G)
+        if (Function *F = dyn_cast<Function>(Globals[G]))
+          ArgsRemainIncomplete.insert(F);
+
+      markReachableFunctionsExternallyAccessible(NN, Visited);
+    }
+  }
 }
 
+
 // run - Calculate the top down data structure graphs for each function in the
 // program.
 //
 bool TDDataStructures::run(Module &M) {
   BUDataStructures &BU = getAnalysis<BUDataStructures>();
   GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
+  GlobalsGraph->setPrintAuxCalls();
 
   // Figure out which functions must not mark their arguments complete because
-  // they are accessible outside this compilation unit.
+  // they are accessible outside this compilation unit.  Currently, these
+  // arguments are functions which are reachable by global variables in the
+  // globals graph.
+  const DSGraph::ScalarMapTy &GGSM = GlobalsGraph->getScalarMap();
+  hash_set<DSNode*> Visited;
+  for (DSGraph::ScalarMapTy::const_iterator I = GGSM.begin(), E = GGSM.end();
+       I != E; ++I)
+    if (isa<GlobalValue>(I->first))
+      markReachableFunctionsExternallyAccessible(I->second.getNode(), Visited);
+
+  // Loop over unresolved call nodes.  Any functions passed into (but not
+  // returned!?) from unresolvable call nodes may be invoked outside of the
+  // current module.
+  const std::vector<DSCallSite> &Calls = GlobalsGraph->getAuxFunctionCalls();
+  for (unsigned i = 0, e = Calls.size(); i != e; ++i) {
+    const DSCallSite &CS = Calls[i];
+    for (unsigned arg = 0, e = CS.getNumPtrArgs(); arg != e; ++arg)
+      markReachableFunctionsExternallyAccessible(CS.getPtrArg(arg).getNode(),
+                                                 Visited);
+  }
+  Visited.clear();
+
+  // Functions without internal linkage also have unknown incoming arguments!
   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
-    if (!FunctionHasCompleteArguments(*I))
+    if (!I->isExternal() && !I->hasInternalLinkage())
       ArgsRemainIncomplete.insert(I);
 
   // We want to traverse the call graph in reverse post-order.  To do this, we