//=-- ExplodedGraph.cpp - Local, Path-Sens. "Exploded Graph" -*- C++ -*------=//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the template classes ExplodedNode and ExplodedGraph,
//  which represent a path-sensitive, intra-procedural "exploded graph."
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "clang/AST/Stmt.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
#include <list>

using namespace clang;

//===----------------------------------------------------------------------===//
// Node auditing.
//===----------------------------------------------------------------------===//

// An out of line virtual method to provide a home for the class vtable.
ExplodedNodeImpl::Auditor::~Auditor() {}

#ifndef NDEBUG
static ExplodedNodeImpl::Auditor* NodeAuditor = 0;
#endif

void ExplodedNodeImpl::SetAuditor(ExplodedNodeImpl::Auditor* A) {
#ifndef NDEBUG
  NodeAuditor = A;
#endif
}

//===----------------------------------------------------------------------===//
// ExplodedNodeImpl.
//===----------------------------------------------------------------------===//

static inline std::vector<ExplodedNodeImpl*>& getVector(void* P) {
  return *reinterpret_cast<std::vector<ExplodedNodeImpl*>*>(P);
}

void ExplodedNodeImpl::addPredecessor(ExplodedNodeImpl* V) {
  assert (!V->isSink());
  Preds.addNode(V);
  V->Succs.addNode(this);
#ifndef NDEBUG
  if (NodeAuditor) NodeAuditor->AddEdge(V, this);
#endif
}

void ExplodedNodeImpl::NodeGroup::addNode(ExplodedNodeImpl* N) {
  
  assert ((reinterpret_cast<uintptr_t>(N) & Mask) == 0x0);
  assert (!getFlag());
  
  if (getKind() == Size1) {
    if (ExplodedNodeImpl* NOld = getNode()) {
      std::vector<ExplodedNodeImpl*>* V = new std::vector<ExplodedNodeImpl*>();
      assert ((reinterpret_cast<uintptr_t>(V) & Mask) == 0x0);
      V->push_back(NOld);
      V->push_back(N);
      P = reinterpret_cast<uintptr_t>(V) | SizeOther;
      assert (getPtr() == (void*) V);
      assert (getKind() == SizeOther);
    }
    else {
      P = reinterpret_cast<uintptr_t>(N);
      assert (getKind() == Size1);
    }
  }
  else {
    assert (getKind() == SizeOther);
    getVector(getPtr()).push_back(N);
  }
}


unsigned ExplodedNodeImpl::NodeGroup::size() const {
  if (getFlag())
    return 0;
  
  if (getKind() == Size1)
    return getNode() ? 1 : 0;
  else
    return getVector(getPtr()).size();
}

ExplodedNodeImpl** ExplodedNodeImpl::NodeGroup::begin() const {
  if (getFlag())
    return NULL;
  
  if (getKind() == Size1)
    return (ExplodedNodeImpl**) (getPtr() ? &P : NULL);
  else
    return const_cast<ExplodedNodeImpl**>(&*(getVector(getPtr()).begin()));
}

ExplodedNodeImpl** ExplodedNodeImpl::NodeGroup::end() const {
  if (getFlag())
    return NULL;
  
  if (getKind() == Size1)
    return (ExplodedNodeImpl**) (getPtr() ? &P+1 : NULL);
  else {
    // Dereferencing end() is undefined behaviour. The vector is not empty, so
    // we can dereference the last elem and then add 1 to the result.
    return const_cast<ExplodedNodeImpl**>(&getVector(getPtr()).back()) + 1;
  }
}

ExplodedNodeImpl::NodeGroup::~NodeGroup() {
  if (getKind() == SizeOther) delete &getVector(getPtr());
}

ExplodedGraphImpl* ExplodedGraphImpl::Trim(ExplodedNodeImpl** BeginSources,
                                           ExplodedNodeImpl** EndSources) const{
  
  typedef llvm::DenseMap<ExplodedNodeImpl*, ExplodedNodeImpl*> Pass1Ty;
  typedef llvm::DenseMap<ExplodedNodeImpl*, ExplodedNodeImpl*> Pass2Ty;
  
  Pass1Ty Pass1;
  Pass2Ty Pass2;
  
  llvm::SmallVector<ExplodedNodeImpl*, 10> WL2;

  { // ===- Pass 1 (reverse BFS) -===
    
    // Enqueue the source nodes to the first worklist. 
    
    std::list<std::pair<ExplodedNodeImpl*, ExplodedNodeImpl*> > WL1;
    std::list<std::pair<ExplodedNodeImpl*, ExplodedNodeImpl*> > WL1_Loops;
  
    for (ExplodedNodeImpl** I = BeginSources; I != EndSources; ++I)
      WL1.push_back(std::make_pair(*I, *I));
    
    // Process the worklist.

    while (! (WL1.empty() && WL1_Loops.empty())) {
      
      ExplodedNodeImpl *N, *Src;

      // Only dequeue from the "loops" worklist if WL1 has no items.
      // Thus we prioritize for paths that don't span loop boundaries.
      
      if (WL1.empty()) {
        N = WL1_Loops.back().first;
        Src = WL1_Loops.back().second;
        WL1_Loops.pop_back();
      }
      else {
        N = WL1.back().first;
        Src = WL1.back().second;
        WL1.pop_back();
      }      
      
      if (Pass1.find(N) != Pass1.end())
        continue;
      
      bool PredHasSameSource = false;
      bool VisitPreds = true;
            
      for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
            I!=E; ++I) {
        
        Pass1Ty::iterator pi = Pass1.find(*I);
        
        if (pi == Pass1.end())
          continue;
        
        VisitPreds = false;
        
        if (pi->second == Src) {
          PredHasSameSource = true;
          break;
        }
      }
      
      if (VisitPreds || !PredHasSameSource) {
        
        Pass1[N] = Src;
      
        if (N->Preds.empty()) {
          WL2.push_back(N);
          continue;      
        }
      }
      else
        Pass1[N] = NULL;
      
      if (VisitPreds)
        for (ExplodedNodeImpl** I=N->Preds.begin(), **E=N->Preds.end();
             I!=E; ++I) {
          
          ProgramPoint P = Src->getLocation();
          
          if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P))
            if (Stmt* T = BE->getSrc()->getTerminator())
              switch (T->getStmtClass()) {
                default: break;
                case Stmt::ForStmtClass:
                case Stmt::WhileStmtClass:
                case Stmt::DoStmtClass:
                  WL1_Loops.push_front(std::make_pair(*I, Src));
                  continue;
                  
              }
          
          WL1.push_front(std::make_pair(*I, Src));
        }
    }
  }
  
  if (WL2.empty())
    return NULL;
    
  ExplodedGraphImpl* G = MakeEmptyGraph();
  
  // ===- Pass 2 (forward DFS to construct the new graph) -===
  
  while (!WL2.empty()) {
    
    ExplodedNodeImpl* N = WL2.back();
    WL2.pop_back();
    
    // Skip this node if we have already processed it.
    
    if (Pass2.find(N) != Pass2.end())
      continue;
    
    // Create the corresponding node in the new graph.
    
    ExplodedNodeImpl* NewN = G->getNodeImpl(N->getLocation(), N->State, NULL);
    Pass2[N] = NewN;
    
    if (N->Preds.empty())
      G->addRoot(NewN);
    
    // In the case that some of the intended predecessors of NewN have already
    // been created, we should hook them up as predecessors.
    
    for (ExplodedNodeImpl **I=N->Preds.begin(), **E=N->Preds.end(); I!=E; ++I) {
        
      Pass2Ty::iterator PI = Pass2.find(*I);

      if (PI == Pass2.end())
        continue;
      
      NewN->addPredecessor(PI->second);
    }

    // In the case that some of the intended successors of NewN have already
    // been created, we should hook them up as successors.  Otherwise, enqueue
    // the new nodes from the original graph that should have nodes created
    // in the new graph.
   
    for (ExplodedNodeImpl **I=N->Succs.begin(), **E=N->Succs.end(); I!=E; ++I) {
      
      Pass2Ty::iterator PI = Pass2.find(*I);
      
      if (PI != Pass2.end()) {
        PI->second->addPredecessor(NewN);
        continue;
      }

      // Enqueue nodes to the worklist that were marked during pass 1.
      
      Pass1Ty::iterator pi = Pass1.find(*I);
      
      if (pi == Pass1.end() || pi->second == NULL)
        continue;
            
      WL2.push_back(*I);
    }
    
    if (N->isSink())
      NewN->markAsSink();
  }
    
  return G;
}
