//===- Local.cpp - Compute a local data structure graph for a function ----===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// Compute the local version of the data structure graph for a function.  The
// external interface to this file is the DSGraph constructor.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Timer.h"

// FIXME: This should eventually be a FunctionPass that is automatically
// aggregated into a Pass.
//
#include "llvm/Module.h"

using namespace llvm;

static RegisterAnalysis<LocalDataStructures>
X("datastructure", "Local Data Structure Analysis");

static cl::opt<bool>
TrackIntegersAsPointers("dsa-track-integers", cl::Hidden,
         cl::desc("If this is set, track integers as potential pointers"));

namespace llvm {
namespace DS {
  // isPointerType - Return true if this type is big enough to hold a pointer.
  bool isPointerType(const Type *Ty) {
    if (isa<PointerType>(Ty))
      return true;
    else if (TrackIntegersAsPointers && Ty->isPrimitiveType() &&Ty->isInteger())
      return Ty->getPrimitiveSize() >= PointerSize;
    return false;
  }
}}

using namespace DS;

namespace {
  cl::opt<bool>
  DisableDirectCallOpt("disable-direct-call-dsopt", cl::Hidden,
                       cl::desc("Disable direct call optimization in "
                                "DSGraph construction"));
  cl::opt<bool>
  DisableFieldSensitivity("disable-ds-field-sensitivity", cl::Hidden,
                          cl::desc("Disable field sensitivity in DSGraphs"));

  //===--------------------------------------------------------------------===//
  //  GraphBuilder Class
  //===--------------------------------------------------------------------===//
  //
  /// This class is the builder class that constructs the local data structure
  /// graph by performing a single pass over the function in question.
  ///
  class GraphBuilder : InstVisitor<GraphBuilder> {
    DSGraph &G;
    DSNodeHandle *RetNode;               // Node that gets returned...
    DSScalarMap &ScalarMap;
    std::list<DSCallSite> *FunctionCalls;

  public:
    GraphBuilder(Function &f, DSGraph &g, DSNodeHandle &retNode,
                 std::list<DSCallSite> &fc)
      : G(g), RetNode(&retNode), ScalarMap(G.getScalarMap()),
        FunctionCalls(&fc) {

      // Create scalar nodes for all pointer arguments...
      for (Function::arg_iterator I = f.arg_begin(), E = f.arg_end();
           I != E; ++I)
        if (isPointerType(I->getType()))
          getValueDest(*I);

      visit(f);  // Single pass over the function
    }

    // GraphBuilder ctor for working on the globals graph
    GraphBuilder(DSGraph &g)
      : G(g), RetNode(0), ScalarMap(G.getScalarMap()), FunctionCalls(0) {
    }

    void mergeInGlobalInitializer(GlobalVariable *GV);

  private:
    // Visitor functions, used to handle each instruction type we encounter...
    friend class InstVisitor<GraphBuilder>;
    void visitMallocInst(MallocInst &MI) { handleAlloc(MI, true); }
    void visitAllocaInst(AllocaInst &AI) { handleAlloc(AI, false); }
    void handleAlloc(AllocationInst &AI, bool isHeap);

    void visitPHINode(PHINode &PN);
    void visitSelectInst(SelectInst &SI);

    void visitGetElementPtrInst(User &GEP);
    void visitReturnInst(ReturnInst &RI);
    void visitLoadInst(LoadInst &LI);
    void visitStoreInst(StoreInst &SI);
    void visitCallInst(CallInst &CI);
    void visitInvokeInst(InvokeInst &II);
    void visitSetCondInst(SetCondInst &SCI);
    void visitFreeInst(FreeInst &FI);
    void visitCastInst(CastInst &CI);
    void visitInstruction(Instruction &I);

    void visitCallSite(CallSite CS);
    void visitVANextInst(VANextInst &I);
    void visitVAArgInst(VAArgInst   &I);

    void MergeConstantInitIntoNode(DSNodeHandle &NH, Constant *C);
  private:
    // Helper functions used to implement the visitation functions...

    /// createNode - Create a new DSNode, ensuring that it is properly added to
    /// the graph.
    ///
    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;
      }
      return N;
    }

    /// setDestTo - Set the ScalarMap entry for the specified value to point to
    /// the specified destination.  If the Value already points to a node, make
    /// sure to merge the two destinations together.
    ///
    void setDestTo(Value &V, const DSNodeHandle &NH);

    /// getValueDest - Return the DSNode that the actual value points to.
    ///
    DSNodeHandle getValueDest(Value &V);

    /// getLink - This method is used to return the specified link in the
    /// specified node if one exists.  If a link does not already exist (it's
    /// null), then we create a new node, link it, then return it.
    ///
    DSNodeHandle &getLink(const DSNodeHandle &Node, unsigned Link = 0);
  };
}

using namespace DS;

//===----------------------------------------------------------------------===//
// DSGraph constructor - Simply use the GraphBuilder to construct the local
// graph.
DSGraph::DSGraph(EquivalenceClasses<GlobalValue*> &ECs, const TargetData &td,
                 Function &F, DSGraph *GG)
  : GlobalsGraph(GG), ScalarMap(ECs), TD(td) {
  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, ReturnNodes[&F], FunctionCalls);
#ifndef NDEBUG
  Timer::addPeakMemoryMeasurement();
#endif

  // If there are any constant globals referenced in this function, merge their
  // initializers into the local graph from the globals graph.
  if (ScalarMap.global_begin() != ScalarMap.global_end()) {
    ReachabilityCloner RC(*this, *GG, 0);

    for (DSScalarMap::global_iterator I = ScalarMap.global_begin();
         I != ScalarMap.global_end(); ++I)
      if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
        if (!GV->isExternal() && GV->isConstant())
          RC.merge(ScalarMap[GV], GG->ScalarMap[GV]);
  }

  markIncompleteNodes(DSGraph::MarkFormalArgs);

  // Remove any nodes made dead due to merging...
  removeDeadNodes(DSGraph::KeepUnreachableGlobals);
}


//===----------------------------------------------------------------------===//
// Helper method implementations...
//

/// getValueDest - Return the DSNode that the actual value points to.
///
DSNodeHandle GraphBuilder::getValueDest(Value &Val) {
  Value *V = &Val;
  if (isa<Constant>(V) && cast<Constant>(V)->isNullValue())
    return 0;  // Null doesn't point to anything, don't add to ScalarMap!

  DSNodeHandle &NH = ScalarMap[V];
  if (!NH.isNull())
    return NH;     // Already have a node?  Just return it...

  // 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.
  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) {
        if (isa<PointerType>(CE->getOperand(0)->getType()))
          NH = getValueDest(*CE->getOperand(0));
        else
          NH = createNode()->setUnknownNodeMarker();
      } else if (CE->getOpcode() == Instruction::GetElementPtr) {
        visitGetElementPtrInst(*CE);
        DSScalarMap::iterator I = ScalarMap.find(CE);
        assert(I != ScalarMap.end() && "GEP didn't get processed right?");
        NH = I->second;
      } else {
        // This returns a conservative unknown node for any unhandled ConstExpr
        return NH = createNode()->setUnknownNodeMarker();
      }
      if (NH.isNull()) {  // (getelementptr null, X) returns null
        ScalarMap.erase(V);
        return 0;
      }
      return NH;
    } else if (isa<UndefValue>(C)) {
      ScalarMap.erase(V);
      return 0;
    } else {
      assert(0 && "Unknown constant type!");
    }
    N = createNode(); // just create a shadow node
  } else {
    // Otherwise just create a shadow node
    N = createNode();
  }

  NH.setTo(N, 0);      // Remember that we are pointing to it...
  return NH;
}


/// getLink - This method is used to return the specified link in the
/// specified node if one exists.  If a link does not already exist (it's
/// null), then we create a new node, link it, then return it.  We must
/// specify the type of the Node field we are accessing so that we know what
/// type should be linked to if we need to create a new node.
///
DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) {
  DSNodeHandle &Node = const_cast<DSNodeHandle&>(node);
  DSNodeHandle &Link = Node.getLink(LinkNo);
  if (Link.isNull()) {
    // If the link hasn't been created yet, make and return a new shadow node
    Link = createNode();
  }
  return Link;
}


/// setDestTo - Set the ScalarMap entry for the specified value to point to the
/// specified destination.  If the Value already points to a node, make sure to
/// merge the two destinations together.
///
void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) {
  ScalarMap[&V].mergeWith(NH);
}


//===----------------------------------------------------------------------===//
// Specific instruction type handler implementations...
//

/// Alloca & Malloc instruction implementation - Simply create a new memory
/// object, pointing the scalar to it.
///
void GraphBuilder::handleAlloc(AllocationInst &AI, bool isHeap) {
  DSNode *N = createNode();
  if (isHeap)
    N->setHeapNodeMarker();
  else
    N->setAllocaNodeMarker();
  setDestTo(AI, N);
}

// PHINode - Make the scalar for the PHI node point to all of the things the
// incoming values point to... which effectively causes them to be merged.
//
void GraphBuilder::visitPHINode(PHINode &PN) {
  if (!isPointerType(PN.getType())) return; // Only pointer PHIs

  DSNodeHandle &PNDest = ScalarMap[&PN];
  for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
    PNDest.mergeWith(getValueDest(*PN.getIncomingValue(i)));
}

void GraphBuilder::visitSelectInst(SelectInst &SI) {
  if (!isPointerType(SI.getType())) return; // Only pointer Selects

  DSNodeHandle &Dest = ScalarMap[&SI];
  Dest.mergeWith(getValueDest(*SI.getOperand(1)));
  Dest.mergeWith(getValueDest(*SI.getOperand(2)));
}

void GraphBuilder::visitSetCondInst(SetCondInst &SCI) {
  if (!isPointerType(SCI.getOperand(0)->getType()) ||
      isa<ConstantPointerNull>(SCI.getOperand(1))) return; // Only pointers
  ScalarMap[SCI.getOperand(0)].mergeWith(getValueDest(*SCI.getOperand(1)));
}


void GraphBuilder::visitGetElementPtrInst(User &GEP) {
  DSNodeHandle Value = getValueDest(*GEP.getOperand(0));
  if (Value.isNull())
    Value = createNode();

  // As a special case, if all of the index operands of GEP are constant zeros,
  // handle this just like we handle casts (ie, don't do much).
  bool AllZeros = true;
  for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i)
    if (GEP.getOperand(i) !=
           Constant::getNullValue(GEP.getOperand(i)->getType())) {
      AllZeros = false;
      break;
    }

  // If all of the indices are zero, the result points to the operand without
  // applying the type.
  if (AllZeros || (!Value.isNull() &&
                   Value.getNode()->isNodeCompletelyFolded())) {
    setDestTo(GEP, Value);
    return;
  }


  const PointerType *PTy = cast<PointerType>(GEP.getOperand(0)->getType());
  const Type *CurTy = PTy->getElementType();

  if (Value.getNode()->mergeTypeInfo(CurTy, Value.getOffset())) {
    // If the node had to be folded... exit quickly
    setDestTo(GEP, Value);  // GEP result points to folded node
    return;
  }

  const TargetData &TD = Value.getNode()->getTargetData();

#if 0
  // Handle the pointer index specially...
  if (GEP.getNumOperands() > 1 &&
      (!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) {
      TopTypeRec.isArray = true;

      // If we are treating some inner field pointer as an array, fold the node
      // up because we cannot handle it right.  This can come because of
      // something like this:  &((&Pt->X)[1]) == &Pt->Y
      //
      if (Value.getOffset()) {
        // Value is now the pointer we want to GEP to be...
        Value.getNode()->foldNodeCompletely();
        setDestTo(GEP, Value);  // GEP result points to folded node
        return;
      } else {
        // This is a pointer to the first byte of the node.  Make sure that we
        // are pointing to the outter most type in the node.
        // FIXME: We need to check one more case here...
      }
    }
  }
#endif

  // All of these subscripts are indexing INTO the elements we have...
  unsigned Offset = 0;
  for (gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP);
       I != E; ++I)
    if (const StructType *STy = dyn_cast<StructType>(*I)) {
      unsigned FieldNo =
           (unsigned)cast<ConstantUInt>(I.getOperand())->getValue();
      Offset += (unsigned)TD.getStructLayout(STy)->MemberOffsets[FieldNo];
    } else if (const PointerType *PTy = dyn_cast<PointerType>(*I)) {
      if (!isa<Constant>(I.getOperand()) ||
          !cast<Constant>(I.getOperand())->isNullValue())
        Value.getNode()->setArrayMarker();
    }


#if 0
    if (const SequentialType *STy = cast<SequentialType>(*I)) {
      CurTy = STy->getElementType();
      if (ConstantSInt *CS = dyn_cast<ConstantSInt>(GEP.getOperand(i))) {
        Offset += CS->getValue()*TD.getTypeSize(CurTy);
      } else {
        // Variable index into a node.  We must merge all of the elements of the
        // sequential type here.
        if (isa<PointerType>(STy))
          std::cerr << "Pointer indexing not handled yet!\n";
        else {
          const ArrayType *ATy = cast<ArrayType>(STy);
          unsigned ElSize = TD.getTypeSize(CurTy);
          DSNode *N = Value.getNode();
          assert(N && "Value must have a node!");
          unsigned RawOffset = Offset+Value.getOffset();

          // Loop over all of the elements of the array, merging them into the
          // 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)
              N->mergeIndexes(RawOffset+j, RawOffset+i*ElSize+j);
        }
      }
    }
#endif

  // Add in the offset calculated...
  Value.setOffset(Value.getOffset()+Offset);

  // Value is now the pointer we want to GEP to be...
  setDestTo(GEP, Value);
}

void GraphBuilder::visitLoadInst(LoadInst &LI) {
  DSNodeHandle Ptr = getValueDest(*LI.getOperand(0));
  if (Ptr.isNull())
    Ptr = createNode();

  // Make that the node is read from...
  Ptr.getNode()->setReadMarker();

  // Ensure a typerecord exists...
  Ptr.getNode()->mergeTypeInfo(LI.getType(), Ptr.getOffset(), false);

  if (isPointerType(LI.getType()))
    setDestTo(LI, getLink(Ptr));
}

void GraphBuilder::visitStoreInst(StoreInst &SI) {
  const Type *StoredTy = SI.getOperand(0)->getType();
  DSNodeHandle Dest = getValueDest(*SI.getOperand(1));
  if (Dest.isNull()) return;

  // Mark that the node is written to...
  Dest.getNode()->setModifiedMarker();

  // Ensure a type-record exists...
  Dest.getNode()->mergeTypeInfo(StoredTy, Dest.getOffset());

  // Avoid adding edges from null, or processing non-"pointer" stores
  if (isPointerType(StoredTy))
    Dest.addEdgeTo(getValueDest(*SI.getOperand(0)));
}

void GraphBuilder::visitReturnInst(ReturnInst &RI) {
  if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType()))
    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 type record exists.
  DSNode *PtrN = Ptr.getNode();
  PtrN->mergeTypeInfo(I.getType(), Ptr.getOffset(), false);

  if (isPointerType(I.getType()))
    setDestTo(I, getLink(Ptr));
}


void GraphBuilder::visitCallInst(CallInst &CI) {
  visitCallSite(&CI);
}

void GraphBuilder::visitInvokeInst(InvokeInst &II) {
  visitCallSite(&II);
}

void GraphBuilder::visitCallSite(CallSite CS) {
  Value *Callee = CS.getCalledValue();

  // 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
        // modified.
        DSNodeHandle RetNH = getValueDest(**CS.arg_begin());
        RetNH.mergeWith(getValueDest(**(CS.arg_begin()+1)));
        if (DSNode *N = RetNH.getNode())
          N->setModifiedMarker()->setReadMarker();
        return;
      }
      case Intrinsic::memset:
        // Mark the memory modified.
        if (DSNode *N = getValueDest(**CS.arg_begin()).getNode())
          N->setModifiedMarker();
        return;
      default:
        if (F->getName() == "calloc" || F->getName() == "posix_memalign" ||
            F->getName() == "memalign" || F->getName() == "valloc") {
          setDestTo(*CS.getInstruction(),
                    createNode()->setHeapNodeMarker()->setModifiedMarker());
          return;
        } else if (F->getName() == "realloc") {
          DSNodeHandle RetNH = getValueDest(*CS.getInstruction());
          if (CS.arg_begin() != CS.arg_end())
            RetNH.mergeWith(getValueDest(**CS.arg_begin()));
          if (DSNode *N = RetNH.getNode())
            N->setHeapNodeMarker()->setModifiedMarker()->setReadMarker();
          return;
        } else if (F->getName() == "memmove") {
          // Merge the first & second arguments, and mark the memory read and
          // modified.
          DSNodeHandle RetNH = getValueDest(**CS.arg_begin());
          RetNH.mergeWith(getValueDest(**(CS.arg_begin()+1)));
          if (DSNode *N = RetNH.getNode())
            N->setModifiedMarker()->setReadMarker();
          return;

        } else if (F->getName() == "atoi" || F->getName() == "atof" ||
                   F->getName() == "atol" || F->getName() == "atoll" ||
                   F->getName() == "remove" || F->getName() == "unlink" ||
                   F->getName() == "rename" || F->getName() == "memcmp" ||
                   F->getName() == "strcmp" || F->getName() == "strncmp" ||
                   F->getName() == "execl" || F->getName() == "execlp" ||
                   F->getName() == "execle" || F->getName() == "execv" ||
                   F->getName() == "execvp" || F->getName() == "chmod" ||
                   F->getName() == "puts" || F->getName() == "write" ||
                   F->getName() == "open" || F->getName() == "create" ||
                   F->getName() == "truncate" || F->getName() == "chdir" ||
                   F->getName() == "mkdir" || F->getName() == "rmdir") {
          // These functions read all of their pointer operands.
          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI) {
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setReadMarker();
          }
          return;
        } else if (F->getName() == "read" || F->getName() == "pipe" ||
                   F->getName() == "wait" || F->getName() == "time") {
          // These functions write all of their pointer operands.
          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI) {
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setModifiedMarker();
          }
          return;
        } else if (F->getName() == "stat" || F->getName() == "fstat" ||
                   F->getName() == "lstat") {
          // These functions read their first operand if its a pointer.
          CallSite::arg_iterator AI = CS.arg_begin();
          if (isPointerType((*AI)->getType())) {
            DSNodeHandle Path = getValueDest(**AI);
            if (DSNode *N = Path.getNode()) N->setReadMarker();
          }

          // Then they write into the stat buffer.
          DSNodeHandle StatBuf = getValueDest(**++AI);
          if (DSNode *N = StatBuf.getNode()) {
            N->setModifiedMarker();
            const Type *StatTy = F->getFunctionType()->getParamType(1);
            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") {
          // These functions read all of their pointer operands.
          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI)
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setReadMarker();

          // fopen allocates in an unknown way and writes to the file
          // descriptor.  Also, merge the allocated type into the node.
          DSNodeHandle Result = getValueDest(*CS.getInstruction());
          if (DSNode *N = Result.getNode()) {
            N->setModifiedMarker()->setUnknownNodeMarker();
            const Type *RetTy = F->getFunctionType()->getReturnType();
            if (const PointerType *PTy = dyn_cast<PointerType>(RetTy))
              N->mergeTypeInfo(PTy->getElementType(), Result.getOffset());
          }

          // If this is freopen, merge the file descriptor passed in with the
          // result.
          if (F->getName() == "freopen") {
            // ICC doesn't handle getting the iterator, decrementing and
            // dereferencing it in one operation without error. Do it in 2 steps
            CallSite::arg_iterator compit = CS.arg_end();
            Result.mergeWith(getValueDest(**--compit));
          }
          return;
        } else if (F->getName() == "fclose" && CS.arg_end()-CS.arg_begin() ==1){
          // fclose reads and deallocates the memory in an unknown way for the
          // file descriptor.  It merges the FILE type into the descriptor.
          DSNodeHandle H = getValueDest(**CS.arg_begin());
          if (DSNode *N = H.getNode()) {
            N->setReadMarker()->setUnknownNodeMarker();
            const Type *ArgTy = F->getFunctionType()->getParamType(0);
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }
          return;
        } else if (CS.arg_end()-CS.arg_begin() == 1 &&
                   (F->getName() == "fflush" || F->getName() == "feof" ||
                    F->getName() == "fileno" || F->getName() == "clearerr" ||
                    F->getName() == "rewind" || F->getName() == "ftell" ||
                    F->getName() == "ferror" || F->getName() == "fgetc" ||
                    F->getName() == "fgetc" || F->getName() == "_IO_getc")) {
          // fflush reads and writes the memory for the file descriptor.  It
          // merges the FILE type into the descriptor.
          DSNodeHandle H = getValueDest(**CS.arg_begin());
          if (DSNode *N = H.getNode()) {
            N->setReadMarker()->setModifiedMarker();

            const Type *ArgTy = F->getFunctionType()->getParamType(0);
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }
          return;
        } else if (CS.arg_end()-CS.arg_begin() == 4 &&
                   (F->getName() == "fwrite" || F->getName() == "fread")) {
          // fread writes the first operand, fwrite reads it.  They both
          // read/write the FILE descriptor, and merges the FILE type.
          CallSite::arg_iterator compit = CS.arg_end();
          DSNodeHandle H = getValueDest(**--compit);
          if (DSNode *N = H.getNode()) {
            N->setReadMarker()->setModifiedMarker();
            const Type *ArgTy = F->getFunctionType()->getParamType(3);
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }

          H = getValueDest(**CS.arg_begin());
          if (DSNode *N = H.getNode())
            if (F->getName() == "fwrite")
              N->setReadMarker();
            else
              N->setModifiedMarker();
          return;
        } else if (F->getName() == "fgets" && CS.arg_end()-CS.arg_begin() == 3){
          // fgets reads and writes the memory for the file descriptor.  It
          // merges the FILE type into the descriptor, and writes to the
          // argument.  It returns the argument as well.
          CallSite::arg_iterator AI = CS.arg_begin();
          DSNodeHandle H = getValueDest(**AI);
          if (DSNode *N = H.getNode())
            N->setModifiedMarker();                        // Writes buffer
          H.mergeWith(getValueDest(*CS.getInstruction())); // Returns buffer
          ++AI; ++AI;

          // Reads and writes file descriptor, merge in FILE type.
          H = getValueDest(**AI);
          if (DSNode *N = H.getNode()) {
            N->setReadMarker()->setModifiedMarker();
            const Type *ArgTy = F->getFunctionType()->getParamType(2);
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }
          return;
        } else if (F->getName() == "ungetc" || F->getName() == "fputc" ||
                   F->getName() == "fputs" || F->getName() == "putc" ||
                   F->getName() == "ftell" || F->getName() == "rewind" ||
                   F->getName() == "_IO_putc") {
          // These functions read and write the memory for the file descriptor,
          // which is passes as the last argument.
          CallSite::arg_iterator compit = CS.arg_end();
          DSNodeHandle H = getValueDest(**--compit);
          if (DSNode *N = H.getNode()) {
            N->setReadMarker()->setModifiedMarker();
            FunctionType::param_iterator compit2 = F->getFunctionType()->param_end();
            const Type *ArgTy = *--compit2;
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }

          // Any pointer arguments are read.
          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI)
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setReadMarker();
          return;
        } else if (F->getName() == "fseek" || F->getName() == "fgetpos" ||
                   F->getName() == "fsetpos") {
          // These functions read and write the memory for the file descriptor,
          // and read/write all other arguments.
          DSNodeHandle H = getValueDest(**CS.arg_begin());
          if (DSNode *N = H.getNode()) {
            FunctionType::param_iterator compit2 = F->getFunctionType()->param_end();
            const Type *ArgTy = *--compit2;
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }

          // Any pointer arguments are read.
          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI)
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setReadMarker()->setModifiedMarker();
          return;
        } else if (F->getName() == "printf" || F->getName() == "fprintf" ||
                   F->getName() == "sprintf") {
          CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();

          if (F->getName() == "fprintf") {
            // fprintf reads and writes the FILE argument, and applies the type
            // to it.
            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());
            }
          } else if (F->getName() == "sprintf") {
            // sprintf 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());
            }
          }

          for (; AI != E; ++AI) {
            // printf reads all pointer arguments.
            if (isPointerType((*AI)->getType()))
              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") {
          CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();

          if (F->getName() == "fscanf") {
            // fscanf reads and writes the FILE argument, and applies the type
            // to it.
            DSNodeHandle H = getValueDest(**AI);
            if (DSNode *N = H.getNode()) {
              N->setReadMarker();
              const Type *ArgTy = (*AI)->getType();
              if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
                N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
            }
          } else if (F->getName() == "sscanf") {
            // sscanf reads the first string argument.
            DSNodeHandle H = getValueDest(**AI++);
            if (DSNode *N = H.getNode()) {
              N->setReadMarker();
              const Type *ArgTy = (*AI)->getType();
              if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
                N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
            }
          }

          for (; AI != E; ++AI) {
            // scanf writes all pointer arguments.
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setModifiedMarker();
          }
          return;
        } else if (F->getName() == "strtok") {
          // strtok reads and writes the first argument, returning it.  It reads
          // its second arg.  FIXME: strtok also modifies some hidden static
          // data.  Someday this might matter.
          CallSite::arg_iterator AI = CS.arg_begin();
          DSNodeHandle H = getValueDest(**AI++);
          if (DSNode *N = H.getNode()) {
            N->setReadMarker()->setModifiedMarker();      // Reads/Writes buffer
            const Type *ArgTy = F->getFunctionType()->getParamType(0);
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }
          H.mergeWith(getValueDest(*CS.getInstruction())); // Returns buffer

          H = getValueDest(**AI);       // Reads delimiter
          if (DSNode *N = H.getNode()) {
            N->setReadMarker();
            const Type *ArgTy = F->getFunctionType()->getParamType(1);
            if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
              N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
          }
          return;
        } else if (F->getName() == "strchr" || F->getName() == "strrchr" ||
                   F->getName() == "strstr") {
          // These read their arguments, and return the first one
          DSNodeHandle H = getValueDest(**CS.arg_begin());
          H.mergeWith(getValueDest(*CS.getInstruction())); // Returns buffer

          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI)
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setReadMarker();

          if (DSNode *N = H.getNode())
            N->setReadMarker();
          return;
        } else if (F->getName() == "__assert_fail") {
          for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
               AI != E; ++AI)
            if (isPointerType((*AI)->getType()))
              if (DSNode *N = getValueDest(**AI).getNode())
                N->setReadMarker();
          return;
        } else if (F->getName() == "modf" && CS.arg_end()-CS.arg_begin() == 2) {
          // This writes its second argument, and forces it to double.
          CallSite::arg_iterator compit = CS.arg_end();
          DSNodeHandle H = getValueDest(**--compit);
          if (DSNode *N = H.getNode()) {
            N->setModifiedMarker();
            N->mergeTypeInfo(Type::DoubleTy, H.getOffset());
          }
          return;
        } else {
          // Unknown function, warn if it returns a pointer type or takes a
          // pointer argument.
          bool Warn = isPointerType(CS.getInstruction()->getType());
          if (!Warn)
            for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
                 I != E; ++I)
              if (isPointerType((*I)->getType())) {
                Warn = true;
                break;
              }
          if (Warn)
            std::cerr << "WARNING: Call to unknown external function '"
                      << F->getName() << "' will cause pessimistic results!\n";
        }
      }


  // Set up the return value...
  DSNodeHandle RetVal;
  Instruction *I = CS.getInstruction();
  if (isPointerType(I->getType()))
    RetVal = getValueDest(*I);

  DSNode *CalleeNode = 0;
  if (DisableDirectCallOpt || !isa<Function>(Callee)) {
    CalleeNode = getValueDest(*Callee).getNode();
    if (CalleeNode == 0) {
      std::cerr << "WARNING: Program is calling through a null pointer?\n"<< *I;
      return;  // Calling a null pointer?
    }
  }

  std::vector<DSNodeHandle> Args;
  Args.reserve(CS.arg_end()-CS.arg_begin());

  // Calculate the arguments vector...
  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 (CalleeNode)
    FunctionCalls->push_back(DSCallSite(CS, RetVal, CalleeNode, Args));
  else
    FunctionCalls->push_back(DSCallSite(CS, RetVal, cast<Function>(Callee),
                                        Args));
}

void GraphBuilder::visitFreeInst(FreeInst &FI) {
  // Mark that the node is written to...
  if (DSNode *N = getValueDest(*FI.getOperand(0)).getNode())
    N->setModifiedMarker()->setHeapNodeMarker();
}

/// Handle casts...
void GraphBuilder::visitCastInst(CastInst &CI) {
  if (isPointerType(CI.getType()))
    if (isPointerType(CI.getOperand(0)->getType())) {
      DSNodeHandle Ptr = getValueDest(*CI.getOperand(0));
      if (Ptr.getNode() == 0) return;

      // Cast one pointer to the other, just act like a copy instruction
      setDestTo(CI, Ptr);
    } else {
      // Cast something (floating point, small integer) to a pointer.  We need
      // to track the fact that the node points to SOMETHING, just something we
      // don't know about.  Make an "Unknown" node.
      //
      setDestTo(CI, createNode()->setUnknownNodeMarker());
    }
}


// visitInstruction - For all other instruction types, if we have any arguments
// that are of pointer type, make them have unknown composition bits, and merge
// the nodes together.
void GraphBuilder::visitInstruction(Instruction &Inst) {
  DSNodeHandle CurNode;
  if (isPointerType(Inst.getType()))
    CurNode = getValueDest(Inst);
  for (User::op_iterator I = Inst.op_begin(), E = Inst.op_end(); I != E; ++I)
    if (isPointerType((*I)->getType()))
      CurNode.mergeWith(getValueDest(**I));

  if (DSNode *N = CurNode.getNode())
    N->setUnknownNodeMarker();
}



//===----------------------------------------------------------------------===//
// LocalDataStructures Implementation
//===----------------------------------------------------------------------===//

// MergeConstantInitIntoNode - Merge the specified constant into the node
// pointed to by NH.
void GraphBuilder::MergeConstantInitIntoNode(DSNodeHandle &NH, Constant *C) {
  // Ensure a type-record exists...
  DSNode *NHN = NH.getNode();
  NHN->mergeTypeInfo(C->getType(), NH.getOffset());

  if (C->getType()->isFirstClassType()) {
    if (isPointerType(C->getType()))
      // Avoid adding edges from null, or processing non-"pointer" stores
      NH.addEdgeTo(getValueDest(*C));
    return;
  }

  const TargetData &TD = NH.getNode()->getTargetData();

  if (ConstantArray *CA = dyn_cast<ConstantArray>(C)) {
    for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
      // We don't currently do any indexing for arrays...
      MergeConstantInitIntoNode(NH, cast<Constant>(CA->getOperand(i)));
  } else if (ConstantStruct *CS = dyn_cast<ConstantStruct>(C)) {
    const StructLayout *SL = TD.getStructLayout(CS->getType());
    for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
      DSNode *NHN = NH.getNode();
      DSNodeHandle NewNH(NHN, NH.getOffset()+(unsigned)SL->MemberOffsets[i]);
      MergeConstantInitIntoNode(NewNH, cast<Constant>(CS->getOperand(i)));
    }
  } else if (isa<ConstantAggregateZero>(C) || isa<UndefValue>(C)) {
    // Noop
  } else {
    assert(0 && "Unknown constant type!");
  }
}

void GraphBuilder::mergeInGlobalInitializer(GlobalVariable *GV) {
  assert(!GV->isExternal() && "Cannot merge in external global!");
  // Get a node handle to the global node and merge the initializer into it.
  DSNodeHandle NH = getValueDest(*GV);
  MergeConstantInitIntoNode(NH, GV->getInitializer());
}


/// BuildGlobalECs - Look at all of the nodes in the globals graph.  If any node
/// contains multiple globals, DSA will never, ever, be able to tell the globals
/// apart.  Instead of maintaining this information in all of the graphs
/// throughout the entire program, store only a single global (the "leader") in
/// the graphs, and build equivalence classes for the rest of the globals.
static void BuildGlobalECs(DSGraph &GG, std::set<GlobalValue*> &ECGlobals) {
  DSScalarMap &SM = GG.getScalarMap();
  EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();
  for (DSGraph::node_iterator I = GG.node_begin(), E = GG.node_end();
       I != E; ++I) {
    if (I->getGlobalsList().size() <= 1) continue;

    // First, build up the equivalence set for this block of globals.
    const std::vector<GlobalValue*> &GVs = I->getGlobalsList();
    GlobalValue *First = GVs[0];
    for (unsigned i = 1, e = GVs.size(); i != e; ++i)
      GlobalECs.unionSets(First, GVs[i]);

    // Next, get the leader element.
    assert(First == GlobalECs.getLeaderValue(First) &&
           "First did not end up being the leader?");

    // Next, remove all globals from the scalar map that are not the leader.
    assert(GVs[0] == First && "First had to be at the front!");
    for (unsigned i = 1, e = GVs.size(); i != e; ++i) {
      ECGlobals.insert(GVs[i]);
      SM.erase(SM.find(GVs[i]));
    }

    // Finally, change the global node to only contain the leader.
    I->clearGlobals();
    I->addGlobal(First);
  }

  DEBUG(GG.AssertGraphOK());
}

/// EliminateUsesOfECGlobals - Once we have determined that some globals are in
/// really just equivalent to some other globals, remove the globals from the
/// specified DSGraph (if present), and merge any nodes with their leader nodes.
static void EliminateUsesOfECGlobals(DSGraph &G,
                                     const std::set<GlobalValue*> &ECGlobals) {
  DSScalarMap &SM = G.getScalarMap();
  EquivalenceClasses<GlobalValue*> &GlobalECs = SM.getGlobalECs();

  bool MadeChange = false;
  for (DSScalarMap::global_iterator GI = SM.global_begin(), E = SM.global_end();
       GI != E; ) {
    GlobalValue *GV = *GI++;
    if (!ECGlobals.count(GV)) continue;

    const DSNodeHandle &GVNH = SM[GV];
    assert(!GVNH.isNull() && "Global has null NH!?");

    // Okay, this global is in some equivalence class.  Start by finding the
    // leader of the class.
    GlobalValue *Leader = GlobalECs.getLeaderValue(GV);

    // If the leader isn't already in the graph, insert it into the node
    // corresponding to GV.
    if (!SM.global_count(Leader)) {
      GVNH.getNode()->addGlobal(Leader);
      SM[Leader] = GVNH;
    } else {
      // Otherwise, the leader is in the graph, make sure the nodes are the
      // merged in the specified graph.
      const DSNodeHandle &LNH = SM[Leader];
      if (LNH.getNode() != GVNH.getNode())
        LNH.mergeWith(GVNH);
    }

    // Next step, remove the global from the DSNode.
    GVNH.getNode()->removeGlobal(GV);

    // Finally, remove the global from the ScalarMap.
    SM.erase(GV);
    MadeChange = true;
  }

  DEBUG(if(MadeChange) G.AssertGraphOK());
}

bool LocalDataStructures::runOnModule(Module &M) {
  const TargetData &TD = getAnalysis<TargetData>();

  // First step, build the globals graph.
  GlobalsGraph = new DSGraph(GlobalECs, TD);
  {
    GraphBuilder GGB(*GlobalsGraph);

    // Add initializers for all of the globals to the globals graph.
    for (Module::global_iterator I = M.global_begin(), E = M.global_end();
         I != E; ++I)
      if (!I->isExternal())
        GGB.mergeInGlobalInitializer(I);
  }

  // Next step, iterate through the nodes in the globals graph, unioning
  // together the globals into equivalence classes.
  std::set<GlobalValue*> ECGlobals;
  BuildGlobalECs(*GlobalsGraph, ECGlobals);
  DEBUG(std::cerr << "Eliminating " << ECGlobals.size() << " EC Globals!\n");
  ECGlobals.clear();

  // Calculate all of the graphs...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal())
      DSInfo.insert(std::make_pair(I, new DSGraph(GlobalECs, TD, *I,
                                                  GlobalsGraph)));

  GlobalsGraph->removeTriviallyDeadNodes();
  GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs);

  // Now that we've computed all of the graphs, and merged all of the info into
  // the globals graph, see if we have further constrained the globals in the
  // program if so, update GlobalECs and remove the extraneous globals from the
  // program.
  BuildGlobalECs(*GlobalsGraph, ECGlobals);
  if (!ECGlobals.empty()) {
    DEBUG(std::cerr << "Eliminating " << ECGlobals.size() << " EC Globals!\n");
    for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
           E = DSInfo.end(); I != E; ++I)
      EliminateUsesOfECGlobals(*I->second, ECGlobals);
  }

  return false;
}

// releaseMemory - If the pass pipeline is done with this pass, we can release
// our memory... here...
//
void LocalDataStructures::releaseMemory() {
  for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
         E = DSInfo.end(); I != E; ++I) {
    I->second->getReturnNodes().erase(I->first);
    if (I->second->getReturnNodes().empty())
      delete I->second;
  }

  // Empty map so next time memory is released, data structures are not
  // re-deleted.
  DSInfo.clear();
  delete GlobalsGraph;
  GlobalsGraph = 0;
}

