Be a bit more efficient when processing the active and inactive
[oota-llvm.git] / lib / Analysis / DataStructure / Local.cpp
index dea8e9f3601e8aa1f940fc5334bb155c8cd64ca2..34c56dc2ea709aceb7969b00514724128e73057d 100644 (file)
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Analysis/DataStructure.h"
-#include "llvm/Analysis/DSGraph.h"
+#include "llvm/Analysis/DataStructure/DataStructure.h"
+#include "llvm/Analysis/DataStructure/DSGraph.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
@@ -36,7 +36,7 @@ static RegisterAnalysis<LocalDataStructures>
 X("datastructure", "Local Data Structure Analysis");
 
 static cl::opt<bool>
-TrackIntegersAsPointers("dsa-track-integers",
+TrackIntegersAsPointers("dsa-track-integers", cl::Hidden,
          cl::desc("If this is set, track integers as potential pointers"));
 
 namespace llvm {
@@ -117,6 +117,8 @@ namespace {
     void visitInstruction(Instruction &I);
 
     void visitCallSite(CallSite CS);
+    void visitVANextInst(VANextInst &I);
+    void visitVAArgInst(VAArgInst   &I);
 
     void MergeConstantInitIntoNode(DSNodeHandle &NH, Constant *C);
   private:
@@ -128,6 +130,9 @@ namespace {
     DSNode *createNode(const Type *Ty = 0) {
       DSNode *N = new DSNode(Ty, &G);   // Create the node
       if (DisableFieldSensitivity) {
+        // Create node handle referring to the old node so that it is
+        // immediately removed from the graph when the node handle is destroyed.
+        DSNodeHandle OldNNH = N;
         N->foldNodeCompletely();
         if (DSNode *FN = N->getForwardNode())
           N = FN;
@@ -185,7 +190,7 @@ DSGraph::DSGraph(const TargetData &td, Function &F, DSGraph *GG)
     for (DSScalarMap::global_iterator I = ScalarMap.global_begin();
          I != ScalarMap.global_end(); ++I)
       if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
-        if (GV->isConstant())
+        if (!GV->isExternal() && GV->isConstant())
           RC.merge(ScalarMap[GV], GG->ScalarMap[GV]);
   }
 
@@ -214,10 +219,13 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
   // Otherwise we need to create a new node to point to.
   // Check first for constant expressions that must be traversed to
   // extract the actual value.
-  if (Constant *C = dyn_cast<Constant>(V))
-    if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
-      return NH = getValueDest(*CPR->getValue());
-    } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+  DSNode* N;
+  if (GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
+    // Create a new global node for this global variable...
+    N = createNode(GV->getType()->getElementType());
+    N->addGlobal(GV);
+  } else if (Constant *C = dyn_cast<Constant>(V)) {
+    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
       if (CE->getOpcode() == Instruction::Cast)
         NH = getValueDest(*CE->getOperand(0));
       else if (CE->getOpcode() == Instruction::GetElementPtr) {
@@ -241,20 +249,13 @@ DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
     } else {
       assert(0 && "Unknown constant type!");
     }
-
-  // Otherwise we need to create a new node to point to...
-  DSNode *N;
-  if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
-    // Create a new global node for this global variable...
-    N = createNode(GV->getType()->getElementType());
-    N->addGlobal(GV);
+    N = createNode(); // just create a shadow node
   } else {
     // Otherwise just create a shadow node
     N = createNode();
   }
 
-  NH.setNode(N);      // Remember that we are pointing to it...
-  NH.setOffset(0);
+  NH.setTo(N, 0);      // Remember that we are pointing to it...
   return NH;
 }
 
@@ -281,11 +282,7 @@ DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) {
 /// merge the two destinations together.
 ///
 void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) {
-  DSNodeHandle &AINH = ScalarMap[&V];
-  if (AINH.getNode() == 0)   // Not pointing to anything yet?
-    AINH = NH;               // Just point directly to NH
-  else
-    AINH.mergeWith(NH);
+  ScalarMap[&V].mergeWith(NH);
 }
 
 
@@ -352,7 +349,8 @@ void GraphBuilder::visitGetElementPtrInst(User &GEP) {
 #if 0
   // Handle the pointer index specially...
   if (GEP.getNumOperands() > 1 &&
-      GEP.getOperand(1) != ConstantSInt::getNullValue(Type::LongTy)) {
+      (!isa<Constant>(GEP.getOperand(1)) ||
+       !cast<Constant>(GEP.getOperand(1))->isNullValue())) {
 
     // If we already know this is an array being accessed, don't do anything...
     if (!TopTypeRec.isArray) {
@@ -442,7 +440,7 @@ void GraphBuilder::visitLoadInst(LoadInst &LI) {
 void GraphBuilder::visitStoreInst(StoreInst &SI) {
   const Type *StoredTy = SI.getOperand(0)->getType();
   DSNodeHandle Dest = getValueDest(*SI.getOperand(1));
-  if (Dest.getNode() == 0) return;
+  if (Dest.isNull()) return;
 
   // Mark that the node is written to...
   Dest.getNode()->setModifiedMarker();
@@ -460,6 +458,25 @@ void GraphBuilder::visitReturnInst(ReturnInst &RI) {
     RetNode->mergeWith(getValueDest(*RI.getOperand(0)));
 }
 
+void GraphBuilder::visitVANextInst(VANextInst &I) {
+  getValueDest(*I.getOperand(0)).mergeWith(getValueDest(I));
+}
+
+void GraphBuilder::visitVAArgInst(VAArgInst &I) {
+  DSNodeHandle Ptr = getValueDest(*I.getOperand(0));
+  if (Ptr.isNull()) return;
+
+  // Make that the node is read from.
+  Ptr.getNode()->setReadMarker();
+
+  // Ensure a typerecord exists...
+  Ptr.getNode()->mergeTypeInfo(I.getType(), Ptr.getOffset(), false);
+
+  if (isPointerType(I.getType()))
+    setDestTo(I, getLink(Ptr));
+}
+
+
 void GraphBuilder::visitCallInst(CallInst &CI) {
   visitCallSite(&CI);
 }
@@ -470,13 +487,20 @@ void GraphBuilder::visitInvokeInst(InvokeInst &II) {
 
 void GraphBuilder::visitCallSite(CallSite CS) {
   Value *Callee = CS.getCalledValue();
-  if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(Callee))
-    Callee = CPR->getValue();
 
   // Special case handling of certain libc allocation functions here.
   if (Function *F = dyn_cast<Function>(Callee))
     if (F->isExternal())
       switch (F->getIntrinsicID()) {
+      case Intrinsic::vastart:
+        getValueDest(*CS.getInstruction()).getNode()->setAllocaNodeMarker();
+        return;
+      case Intrinsic::vacopy:
+        getValueDest(*CS.getInstruction()).
+          mergeWith(getValueDest(**(CS.arg_begin())));
+        return;
+      case Intrinsic::vaend:
+        return;  // noop
       case Intrinsic::memmove:
       case Intrinsic::memcpy: {
         // Merge the first & second arguments, and mark the memory read and
@@ -493,7 +517,8 @@ void GraphBuilder::visitCallSite(CallSite CS) {
           N->setModifiedMarker();
         return;
       default:
-        if (F->getName() == "calloc") {
+        if (F->getName() == "calloc" || F->getName() == "posix_memalign" ||
+            F->getName() == "memalign" || F->getName() == "valloc") {
           setDestTo(*CS.getInstruction(),
                     createNode()->setHeapNodeMarker()->setModifiedMarker());
           return;
@@ -559,6 +584,24 @@ void GraphBuilder::visitCallSite(CallSite CS) {
             if (const PointerType *PTy = dyn_cast<PointerType>(StatTy))
               N->mergeTypeInfo(PTy->getElementType(), StatBuf.getOffset());
           }
+          return;
+        } else if (F->getName() == "strtod" || F->getName() == "strtof" ||
+                   F->getName() == "strtold") {
+          // These functions read the first pointer
+          if (DSNode *Str = getValueDest(**CS.arg_begin()).getNode()) {
+            Str->setReadMarker();
+            // If the second parameter is passed, it will point to the first
+            // argument node.
+            const DSNodeHandle &EndPtrNH = getValueDest(**(CS.arg_begin()+1));
+            if (DSNode *End = EndPtrNH.getNode()) {
+              End->mergeTypeInfo(PointerType::get(Type::SByteTy),
+                                 EndPtrNH.getOffset(), false);
+              End->setModifiedMarker();
+              DSNodeHandle &Link = getLink(EndPtrNH);
+              Link.mergeWith(getValueDest(**CS.arg_begin()));
+            }
+          }
+
           return;
         } else if (F->getName() == "fopen" || F->getName() == "fdopen" ||
                    F->getName() == "freopen") {
@@ -581,7 +624,8 @@ void GraphBuilder::visitCallSite(CallSite CS) {
 
           // If this is freopen, merge the file descriptor passed in with the
           // result.
-          Result.mergeWith(getValueDest(**--CS.arg_end()));
+          if (F->getName() == "freopen")
+            Result.mergeWith(getValueDest(**--CS.arg_end()));
 
           return;
         } else if (F->getName() == "fclose" && CS.arg_end()-CS.arg_begin() ==1){
@@ -721,6 +765,54 @@ void GraphBuilder::visitCallSite(CallSite CS) {
               if (DSNode *N = getValueDest(**AI).getNode())
                 N->setReadMarker();   
           }
+          return;
+        } else if (F->getName() == "vprintf" || F->getName() == "vfprintf" ||
+                   F->getName() == "vsprintf") {
+          CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
+
+          if (F->getName() == "vfprintf") {
+            // ffprintf reads and writes the FILE argument, and applies the type
+            // to it.
+            DSNodeHandle H = getValueDest(**AI);
+            if (DSNode *N = H.getNode()) {
+              N->setModifiedMarker()->setReadMarker();
+              const Type *ArgTy = (*AI)->getType();
+              if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
+                N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
+            }
+            ++AI;
+          } else if (F->getName() == "vsprintf") {
+            // vsprintf writes the first string argument.
+            DSNodeHandle H = getValueDest(**AI++);
+            if (DSNode *N = H.getNode()) {
+              N->setModifiedMarker();
+              const Type *ArgTy = (*AI)->getType();
+              if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
+                N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
+            }
+          }
+
+          // Read the format
+          if (AI != E) {
+            if (isPointerType((*AI)->getType()))
+              if (DSNode *N = getValueDest(**AI).getNode())
+                N->setReadMarker();
+            ++AI;
+          }
+          
+          // Read the valist, and the pointed-to objects.
+          if (AI != E && isPointerType((*AI)->getType())) {
+            const DSNodeHandle &VAList = getValueDest(**AI);
+            if (DSNode *N = VAList.getNode()) {
+              N->setReadMarker();
+              N->mergeTypeInfo(PointerType::get(Type::SByteTy),
+                               VAList.getOffset(), false);
+
+              DSNodeHandle &VAListObjs = getLink(VAList);
+              VAListObjs.getNode()->setReadMarker();
+            }
+          }
+
           return;
         } else if (F->getName() == "scanf" || F->getName() == "fscanf" ||
                    F->getName() == "sscanf") {