//===- DataStructure.cpp - Implement the core data structure analysis -----===//
//
//                     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 core data structure functionality.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "dsa"

#include "dsa/DSGraphTraits.h"
#include "dsa/DataStructure.h"
#include "dsa/DSGraph.h"
#include "dsa/DSSupport.h"
#include "dsa/DSNode.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"

#include <iostream>
#include <algorithm>
using namespace llvm;

#define COLLAPSE_ARRAYS_AGGRESSIVELY 0
namespace {
  STATISTIC (NumFolds, "Number of nodes completely folded");
  STATISTIC (NumFoldsOOBOffset, "Number of OOB offsets that caused node folding");
  STATISTIC (NumNodeAllocated  , "Number of nodes allocated");
}

/// isForwarding - Return true if this NodeHandle is forwarding to another
/// one.
bool DSNodeHandle::isForwarding() const {
  return N && N->isForwarding();
}

DSNode *DSNodeHandle::HandleForwarding() const {
  assert(N->isForwarding() && "Can only be invoked if forwarding!");
  DEBUG(
    { //assert not looping
    DSNode* NH = N;
    svset<DSNode*> seen;
    while(NH && NH->isForwarding()) {
    assert(seen.find(NH) == seen.end() && "Loop detected");
    seen.insert(NH);
    NH = NH->ForwardNH.N;
    }
    }
    );
  // Handle node forwarding here!
  DSNode *Next = N->ForwardNH.getNode();  // Cause recursive shrinkage
  Offset += N->ForwardNH.getOffset();

  if (--N->NumReferrers == 0) {
    // Removing the last referrer to the node, sever the forwarding link
    N->stopForwarding();
  }

  N = Next;
  N->NumReferrers++;

  if (N->getSize() <= Offset) {
    assert(N->getSize() <= 1 && "Forwarded to shrunk but not collapsed node?");
    Offset = 0;
  }
  return N;
}

//===----------------------------------------------------------------------===//
// DSScalarMap Implementation
//===----------------------------------------------------------------------===//

DSNodeHandle &DSScalarMap::AddGlobal(const GlobalValue *GV) {
  assert(GV);
  assert(ValueMap.count(GV) == 0 && "GV already exists!");

  // If the node doesn't exist, check to see if it's a global that is
  // equated to another global in the program.
  EquivalenceClasses<const GlobalValue*>::iterator ECI = GlobalECs.findValue(GV);
  if (ECI != GlobalECs.end()) {
    const GlobalValue *Leader = *GlobalECs.findLeader(ECI);
    if (Leader != GV) {
      GV = Leader;
      iterator I = ValueMap.find(GV);
      if (I != ValueMap.end())
        return I->second;
    }
  }

  // Okay, this is either not an equivalenced global or it is the leader, it
  // will be inserted into the scalar map now.
  GlobalSet.insert(GV);

  return ValueMap.insert(std::make_pair(GV, DSNodeHandle())).first->second;
}

/// spliceFrom - Copy all entries from RHS, then clear RHS.
///
void DSScalarMap::spliceFrom(DSScalarMap &RHS) {
  // Special case if this is empty.
  if (ValueMap.empty()) {
    ValueMap.swap(RHS.ValueMap);
    GlobalSet.swap(RHS.GlobalSet);
  } else {
    GlobalSet.insert(RHS.GlobalSet.begin(), RHS.GlobalSet.end());
    for (ValueMapTy::iterator I = RHS.ValueMap.begin(), E = RHS.ValueMap.end();
         I != E; ++I)
      ValueMap[I->first].mergeWith(I->second);
    RHS.ValueMap.clear();
  }
}

//===----------------------------------------------------------------------===//
// DSNode Implementation
//===----------------------------------------------------------------------===//

DSNode::DSNode(DSGraph *G)
  : NumReferrers(0), Size(0), ParentGraph(G), NodeType(0) {
    // Add the type entry if it is specified...
    if (G) G->addNode(this);
    ++NumNodeAllocated;
  }

// DSNode copy constructor... do not copy over the referrers list!
DSNode::DSNode(const DSNode &N, DSGraph *G, bool NullLinks)
  : NumReferrers(0), Size(N.Size), ParentGraph(G), TyMap(N.TyMap),
  Globals(N.Globals), NodeType(N.NodeType) {
    if (!NullLinks) Links = N.Links;
    G->addNode(this);
    ++NumNodeAllocated;
  }

DSNode::~DSNode() {
  dropAllReferences();
  assert(hasNoReferrers() && "Referrers to dead node exist!");
}

void DSNode::assertOK() const {
  //  assert(((Ty && Ty->getTypeID() != Type::VoidTyID) ||
  //         ((!Ty || Ty->getTypeID() == Type::VoidTyID) && (Size == 0 ||
  //         (NodeType & DSNode::ArrayNode)))) &&
  //         "Node not OK!");

  assert(ParentGraph && "Node has no parent?");
  for (globals_iterator ii = globals_begin(), ee = globals_end();
       ii != ee; ++ii) {
    assert(ParentGraph->getScalarMap().global_count(*ii));
    assert(ParentGraph->getScalarMap().find(*ii)->second.getNode() == this);
  }
}

/// forwardNode - Mark this node as being obsolete, and all references to it
/// should be forwarded to the specified node and offset.
///
void DSNode::forwardNode(DSNode *To, unsigned Offset) {
  assert(this != To && "Cannot forward a node to itself!");
  assert(ForwardNH.isNull() && "Already forwarding from this node!");
  if (To->Size <= 1) Offset = 0;
  assert((Offset < To->Size || (Offset == To->Size && Offset == 0)) &&
         "Forwarded offset is wrong!");
  ForwardNH.setTo(To, Offset);
  NodeType = DeadNode;
  Size = 0;

  DSNodeHandle ToNH(To,Offset);

  //Move the Links
  for (LinkMapTy::iterator ii = Links.begin(), ee = Links.end();
       ii != ee; ++ii) {
    if (!ii->second.isNull()) {
      // Compute the offset into the current node at which to
      // merge this link.  In the common case, this is a linear
      // relation to the offset in the original node (with
      // wrapping), but if the current node gets collapsed due to
      // recursive merging, we must make sure to merge in all remaining
      // links at offset zero.
      unsigned MergeOffset = 0;
      if (ToNH.getNode()->getSize() != 1)
        MergeOffset = (ii->first + Offset) % ToNH.getNode()->getSize();
      ToNH.getNode()->addEdgeTo(MergeOffset, ii->second);
    }
  }
  Links.clear();

  // Remove this node from the parent graph's Nodes list.
  ParentGraph->unlinkNode(this);
  ParentGraph = 0;
}

// addGlobal - Add an entry for a global value to the Globals list.  This also
// marks the node with the 'G' flag if it does not already have it.
//
void DSNode::addGlobal(const GlobalValue *GV) {
  // First, check to make sure this is the leader if the global is in an
  // equivalence class.
  GV = getParentGraph()->getScalarMap().getLeaderForGlobal(GV);

  Globals.insert(GV);
  setGlobalMarker();
}

void DSNode::addFunction(const Function* F) {
  addGlobal(F);
}

// removeGlobal - Remove the specified global that is explicitly in the globals
// list.
void DSNode::removeGlobal(const GlobalValue *GV) {
  assert (Globals.count(GV) && "Global not in Node!");
  Globals.erase(GV);
}

/// foldNodeCompletely - If we determine that this node has some funny
/// behavior happening to it that we cannot represent, we fold it down to a
/// single, completely pessimistic, node.  This node is represented as a
/// single byte with a single TypeEntry of "void".
///
void DSNode::foldNodeCompletely() {
  if (isNodeCompletelyFolded()) return;  // If this node is already folded...

  //  assert(0 && "Folding is happening");

  ++NumFolds;

  //Collapsed nodes don't really need a type
  //Clear the array flag too. Node should be of type VOID
  TyMap.clear();
  maskNodeTypes(~ArrayNode);

  // If this node has a size that is <= 1, we don't need to create a forwarding
  // node.
  if (getSize() <= 1) {
    setCollapsedMarker();
    Size = 1;
    assert(Links.size() <= 1 && "Size is 1, but has more links?");
  } else {
    // Create the node we are going to forward to.  This is required because
    // some referrers may have an offset that is > 0.  By forcing them to
    // forward, the forwarder has the opportunity to correct the offset.
    DSNode *DestNode = new DSNode(ParentGraph);
    DestNode->NodeType = NodeType;
    DestNode->setCollapsedMarker();
    DestNode->Size = 1;
    DestNode->Globals.swap(Globals);

    // Start forwarding to the destination node...
    forwardNode(DestNode, 0);

  }
}

/// isNodeCompletelyFolded - Return true if this node has been completely
/// folded down to something that can never be expanded, effectively losing
/// all of the field sensitivity that may be present in the node.
///
bool DSNode::isNodeCompletelyFolded() const {
  return isCollapsedNode();
}

void DSNode::addValueList(std::vector<const Value*> &List) const {
  DSScalarMap &SN = getParentGraph()->getScalarMap();
  for(DSScalarMap::const_iterator I = SN.begin(), E = SN.end(); I!= E; I++) {
    if(SN[I->first].getNode() == this){
      //I->first->dump();
    }

  }
}
/// addFullGlobalsSet - Compute the full set of global values that are
/// represented by this node.  Unlike getGlobalsList(), this requires fair
/// amount of work to compute, so don't treat this method call as free.
void DSNode::addFullGlobalsSet(svset<const GlobalValue*> &Set) const {
  if (globals_begin() == globals_end()) return;

  EquivalenceClasses<const GlobalValue*> &EC = getParentGraph()->getGlobalECs();

  for (globals_iterator I = globals_begin(), E = globals_end(); I != E; ++I) {
    EquivalenceClasses<const GlobalValue*>::iterator ECI = EC.findValue(*I);
    if (ECI == EC.end())
      Set.insert(*I);
    else
      Set.insert(EC.member_begin(ECI), EC.member_end());
  }
}

/// addFullFunctionSet - Identical to addFullGlobalsSet, but only return the
/// functions in the full list.
void DSNode::addFullFunctionSet(svset<const Function*> &Set) const {
  if (globals_begin() == globals_end()) return;

  EquivalenceClasses<const GlobalValue*> &EC = getParentGraph()->getGlobalECs();

  for (globals_iterator I = globals_begin(), E = globals_end(); I != E; ++I) {
    EquivalenceClasses<const GlobalValue*>::iterator ECI = EC.findValue(*I);
    if (ECI == EC.end()) {
      if (const Function *F = dyn_cast<Function>(*I))
        Set.insert(F);
    } else {
      for (EquivalenceClasses<const GlobalValue*>::member_iterator MI =
           EC.member_begin(ECI), E = EC.member_end(); MI != E; ++MI)
        if (const Function *F = dyn_cast<Function>(*MI))
          Set.insert(F);
    }
  }
}

void DSNode::dumpFuncs() {
  std::vector<const Function *> List;
  addFullFunctionList (List);
  for (unsigned index = 0; index < List.size(); ++index) {
    std::cerr << List[index]->getName().str() << std::endl;
  }
  return;
}

/// markIntPtrFlags - Mark P2 flags on node, if integer and pointer types
/// overlap at any offset.
///
void DSNode::markIntPtrFlags() {
  // check if the types merged have both int and pointer at the same offset,

  const DataLayout &TD = getParentGraph()->getDataLayout();
  // check all offsets for that node.
  for(unsigned offset = 0; offset < getSize() ; offset++) {
    // if that Node has no Type information, skip
    if(TyMap.find(offset) == TyMap.end())
      continue;
    if(!TyMap[offset])
      continue;

    bool pointerTy = false;
    bool integerTy = false;
    unsigned intSize = 0;
    unsigned ptrSize = 0;

    // Iterate through all the Types, at that offset, checking if we have
    // found a pointer type/integer type
    for (svset<Type*>::const_iterator ni = TyMap[offset]->begin(),
         ne = TyMap[offset]->end(); ni != ne; ++ni) {
      if((*ni)->isPointerTy()) {
        PointerType * PT = dyn_cast<PointerType>(*ni);
        pointerTy = true;
        ptrSize = TD.getPointerSize(PT->getAddressSpace());
      }
      if((*ni)->isIntegerTy()) {
        integerTy = true;
        if (TD.getTypeStoreSize(*ni) > intSize)
          intSize = TD.getTypeStoreSize(*ni);
      }
    }
    // If this offset itself contains both pointer and integer, set the
    // flags and exit.
    if(pointerTy && integerTy){
      setUnknownMarker()->setIntToPtrMarker()->setPtrToIntMarker();
      return;
    }
    if(!pointerTy && !integerTy){
      continue;
    }

    // If only either integer or pointer was found, we must see if it 
    // overlaps with any other pointer or integer type at an offset that
    // comes later. 
    unsigned maxOffset = offset + (pointerTy ? ptrSize:intSize);
    unsigned offset2 = offset;
    while(offset2 < maxOffset && offset2 < getSize()) {
      if(TyMap.find(offset2) == TyMap.end()) {
        offset2++;
        continue;
      }
      for (svset<Type*>::const_iterator ni = TyMap[offset2]->begin(),
           ne = TyMap[offset2]->end(); ni != ne; ++ni) {
        if((*ni)->isPointerTy()) {
          pointerTy = true;
        }
        if((*ni)->isIntegerTy()) {
          integerTy = true;
        }
      }
      // whenever we have found overlapping integer and pointer types,
      // we can set the flags, and exit.
      if(pointerTy && integerTy){
        setUnknownMarker()->setIntToPtrMarker()->setPtrToIntMarker();
        return;
      }
      offset2++;
    }
  }
}

/// growSizeForType - This method increases the size of the node 
/// to accomodate NewTy at the given offset. This is useful for
/// updating the size of a DSNode, without actually inferring a 
/// Type.
void DSNode::growSizeForType(Type *NewTy, unsigned Offset) {

  if (!NewTy || NewTy->isVoidTy()) return;

  if (isCollapsedNode()) return;
  if (isArrayNode() && getSize() > 0) {
    Offset %= getSize();
  }
  const DataLayout &TD = getParentGraph()->getDataLayout();
  if (Offset + TD.getTypeAllocSize(NewTy) >= getSize())
    growSize(Offset + TD.getTypeAllocSize(NewTy));

}

/// mergeTypeInfo - This method merges the specified type into the current node
/// at the specified offset.  This may update the current node's type record if
/// this gives more information to the node, it may do nothing to the node if
/// this information is already known, or it may merge the node completely (and
/// return true) if the information is incompatible with what is already known.
///
/// This method returns true if the node is completely folded, otherwise false.
///
void DSNode::mergeTypeInfo(Type *NewTy, unsigned Offset) {
  if (!NewTy || NewTy->isVoidTy()) return;
  if (isCollapsedNode()) return;

  growSizeForType(NewTy, Offset);

  // Clang generates loads and stores of struct types.
  // %tmp12 = load %struct.demand* %retval, align 1 

  // In such cases, merge type information for each struct field
  // individually(at the appropriate offset), instead of the 
  // struct type.
  if(NewTy->isStructTy()) {
    const DataLayout &TD = getParentGraph()->getDataLayout();
    StructType *STy = cast<StructType>(NewTy);
    const StructLayout *SL = TD.getStructLayout(cast<StructType>(STy));
    unsigned count = 0;
    for(Type::subtype_iterator ii = STy->element_begin(), ee = STy->element_end(); ii!= ee; ++ii, ++count) {
      unsigned FieldOffset = SL->getElementOffset(count);
      mergeTypeInfo(*ii, Offset + FieldOffset);
    }
  } else {
    TyMap[Offset] = getParentGraph()->getTypeSS().getOrCreate(TyMap[Offset], NewTy);
  }

  assert(TyMap[Offset]);
}

void DSNode::mergeTypeInfo(const TyMapTy::mapped_type TyIt, unsigned Offset) {
  if (isCollapsedNode()) return;
  if (isArrayNode()) Offset %= getSize();

  const DataLayout &TD = getParentGraph()->getDataLayout();
  if (!TyMap[Offset]){
    TyMap[Offset] = TyIt;
    for (svset<Type*>::const_iterator ni = TyMap[Offset]->begin(),
         ne = TyMap[Offset]->end(); ni != ne; ++ni) {
      if (Offset + TD.getTypeAllocSize(*ni) >= getSize())
        growSize(Offset + TD.getTypeAllocSize(*ni));
    }
  } else if (TyIt) {
    svset<Type*> S(*TyMap[Offset]);
    S.insert(TyIt->begin(), TyIt->end());
    TyMap[Offset] = getParentGraph()->getTypeSS().getOrCreate(S);
  }
  assert(TyMap[Offset]);
}

void DSNode::mergeTypeInfo(const DSNode* DN, unsigned Offset) {
  if (isCollapsedNode()) return;

  for (TyMapTy::const_iterator ii = DN->TyMap.begin(), ee = DN->TyMap.end();
       ii != ee; ++ii)
    mergeTypeInfo(ii->second, ii->first + Offset);
}

/// addEdgeTo - Add an edge from the current node to the specified node.  This
/// can cause merging of nodes in the graph.
///
void DSNode::addEdgeTo(unsigned Offset, const DSNodeHandle &NH) {
  if (NH.isNull()) return;       // Nothing to do

  if (isNodeCompletelyFolded())
    Offset = 0;

  DSNodeHandle &ExistingEdge = getLink(Offset);
  if (!ExistingEdge.isNull()) {
    // Merge the two nodes...
    ExistingEdge.mergeWith(NH);
  } else {                             // No merging to perform...
    setLink(Offset, NH);               // Just force a link in there...
  }
}

void DSNode::mergeGlobals(const DSNode &RHS) {
  Globals.insert(RHS.Globals.begin(), RHS.Globals.end());
}

// MergeNodes - Helper function for DSNode::mergeWith().
// This function does the hard work of merging two nodes, CurNodeH
// and NH after filtering out trivial cases and making sure that
// CurNodeH.offset >= NH.offset.
//
// ***WARNING***
// Since merging may cause either node to go away, we must always
// use the node-handles to refer to the nodes.  These node handles are
// automatically updated during merging, so will always provide access
// to the correct node after a merge.
//
void DSNode::MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH) {
  assert(CurNodeH.getOffset() >= NH.getOffset() &&
         "This should have been enforced in the caller.");
  assert(CurNodeH.getNode()->getParentGraph()==NH.getNode()->getParentGraph() &&
         "Cannot merge two nodes that are not in the same graph!");

  // Now we know that Offset >= NH.Offset, so convert it so our "Offset" (with
  // respect to NH.Offset) is now zero.  NOffset is the distance from the base
  // of our object that N starts from.
  //
  unsigned NOffset = CurNodeH.getOffset()-NH.getOffset();
  unsigned NSize = NH.getNode()->getSize();

  // If the two nodes are of different size, and the smaller node has the array
  // bit set, collapse!
  if (NSize != CurNodeH.getNode()->getSize()) {
#if COLLAPSE_ARRAYS_AGGRESSIVELY
    if (NSize < CurNodeH.getNode()->getSize()) {
      if (NH.getNode()->isArrayNode())
        NH.getNode()->foldNodeCompletely();
    } else if (CurNodeH.getNode()->isArrayNode()) {
      NH.getNode()->foldNodeCompletely();
    }
#endif
  }

  // If we are merging a node with a completely folded node, then both nodes are
  // now completely folded.
  //
  if (CurNodeH.getNode()->isNodeCompletelyFolded()) {
    if (!NH.getNode()->isNodeCompletelyFolded()) {
      NH.getNode()->foldNodeCompletely();
      assert(NH.getNode() && NH.getOffset() == 0 &&
             "folding did not make offset 0?");
      NOffset = NH.getOffset();
      NSize = NH.getNode()->getSize();
      assert(NOffset == 0 && NSize == 1);
    }
  } else if (NH.getNode()->isNodeCompletelyFolded()) {
    CurNodeH.getNode()->foldNodeCompletely();
    assert(CurNodeH.getNode() && CurNodeH.getOffset() == 0 &&
           "folding did not make offset 0?");
    NSize = NH.getNode()->getSize();
    NOffset = NH.getOffset();
    assert(NOffset == 0 && NSize == 1);
  }

  // FIXME:Add comments.
  if(NH.getNode()->isArrayNode() && !CurNodeH.getNode()->isArrayNode()) {
    if(NH.getNode()->getSize() != 0 && CurNodeH.getNode()->getSize() != 0) { 
      if((NH.getNode()->getSize() != CurNodeH.getNode()->getSize() &&
          (NH.getOffset() != 0 || CurNodeH.getOffset() != 0) 
          && NH.getNode()->getSize() < CurNodeH.getNode()->getSize())) {
        CurNodeH.getNode()->foldNodeCompletely();
        NH.getNode()->foldNodeCompletely();
        NSize = NH.getNode()->getSize();
        NOffset = NH.getOffset();
      }
    }
  }
  if(!NH.getNode()->isArrayNode() && CurNodeH.getNode()->isArrayNode()) {
    if(NH.getNode()->getSize() != 0 && CurNodeH.getNode()->getSize() != 0) { 
      if((NH.getNode()->getSize() != CurNodeH.getNode()->getSize() &&
          (NH.getOffset() != 0 || CurNodeH.getOffset() != 0) 
          && NH.getNode()->getSize() > CurNodeH.getNode()->getSize())) {
        CurNodeH.getNode()->foldNodeCompletely();
        NH.getNode()->foldNodeCompletely();
        NSize = NH.getNode()->getSize();
        NOffset = NH.getOffset();
      }
    }
  }

  if (CurNodeH.getNode()->isArrayNode() && NH.getNode()->isArrayNode()) {
    if(NH.getNode()->getSize() != 0 && CurNodeH.getNode()->getSize() != 0
       && (NH.getNode()->getSize() != CurNodeH.getNode()->getSize())){
      CurNodeH.getNode()->foldNodeCompletely();
      NH.getNode()->foldNodeCompletely();
      NSize = NH.getNode()->getSize();
      NOffset = NH.getOffset();
    }
  }


  DSNode *N = NH.getNode();
  if (CurNodeH.getNode() == N || N == 0) return;
  assert(!CurNodeH.getNode()->isDeadNode());

  // Merge the type entries of the two nodes together...
  CurNodeH.getNode()->mergeTypeInfo(NH.getNode(), NOffset);
  if (NH.getNode()->getSize() + NOffset > CurNodeH.getNode()->getSize())
    CurNodeH.getNode()->growSize(NH.getNode()->getSize() + NOffset);
  assert(!CurNodeH.getNode()->isDeadNode());

  // Merge the NodeType information.
  CurNodeH.getNode()->NodeType |= N->NodeType;

  // Start forwarding to the new node!
  N->forwardNode(CurNodeH.getNode(), NOffset);
  assert(!CurNodeH.getNode()->isDeadNode());

  // Make all of the outgoing links of N now be outgoing links of CurNodeH.
  //
  for (LinkMapTy::iterator ii = N->Links.begin(), ee = N->Links.end();
       ii != ee; ++ii)
    if (ii->second.getNode()) {
      // Compute the offset into the current node at which to
      // merge this link.  In the common case, this is a linear
      // relation to the offset in the original node (with
      // wrapping), but if the current node gets collapsed due to
      // recursive merging, we must make sure to merge in all remaining
      // links at offset zero.
      unsigned MergeOffset = 0;
      DSNode *CN = CurNodeH.getNode();
      if (CN->Size != 1)
        MergeOffset = (ii->first + NOffset) % CN->getSize();
      CN->addEdgeTo(MergeOffset, ii->second);
    }

  // Now that there are no outgoing edges, all of the Links are dead.
  N->Links.clear();

  // Merge the globals list...
  CurNodeH.getNode()->mergeGlobals(*N);

  // Delete the globals from the old node...
  N->Globals.clear();
}


/// mergeWith - Merge this node and the specified node, moving all links to and
/// from the argument node into the current node, deleting the node argument.
/// Offset indicates what offset the specified node is to be merged into the
/// current node.
///
/// The specified node may be a null pointer (in which case, we update it to
/// point to this node).
///
void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) {
  DSNode *N = NH.getNode();
  if (N == this && NH.getOffset() == Offset)
    return;  // Noop

  // If the RHS is a null node, make it point to this node!
  if (N == 0) {
    NH.mergeWith(DSNodeHandle(this, Offset));
    return;
  }

  assert(!N->isDeadNode() && !isDeadNode());
  assert(!hasNoReferrers() && "Should not try to fold a useless node!");

  if (N == this) {
    // We cannot merge two pieces of the same node together, collapse the node
    // completely.
    DEBUG(errs() << "Attempting to merge two chunks of the same node together!\n");
    foldNodeCompletely();
    return;
  }

  // If both nodes are not at offset 0, make sure that we are merging the node
  // at an later offset into the node with the zero offset.
  //
  if (Offset < NH.getOffset()) {
    N->mergeWith(DSNodeHandle(this, Offset), NH.getOffset());
    return;
  } else if (Offset == NH.getOffset() && getSize() < N->getSize()) {
    // If the offsets are the same, merge the smaller node into the bigger node
    N->mergeWith(DSNodeHandle(this, Offset), NH.getOffset());
    return;
  }

  // Ok, now we can merge the two nodes.  Use a static helper that works with
  // two node handles, since "this" may get merged away at intermediate steps.
  DSNodeHandle CurNodeH(this, Offset);
  DSNodeHandle NHCopy(NH);
  if (CurNodeH.getOffset() >= NHCopy.getOffset())
    DSNode::MergeNodes(CurNodeH, NHCopy);
  else
    DSNode::MergeNodes(NHCopy, CurNodeH);
}

void DSNode::cleanEdges() {
  //get rid of any type edge pointing to the null type
  for (type_iterator ii = type_begin(); ii != type_end(); ) {
    if (ii->second)
      ++ii;
    else {
      type_iterator backup = ii;
      ++backup;
      TyMap.erase(ii);
      ii = backup;
    }
  }
  //get rid of any node edge pointing to nothing
  for (edge_iterator ii = edge_begin(); ii != edge_end(); ) {
    if (ii->second.isNull()) {
      edge_iterator backup = ii;
      ++backup;
      Links.erase(ii);
      ii = backup;
    } else
      ++ii;
  }
}

void DSNode::checkOffsetFoldIfNeeded(int Offset) {
  if (!isNodeCompletelyFolded() &&
      (Size != 0 || Offset != 0) &&
      !isForwarding()) {
    if ((Offset >= (int)Size) || Offset < 0) {
      // Accessing offsets out of node size range
      // This is seen in the "magic" struct in named (from bind), where the
      // fourth field is an array of length 0, presumably used to create struct
      // instances of different sizes
      // More generally this happens whenever code indexes past the end
      // of a struct type.  We don't model this, so fold!

      // Collapse the node since its size is now variable
      foldNodeCompletely();

      ++NumFoldsOOBOffset;
    }
  }
}
//===----------------------------------------------------------------------===//
// ReachabilityCloner Implementation
//===----------------------------------------------------------------------===//

DSNodeHandle ReachabilityCloner::getClonedNH(const DSNodeHandle &SrcNH) {
  if (SrcNH.isNull()) return DSNodeHandle();
  const DSNode *SN = SrcNH.getNode();

  DSNodeHandle &NH = NodeMap[SN];
  if (!NH.isNull()) { // Node already mapped?
    DSNode *NHN = NH.getNode();
    unsigned NewOffset = NH.getOffset() + SrcNH.getOffset();
    if (NHN) {
      NHN->checkOffsetFoldIfNeeded(NewOffset);
      NHN = NH.getNode();
    }
    return DSNodeHandle(NHN, NewOffset);
  }

  // If SrcNH has globals and the destination graph has one of the same globals,
  // merge this node with the destination node, which is much more efficient.
  if (SN->globals_begin() != SN->globals_end()) {
    DSScalarMap &DestSM = Dest->getScalarMap();
    for (DSNode::globals_iterator I = SN->globals_begin(),E = SN->globals_end();
         I != E; ++I) {
      const GlobalValue *GV = *I;
      DSScalarMap::iterator GI = DestSM.find(GV);
      if (GI != DestSM.end() && !GI->second.isNull()) {
        // We found one, use merge instead!
        merge(GI->second, Src->getNodeForValue(GV));
        assert(!NH.isNull() && "Didn't merge node!");
        DSNode *NHN = NH.getNode();
        unsigned NewOffset = NH.getOffset() + SrcNH.getOffset();
        if (NHN) {
          NHN->checkOffsetFoldIfNeeded(NewOffset);
          NHN = NH.getNode();
        }
        return DSNodeHandle(NHN, NewOffset);
      }
    }
  }

  if (!createDest) return DSNodeHandle(0,0);

  DSNode *DN = new DSNode(*SN, Dest, true /* Null out all links */);
  DN->maskNodeTypes(BitsToKeep);
  NH = DN;

  // Next, recursively clone all outgoing links as necessary.  Note that
  // adding these links can cause the node to collapse itself at any time, and
  // the current node may be merged with arbitrary other nodes.  For this
  // reason, we must always go through NH.
  DN = 0;
  for (DSNode::const_edge_iterator ii = SN->edge_begin(), ee = SN->edge_end();
       ii != ee; ++ii) {
    const DSNodeHandle &SrcEdge = ii->second;
    if (!SrcEdge.isNull()) {
      const DSNodeHandle &DestEdge = getClonedNH(SrcEdge);
      // Compute the offset into the current node at which to
      // merge this link.  In the common case, this is a linear
      // relation to the offset in the original node (with
      // wrapping), but if the current node gets collapsed due to
      // recursive merging, we must make sure to merge in all remaining
      // links at offset zero.
      unsigned MergeOffset = 0;
      DSNode *CN = NH.getNode();
      if (CN->getSize() != 1)
        MergeOffset = (ii->first + NH.getOffset()) % CN->getSize();
      CN->addEdgeTo(MergeOffset, DestEdge);
    }
  }

  // If this node contains any globals, make sure they end up in the scalar
  // map with the correct offset.
  for (DSNode::globals_iterator I = SN->globals_begin(), E = SN->globals_end();
       I != E; ++I) {
    const GlobalValue *GV = *I;
    const DSNodeHandle &SrcGNH = Src->getNodeForValue(GV);
    DSNodeHandle &DestGNH = NodeMap[SrcGNH.getNode()];
    assert(DestGNH.getNode() == NH.getNode() &&"Global mapping inconsistent");
    Dest->getNodeForValue(GV).mergeWith(DSNodeHandle(DestGNH.getNode(),
                                                     DestGNH.getOffset()+SrcGNH.getOffset()));
  }
  NH.getNode()->mergeGlobals(*SN);

  DSNode* NHN = NH.getNode();
  unsigned NewOffset = NH.getOffset() + SrcNH.getOffset();
  if (NHN) {
    NHN->checkOffsetFoldIfNeeded(NewOffset);
    NHN = NH.getNode();
  }
  return DSNodeHandle(NHN, NewOffset);
}

void ReachabilityCloner::merge(const DSNodeHandle &NH,
                               const DSNodeHandle &SrcNH) {
  if (SrcNH.isNull()) return;  // Noop
  if (NH.isNull()) {
    // If there is no destination node, just clone the source and assign the
    // destination node to be it.
    NH.mergeWith(getClonedNH(SrcNH));
    return;
  }

  // Okay, at this point, we know that we have both a destination and a source
  // node that need to be merged.  Check to see if the source node has already
  // been cloned.
  const DSNode *SN = SrcNH.getNode();
  DSNodeHandle &SCNH = NodeMap[SN];  // SourceClonedNodeHandle
  if (!SCNH.isNull()) {   // Node already cloned?
    DSNode *SCNHN = SCNH.getNode();
    NH.mergeWith(DSNodeHandle(SCNHN,
                              SCNH.getOffset()+SrcNH.getOffset()));
    return;  // Nothing to do!
  }

  // Okay, so the source node has not already been cloned.  Instead of creating
  // a new DSNode, only to merge it into the one we already have, try to perform
  // the merge in-place.  The only case we cannot handle here is when the offset
  // into the existing node is less than the offset into the virtual node we are
  // merging in.  In this case, we have to extend the existing node, which
  // requires an allocation anyway.
  DSNode *DN = NH.getNode();   // Make sure the Offset is up-to-date
  if (NH.getOffset() >= SrcNH.getOffset()) {
    if (!DN->isNodeCompletelyFolded()) {
      // Make sure the destination node is folded if the source node is folded.
      if (SN->isNodeCompletelyFolded()) {
        DN->foldNodeCompletely();
        DN = NH.getNode();
      } else if (SN->getSize() != DN->getSize()) {
        // If the two nodes are of different size, and the smaller node has the
        // array bit set, collapse!
#if COLLAPSE_ARRAYS_AGGRESSIVELY
        if (SN->getSize() < DN->getSize()) {
          if (SN->isArrayNode()) {
            DN->foldNodeCompletely();
            DN = NH.getNode();
          }
        } else if (DN->isArrayNode()) {
          DN->foldNodeCompletely();
          DN = NH.getNode();
        }
#endif
      }


      // FIXME:Add comments.
      if(!DN->isArrayNode() && SN->isArrayNode()) {
        if(DN->getSize() != 0 && SN->getSize() != 0) { 
          if((DN->getSize() != SN->getSize() &&
              (NH.getOffset() != 0 || SrcNH.getOffset() != 0) 
              && DN->getSize() > SN->getSize())) {
            DN->foldNodeCompletely();
            DN = NH.getNode();
          }
        }
      }
      if(!SN->isArrayNode() && DN->isArrayNode()) {
        if(DN->getSize() != 0 && SN->getSize() != 0) { 
          if((DN->getSize() != SN->getSize() &&
              (NH.getOffset() != 0 || SrcNH.getOffset() != 0) 
              && DN->getSize() < SN->getSize())) {
            DN->foldNodeCompletely();
            DN = NH.getNode();
          }
        }
      } 

      if (SN->isArrayNode() && DN->isArrayNode()) {
        if((SN->getSize() != DN->getSize()) && (SN->getSize() != 0) 
           && DN->getSize() != 0) {
          DN->foldNodeCompletely();
          DN = NH.getNode();
        }
      }
      if (!DN->isNodeCompletelyFolded() && DN->getSize() < SN->getSize())
        DN->growSize(SN->getSize());


      // Merge the type entries of the two nodes together...
      if (!DN->isNodeCompletelyFolded())
        DN->mergeTypeInfo(SN, NH.getOffset() - SrcNH.getOffset());
    }

    assert(!DN->isDeadNode());

    // Merge the NodeType information.
    DN->mergeNodeFlags(SN->getNodeFlags() & BitsToKeep);

    // Before we start merging outgoing links and updating the scalar map, make
    // sure it is known that this is the representative node for the src node.
    SCNH = DSNodeHandle(DN, NH.getOffset()-SrcNH.getOffset());

    // If the source node contains any globals, make sure they end up in the
    // scalar map with the correct offset.
    if (SN->globals_begin() != SN->globals_end()) {
      // Update the globals in the destination node itself.
      DN->mergeGlobals(*SN);

      // Update the scalar map for the graph we are merging the source node
      // into.
      for (DSNode::globals_iterator I = SN->globals_begin(),
           E = SN->globals_end(); I != E; ++I) {
        const GlobalValue *GV = *I;
        const DSNodeHandle &SrcGNH = Src->getNodeForValue(GV);
        DSNodeHandle &DestGNH = NodeMap[SrcGNH.getNode()];
        assert(DestGNH.getNode()==NH.getNode() &&"Global mapping inconsistent");
        Dest->getNodeForValue(GV).mergeWith(DSNodeHandle(DestGNH.getNode(),
                                                         DestGNH.getOffset()+SrcGNH.getOffset()));
      }
      NH.getNode()->mergeGlobals(*SN);
    }
  } else {
    // We cannot handle this case without allocating a temporary node.  Fall
    // back on being simple.
    DSNode *NewDN = new DSNode(*SN, Dest, true /* Null out all links */);
    NewDN->maskNodeTypes(BitsToKeep);

#ifndef NDEBUG
    unsigned NHOffset = NH.getOffset();
#endif
    NH.mergeWith(DSNodeHandle(NewDN, SrcNH.getOffset()));

#ifndef NDEBUG
    assert(NH.getNode() &&
           (NH.getOffset() > NHOffset ||
            (NH.getOffset() == 0 && NH.getNode()->isNodeCompletelyFolded())) &&
           "Merging did not adjust the offset!");
#endif

    // Before we start merging outgoing links and updating the scalar map, make
    // sure it is known that this is the representative node for the src node.
    SCNH = DSNodeHandle(NH.getNode(), NH.getOffset()-SrcNH.getOffset());

    // If the source node contained any globals, make sure to create entries
    // in the scalar map for them!
    for (DSNode::globals_iterator I = SN->globals_begin(),
         E = SN->globals_end(); I != E; ++I) {
      const GlobalValue *GV = *I;
      const DSNodeHandle &SrcGNH = Src->getNodeForValue(GV);
      DSNodeHandle &DestGNH = NodeMap[SrcGNH.getNode()];
      assert(DestGNH.getNode()==NH.getNode() &&"Global mapping inconsistent");
      assert(SrcGNH.getNode() == SN && "Global mapping inconsistent");
      Dest->getNodeForValue(GV).mergeWith(DSNodeHandle(DestGNH.getNode(),
                                                       DestGNH.getOffset()+SrcGNH.getOffset()));
    }
  }

  //  DOUT << "LLVA: mergeWith: " << SN << " becomes " << DN << "\n";

  // Next, recursively merge all outgoing links as necessary.  Note that
  // adding these links can cause the destination node to collapse itself at
  // any time, and the current node may be merged with arbitrary other nodes.
  // For this reason, we must always go through NH.
  DN = 0;
  for (DSNode::const_edge_iterator ii = SN->edge_begin(), ee = SN->edge_end();
       ii != ee; ++ii) {
    const DSNodeHandle &SrcEdge = ii->second;
    if (!SrcEdge.isNull()) {
      // Compute the offset into the current node at which to
      // merge this link.  In the common case, this is a linear
      // relation to the offset in the original node (with
      // wrapping), but if the current node gets collapsed due to
      // recursive merging, we must make sure to merge in all remaining
      // links at offset zero.
      DSNode *CN = SCNH.getNode();
      unsigned MergeOffset = (ii->first+SCNH.getOffset()) % CN->getSize();

      DSNodeHandle Tmp = CN->getLink(MergeOffset);
      if (!Tmp.isNull()) {
        // Perform the recursive merging.  Make sure to create a temporary NH,
        // because the Link can disappear in the process of recursive merging.
        merge(Tmp, SrcEdge);
      } else {
        Tmp.mergeWith(getClonedNH(SrcEdge));
        // Merging this could cause all kinds of recursive things to happen,
        // culminating in the current node being eliminated.  Since this is
        // possible, make sure to reaquire the link from 'CN'.

        unsigned MergeOffset = 0;
        CN = SCNH.getNode();
        MergeOffset = (ii->first + SCNH.getOffset()) % CN->getSize();
        CN->getLink(MergeOffset).mergeWith(Tmp);
      }
    }
  }
}

/// mergeCallSite - Merge the nodes reachable from the specified src call
/// site into the nodes reachable from DestCS.
void ReachabilityCloner::mergeCallSite(DSCallSite &DestCS,
                                       const DSCallSite &SrcCS) {
  merge(DestCS.getRetVal(), SrcCS.getRetVal());
  merge(DestCS.getVAVal(), SrcCS.getVAVal());
  unsigned MinArgs = DestCS.getNumPtrArgs();
  if (SrcCS.getNumPtrArgs() < MinArgs) MinArgs = SrcCS.getNumPtrArgs();

  for (unsigned a = 0; a != MinArgs; ++a)
    merge(DestCS.getPtrArg(a), SrcCS.getPtrArg(a));

  for (unsigned a = MinArgs, e = SrcCS.getNumPtrArgs(); a != e; ++a) {
    // If a call site passes more params, ignore the extra params.
    // If the called function is varargs, merge the extra params, with
    // the varargs node.
    if(DestCS.getVAVal() != NULL) {
      merge(DestCS.getVAVal(), SrcCS.getPtrArg(a));
    }
  }

  for (unsigned a = MinArgs, e = DestCS.getNumPtrArgs(); a!=e; ++a) {
    // If a call site passes less explicit params, than the function needs
    // But passes params through a varargs node, merge those in.
    if(SrcCS.getVAVal() != NULL)  {
      merge(DestCS.getPtrArg(a), SrcCS.getVAVal());
    }
  }
}

DSCallSite ReachabilityCloner::cloneCallSite(const DSCallSite& SrcCS) {
  std::vector<DSNodeHandle> Args;
  for(unsigned x = 0; x < SrcCS.getNumPtrArgs(); ++x)
    Args.push_back(getClonedNH(SrcCS.getPtrArg(x)));
  if (SrcCS.isDirectCall())
    return DSCallSite(SrcCS.getCallSite(),
                      getClonedNH(SrcCS.getRetVal()),
                      getClonedNH(SrcCS.getVAVal()),
                      SrcCS.getCalleeFunc(),
                      Args);
  else {
    DSNodeHandle Ret = getClonedNH(SrcCS.getRetVal()),
                 VA = getClonedNH(SrcCS.getVAVal()),
                 Callee = getClonedNH(SrcCS.getCalleeNode());
    // Resolve forwarding now as much as possible.
    Ret.getNode(); VA.getNode();
    // Most importantly, ensure the node passed to DSCallSite
    // is not a forwarding node:
    DSNode * CalleeN = Callee.getNode();
    return DSCallSite(SrcCS.getCallSite(), Ret, VA, CalleeN, Args);
  }
}

//===----------------------------------------------------------------------===//
// DSCallSite Implementation
//===----------------------------------------------------------------------===//

// Define here to avoid including iOther.h and BasicBlock.h in DSGraph.h
const Function &DSCallSite::getCaller() const {
  return *Site.getInstruction()->getParent()->getParent();
}

void DSCallSite::InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
                        ReachabilityCloner &RC) {
  NH = RC.getClonedNH(Src);
}

/// FunctionTypeOfCallSite - Helper method to extract the signature of a function
/// that is called a given CallSite
///
const FunctionType *DSCallSite::FunctionTypeOfCallSite(const CallSite & Site) {
  Value *Callee = Site.getCalledValue();

  // Direct call, simple
  if (Function *F = dyn_cast<Function>(Callee))
    return F->getFunctionType();

  // Indirect call, extract the type
  const FunctionType *CalleeFuncType = NULL;

  const PointerType *CalleeType = dyn_cast<PointerType>(Callee->getType());
  if (!CalleeType) {
    assert(0 && "Call through a non-pointer type?");
  } else {
    CalleeFuncType = dyn_cast<FunctionType>(CalleeType->getElementType());
    assert(CalleeFuncType &&
           "Call through pointer to non-function?");
  }

  return CalleeFuncType;
}

/// isVarArg - Determines if the call this represents is to a variable argument
/// function
///
bool DSCallSite::isVarArg() const {
  const FunctionType *FT = FunctionTypeOfCallSite(Site);
  return FT->isVarArg();
}

/// isUnresolvable - Determines if this call has properties that would
/// prevent it from ever being resolvded.  Put another way, no amount
/// additional information will make this callsite resolvable.
///
bool DSCallSite::isUnresolvable() const {
  // Direct calls are forever unresolvable if they are calls to declarations.
  if (isDirectCall())
    return getCalleeFunc()->isDeclaration();
  // Indirect calls are forever unresolvable if the call node is marked
  // external.
  // (Nodes can't become non-external through additional information)
  return getCalleeNode()->isExternFuncNode();
}

/// remapLinks - Change all of the Links in the current node according to the
/// specified mapping.
///
void DSNode::remapLinks(DSGraph::NodeMapTy &OldNodeMap) {
  for (LinkMapTy::iterator ii = edge_begin(), ee = edge_end();
       ii != ee; ++ii)
    if (DSNode *N = ii->second.getNode()) {
      DSGraph::NodeMapTy::const_iterator ONMI = OldNodeMap.find(N);
      if (ONMI != OldNodeMap.end()) {
        DSNode *ONMIN = ONMI->second.getNode();
        ii->second.setTo(ONMIN, ii->second.getOffset()+ONMI->second.getOffset());
      }
    }
}

/// markReachableNodes - This method recursively traverses the specified
/// DSNodes, marking any nodes which are reachable.  All reachable nodes it adds
/// to the set, which allows it to only traverse visited nodes once.
///
void DSNode::markReachableNodes(DenseSet<const DSNode*> &ReachableNodes) const {
  if (this == 0) return;
  assert(!isForwarding() && "Cannot mark a forwarded node!");
  if (ReachableNodes.insert(this).second) // Is newly reachable?
    for (DSNode::const_edge_iterator I = edge_begin(), E = edge_end();
         I != E; ++I)
      I->second.getNode()->markReachableNodes(ReachableNodes);
}

void DSCallSite::markReachableNodes(DenseSet<const DSNode*> &Nodes) const {
  getRetVal().getNode()->markReachableNodes(Nodes);
  getVAVal().getNode()->markReachableNodes(Nodes);
  if (isIndirectCall()) getCalleeNode()->markReachableNodes(Nodes);

  for (unsigned i = 0, e = getNumPtrArgs(); i != e; ++i)
    getPtrArg(i).getNode()->markReachableNodes(Nodes);
}

////////////////////////////////////////////////////////////////////////////////
//Base DataStructures impl:
////////////////////////////////////////////////////////////////////////////////

  static const Function *getFnForValue(const Value *V) {
    if (const Instruction *I = dyn_cast<Instruction>(V))
      return I->getParent()->getParent();
    else if (const Argument *A = dyn_cast<Argument>(V))
      return A->getParent();
    else if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
      return BB->getParent();
    return 0;
  }

/// deleteValue/copyValue - Interfaces to update the DSGraphs in the program.
/// These correspond to the interfaces defined in the AliasAnalysis class.
/// FIXME: Do these update all the datastructures needed?
/// FIXME: What exactly does it mean to tell DSA to 'copy' a value? or delete it? (particularly a function)
void DataStructures::deleteValue(Value *V) {
  if (const Function *F = getFnForValue(V)) {  // Function local value?
    // If this is a function local value, just delete it from the scalar map!
    getDSGraph(*F)->getScalarMap().eraseIfExists(V);
    return;
  }

  if (Function *F = dyn_cast<Function>(V)) {
    DSGraph *G = getDSGraph(*F);
    if (G->getReturnNodes().size() == 1) {
      // If this is function is part of its own SCC, just delete the graph for it
      delete G;
      DSInfo.erase(F);
    } else {
      // SCC case

      // Remove some of the graph's information about this function since it's no longer needed
      G->getReturnNodes().erase(F);
      G->getVANodes().erase(F);

      // Remove entry for the function, but don't delete the graph since others need it
      DSInfo.erase(F);

      // FIXME: Can more be done here? Is there a good way to remove from the SCC's graph more
      // of the information this function contributed?

    }

    return;
  }

  assert(!isa<GlobalVariable>(V) && "Do not know how to delete GV's yet!");

  assert(0 && "Unrecognized value!");
  abort();
}

void DataStructures::copyValue(Value *From, Value *To) {
  if (From == To) return;
  if (const Function *F = getFnForValue(From)) {  // Function local value?
    // If this is a function local value, just delete it from the scalar map!
    getDSGraph(*F)->getScalarMap().copyScalarIfExists(From, To);
    return;
  }

  if (Function *FromF = dyn_cast<Function>(From)) {
    Function *ToF = cast<Function>(To);
    assert(!DSInfo.count(ToF) && "New Function already exists!");
    DSGraph *G = getDSGraph(*FromF);
    if (G->getReturnNodes().size() == 1) {
      // Copy a single function by duplicating its dsgraph

      DSGraph *NG = new DSGraph(getDSGraph(*FromF), GlobalECs, *TypeSS);
      DSInfo[ToF] = NG;

      // Change the Function* is the returnnodes map to the ToF.
      DSNodeHandle Ret = NG->retnodes_begin()->second;
      NG->getReturnNodes().clear();
      NG->getReturnNodes()[ToF] = Ret;

      // Change the Function* in the vanodes map to the ToF
      DSNodeHandle VA = NG->vanodes_begin()->second;
      NG->getVANodes().clear();
      NG->getVANodes()[ToF] = VA;
    } else {
      // A copy request on a function that's part of an SCC, we just map the new function to the same information

      // G is the graph for ToF as well (add it to the SCC)
      setDSGraph(*ToF,G);

      // Map ToF to the same return/va nodes as FromF
      G->getReturnNodes()[ToF] = G->getReturnNodes()[FromF];
      G->getVANodes()[ToF] = G->getVANodes()[FromF];
    }

    return;
  }

  if (const Function *F = getFnForValue(To)) {
    getDSGraph(*F)->getScalarMap().copyScalarIfExists(From, To);
    return;
  }

  errs() << *From;
  errs() << *To;
  assert(0 && "Do not know how to copy this yet!");
  abort();
}

DSGraph* DataStructures::getOrCreateGraph(const Function* F) {
  assert(F && "No function");
  DSGraph *&G = DSInfo[F];
  if (!G) {
    assert (F->isDeclaration() || GraphSource->hasDSGraph(*F));
    //Clone or Steal the Source Graph
    DSGraph* BaseGraph = GraphSource->getDSGraph(*F);
    if (Clone) {
      G = new DSGraph(BaseGraph, GlobalECs, *TypeSS);
      if (resetAuxCalls)
        G->getAuxFunctionCalls() = G->getFunctionCalls();
    } else {
      G = new DSGraph(GlobalECs, GraphSource->getDataLayout(), *TypeSS);
      G->spliceFrom(BaseGraph);
      if (resetAuxCalls)
        G->getAuxFunctionCalls() = G->getFunctionCalls();
    }
    G->setUseAuxCalls();
    G->setGlobalsGraph(GlobalsGraph);

    // Note that this graph is the graph for ALL of the function in the SCC, not
    // just F.
    for (DSGraph::retnodes_iterator RI = G->retnodes_begin(),
         E = G->retnodes_end(); RI != E; ++RI)
      if (RI->first != F)
        DSInfo[RI->first] = G;
  }
  return G;
}

void DataStructures::formGlobalFunctionList() {
  std::vector<const Function*> List;
  DSScalarMap &SN = GlobalsGraph->getScalarMap();
  EquivalenceClasses<const GlobalValue*> &EC = GlobalsGraph->getGlobalECs();
  for (DSScalarMap::global_iterator I = SN.global_begin(), E = SN.global_end(); I != E; ++I) {
    EquivalenceClasses<const GlobalValue*>::iterator ECI = EC.findValue(*I);
    if (ECI == EC.end()) {
      if (const Function *F = dyn_cast<Function>(*I))
        List.push_back(F);
    } else {
      for (EquivalenceClasses<const GlobalValue*>::member_iterator MI =
           EC.member_begin(ECI), ME = EC.member_end(); MI != ME; ++MI){
        if (const Function *F = dyn_cast<Function>(*MI))
          List.push_back(F);
      }
    }
  }
  GlobalFunctionList.swap(List);
}


void DataStructures::formGlobalECs() {
  // Grow the equivalence classes for the globals to include anything that we
  // now know to be aliased.
  svset<const GlobalValue*> ECGlobals;
  buildGlobalECs(ECGlobals);
  if (!ECGlobals.empty()) {
    DEBUG(errs() << "Eliminating " << ECGlobals.size() << " EC Globals!\n");
    for (DSInfoTy::iterator I = DSInfo.begin(),
         E = DSInfo.end(); I != E; ++I)
      eliminateUsesOfECGlobals(*I->second, ECGlobals);
  }
}

/// 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.
void DataStructures::buildGlobalECs(svset<const GlobalValue*> &ECGlobals) {
  DSScalarMap &SM = GlobalsGraph->getScalarMap();
  EquivalenceClasses<const GlobalValue*> &GlobalECs = SM.getGlobalECs();
  for (DSGraph::node_iterator I = GlobalsGraph->node_begin(), 
       E = GlobalsGraph->node_end();
       I != E; ++I) {
    if (I->numGlobals() <= 1) continue;

    // First, build up the equivalence set for this block of globals.
    DSNode::globals_iterator i = I->globals_begin(); 
    const GlobalValue *First = *i;
    if (GlobalECs.findValue(*i) != GlobalECs.end())
      First = GlobalECs.getLeaderValue(*i);
    if (*i == First) ++i;
    for( ; i != I->globals_end(); ++i) {
      GlobalECs.unionSets(First, *i);
      ECGlobals.insert(*i);
      if (SM.find(*i) != SM.end())
        SM.erase(SM.find(*i));
      else
        errs() << "Global missing in scalar map " << (*i)->getName() << "\n";
    }

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

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

  DEBUG(GlobalsGraph->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.
void DataStructures::eliminateUsesOfECGlobals(DSGraph &G,
                                              const svset<const GlobalValue*> &ECGlobals) {
  DSScalarMap &SM = G.getScalarMap();
  EquivalenceClasses<const GlobalValue*> &GlobalECs = SM.getGlobalECs();

#ifndef NDEBUG
  bool MadeChange = false;
#endif
  std::vector<const GlobalValue*> SMGVV(SM.global_begin(), SM.global_end());

  for (std::vector<const GlobalValue*>::iterator GI = SMGVV.begin(),
       E = SMGVV.end(); GI != E; ) {
    const GlobalValue *GV = *GI; ++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.
    const 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);
#ifndef NDEBUG
    MadeChange = true;
#endif
  }

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

//For Entry Points
void DataStructures::cloneGlobalsInto(DSGraph* Graph, unsigned cloneFlags) {
  // If this graph contains main, copy the contents of the globals graph over.
  // Note that this is *required* for correctness.  If a callee contains a use
  // of a global, we have to make sure to link up nodes due to global-argument
  // bindings.
  const DSGraph* GG = Graph->getGlobalsGraph();
  ReachabilityCloner RC(Graph, GG, cloneFlags);

  // Clone the global nodes into this graph.
  for (DSScalarMap::global_iterator I = Graph->getScalarMap().global_begin(),
       E = Graph->getScalarMap().global_end(); I != E; ++I)
    RC.getClonedNH(GG->getNodeForValue(*I));
}

//For all graphs
void DataStructures::cloneIntoGlobals(DSGraph* Graph, unsigned cloneFlags) {
  // When this graph is finalized, clone the globals in the graph into the
  // globals graph to make sure it has everything, from all graphs.
  DSScalarMap &MainSM = Graph->getScalarMap();
  ReachabilityCloner RC(GlobalsGraph, Graph, cloneFlags);

  // Clone everything reachable from globals in the function graph into the
  // globals graph.
  for (DSScalarMap::global_iterator I = MainSM.global_begin(),
       E = MainSM.global_end(); I != E; ++I)
    RC.getClonedNH(MainSM[*I]);
}


void DataStructures::init(DataStructures* D, bool clone, bool useAuxCalls, 
                          bool copyGlobalAuxCalls, bool resetAux) {
  assert (!GraphSource && "Already init");
  GraphSource = D;
  Clone = clone;
  resetAuxCalls = resetAux;
  TD = D->TD;
  TypeSS = D->TypeSS;
  callgraph = D->callgraph;
  GlobalFunctionList = D->GlobalFunctionList;
  GlobalECs = D->getGlobalECs();
  GlobalsGraph = new DSGraph(D->getGlobalsGraph(), GlobalECs, *TypeSS,
                             copyGlobalAuxCalls? DSGraph::CloneAuxCallNodes
                             :DSGraph::DontCloneAuxCallNodes);
  if (useAuxCalls) GlobalsGraph->setUseAuxCalls();

  //
  // Tell the other DSA pass if we're stealing its graph.
  //
  if (!clone) D->DSGraphsStolen = true;
}

void DataStructures::init(const DataLayout* T) {
  assert (!TD && "Already init");
  GraphSource = 0;
  Clone = false;
  TD = T;
  TypeSS = new SuperSet<Type*>();
  GlobalsGraph = new DSGraph(GlobalECs, *T, *TypeSS);
}

// CBU has the correct call graph. All the passes that follow it 
// must resotre the call graph, at the end, so that it it correct.
// This is simpler than keeping all the CBU data structures around.
// EQBU and subsequent passes must call this.
void DataStructures::restoreCorrectCallGraph(){
  callgraph = GraphSource->callgraph;
}

void DataStructures::releaseMemory() {
  //
  // If the DSGraphs were stolen by another pass, free nothing.
  //
  if (DSGraphsStolen) return;

  std::set<DSGraph*> toDelete;
  for (DSInfoTy::iterator I = DSInfo.begin(), E = DSInfo.end(); I != E; ++I) {
    I->second->getReturnNodes().clear();
    toDelete.insert(I->second);
  }
  for (std::set<DSGraph*>::iterator I = toDelete.begin(), E = toDelete.end(); I != E; ++I)
    delete *I;

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

  delete GlobalsGraph;
  GlobalsGraph = 0;
}
