//===- CompleteBottomUp.cpp - Complete Bottom-Up Data Structure Graphs ----===//
// 
//                     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 is the exact same as the bottom-up graphs, but we use take a completed
// call graph and inline all indirect callees into their callers graphs, making
// the result more useful for things like pool allocation.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Module.h"
#include "llvm/Analysis/DSGraph.h"
using namespace llvm;

namespace {
  RegisterAnalysis<CompleteBUDataStructures>
  X("cbudatastructure", "'Complete' Bottom-up Data Structure Analysis");
}

using namespace DS;

// run - Calculate the bottom up data structure graphs for each function in the
// program.
//
bool CompleteBUDataStructures::run(Module &M) {
  BUDataStructures &BU = getAnalysis<BUDataStructures>();
  GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
  GlobalsGraph->setPrintAuxCalls();

  // Our call graph is the same as the BU data structures call graph
  ActualCallees = BU.getActualCallees();

#if 1   // REMOVE ME EVENTUALLY
  // FIXME: TEMPORARY (remove once finalization of indirect call sites in the
  // globals graph has been implemented in the BU pass)
  TDDataStructures &TD = getAnalysis<TDDataStructures>();

  // The call graph extractable from the TD pass is _much more complete_ and
  // trustable than that generated by the BU pass so far.  Until this is fixed,
  // we hack it like this:
  for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) {
    if (MI->isExternal()) continue;
    const std::vector<DSCallSite> &CSs = TD.getDSGraph(*MI).getFunctionCalls();

    for (unsigned CSi = 0, e = CSs.size(); CSi != e; ++CSi) {
      if (CSs[CSi].isIndirectCall()) {
        Instruction *TheCall = CSs[CSi].getCallSite().getInstruction();

        const std::vector<GlobalValue*> &Callees =
          CSs[CSi].getCalleeNode()->getGlobals();
        for (unsigned i = 0, e = Callees.size(); i != e; ++i)
          if (Function *F = dyn_cast<Function>(Callees[i]))
            ActualCallees.insert(std::make_pair(TheCall, F));
      }
    }
  }
#endif

  // Start by copying all of the BU data structures graphs over, verbatim.
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal()) {
      DSInfo[I] = new DSGraph(BU.getDSGraph(*I));
      DSInfo[I]->setGlobalsGraph(GlobalsGraph);
      DSInfo[I]->setPrintAuxCalls();
    }


  return false;
}
