Add special case handling for calloc and realloc
[oota-llvm.git] / lib / Analysis / DataStructure / Local.cpp
index 27d5ce563aa70300554d3514a145102e97ee832b..43edb18433bb1a0b03b4cb22752632b899d12cde 100644 (file)
@@ -7,19 +7,16 @@
 
 #include "llvm/Analysis/DataStructure.h"
 #include "llvm/Analysis/DSGraph.h"
-#include "llvm/iMemory.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iOther.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
 #include "llvm/GlobalVariable.h"
+#include "llvm/Instructions.h"
 #include "llvm/Support/InstVisitor.h"
 #include "llvm/Target/TargetData.h"
-#include "Support/Statistic.h"
-#include "Support/Timer.h"
 #include "Support/CommandLine.h"
+#include "Support/Debug.h"
+#include "Support/Timer.h"
 
 // FIXME: This should eventually be a FunctionPass that is automatically
 // aggregated into a Pass.
@@ -64,16 +61,14 @@ namespace {
   class GraphBuilder : InstVisitor<GraphBuilder> {
     Function &F;
     DSGraph &G;
-    std::vector<DSNode*> &Nodes;
     DSNodeHandle &RetNode;               // Node that gets returned...
     DSGraph::ScalarMapTy &ScalarMap;
     std::vector<DSCallSite> &FunctionCalls;
 
   public:
-    GraphBuilder(Function &f, DSGraph &g, std::vector<DSNode*> &nodes,
-                 DSNodeHandle &retNode, DSGraph::ScalarMapTy &SM,
-                 std::vector<DSCallSite> &fc)
-      : F(f), G(g), Nodes(nodes), RetNode(retNode), ScalarMap(SM),
+    GraphBuilder(Function &f, DSGraph &g, DSNodeHandle &retNode, 
+                 DSGraph::ScalarMapTy &SM, std::vector<DSCallSite> &fc)
+      : F(f), G(g), RetNode(retNode), ScalarMap(SM),
         FunctionCalls(fc) {
 
       // Create scalar nodes for all pointer arguments...
@@ -98,11 +93,13 @@ namespace {
     void visitLoadInst(LoadInst &LI);
     void visitStoreInst(StoreInst &SI);
     void visitCallInst(CallInst &CI);
+    void visitInvokeInst(InvokeInst &II);
     void visitSetCondInst(SetCondInst &SCI) {}  // SetEQ & friends are ignored
     void visitFreeInst(FreeInst &FI);
     void visitCastInst(CastInst &CI);
     void visitInstruction(Instruction &I);
 
+    void visitCallSite(CallSite CS);
   private:
     // Helper functions used to implement the visitation functions...
 
@@ -142,8 +139,11 @@ namespace {
 // graph.
 DSGraph::DSGraph(Function &F, DSGraph *GG) : GlobalsGraph(GG) {
   PrintAuxCalls = false;
+
+  DEBUG(std::cerr << "  [Loc] Calculating graph for: " << F.getName() << "\n");
+
   // Use the graph builder to construct the local version of the graph
-  GraphBuilder B(F, *this, Nodes, ReturnNodes[&F], ScalarMap, FunctionCalls);
+  GraphBuilder B(F, *this, ReturnNodes[&F], ScalarMap, FunctionCalls);
 #ifndef NDEBUG
   Timer::addPeakMemoryMeasurement();
 #endif
@@ -346,7 +346,7 @@ void GraphBuilder::visitGetElementPtrInst(User &GEP) {
           unsigned RawOffset = Offset+Value.getOffset();
 
           // Loop over all of the elements of the array, merging them into the
-          // zero'th element.
+          // zeroth element.
           for (unsigned i = 1, e = ATy->getNumElements(); i != e; ++i)
             // Merge all of the byte components of this array element
             for (unsigned j = 0; j != ElSize; ++j)
@@ -404,29 +404,54 @@ void GraphBuilder::visitReturnInst(ReturnInst &RI) {
 }
 
 void GraphBuilder::visitCallInst(CallInst &CI) {
+  visitCallSite(&CI);
+}
+
+void GraphBuilder::visitInvokeInst(InvokeInst &II) {
+  visitCallSite(&II);
+}
+
+void GraphBuilder::visitCallSite(CallSite CS) {
+  // Special case handling of certain libc allocation functions here.
+  if (Function *F = CS.getCalledFunction())
+    if (F->isExternal())
+      if (F->getName() == "calloc") {
+        setDestTo(*CS.getInstruction(),
+                  createNode()->setHeapNodeMarker()->setModifiedMarker());
+        return;
+      } else if (F->getName() == "realloc") {
+        DSNodeHandle RetNH = getValueDest(*CS.getInstruction());
+        RetNH.mergeWith(getValueDest(**CS.arg_begin()));
+        DSNode *N = RetNH.getNode();
+        if (N) N->setHeapNodeMarker()->setModifiedMarker()->setReadMarker();
+        return;
+      }
+
+
   // Set up the return value...
   DSNodeHandle RetVal;
-  if (isPointerType(CI.getType()))
-    RetVal = getValueDest(CI);
+  Instruction *I = CS.getInstruction();
+  if (isPointerType(I->getType()))
+    RetVal = getValueDest(*I);
 
   DSNode *Callee = 0;
-  if (DisableDirectCallOpt || !isa<Function>(CI.getOperand(0)))
-    Callee = getValueDest(*CI.getOperand(0)).getNode();
+  if (DisableDirectCallOpt || !isa<Function>(CS.getCalledValue()))
+    Callee = getValueDest(*CS.getCalledValue()).getNode();
 
   std::vector<DSNodeHandle> Args;
-  Args.reserve(CI.getNumOperands()-1);
+  Args.reserve(CS.arg_end()-CS.arg_begin());
 
   // Calculate the arguments vector...
-  for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
-    if (isPointerType(CI.getOperand(i)->getType()))
-      Args.push_back(getValueDest(*CI.getOperand(i)));
+  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
+    if (isPointerType((*I)->getType()))
+      Args.push_back(getValueDest(**I));
 
   // Add a new function call entry...
   if (Callee)
-    FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args));
+    FunctionCalls.push_back(DSCallSite(CS, RetVal, Callee, Args));
   else
-    FunctionCalls.push_back(DSCallSite(CI, RetVal,
-                                       cast<Function>(CI.getOperand(0)), Args));
+    FunctionCalls.push_back(DSCallSite(CS, RetVal, CS.getCalledFunction(),
+                                       Args));
 }
 
 void GraphBuilder::visitFreeInst(FreeInst &FI) {