//== GlobalCallGraph.cpp - Call graph building ------------------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defined the CallGraph and CGBuilder classes.
//
//===----------------------------------------------------------------------===//

#include "clang/Index/GlobalCallGraph.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtVisitor.h"

#include "llvm/Support/GraphWriter.h"

using namespace clang::idx;
using clang::FunctionDecl;
using clang::DeclContext;
using clang::ASTContext;

namespace {
class CGBuilder : public StmtVisitor<CGBuilder> {

  CallGraph &G;
  FunctionDecl *FD;

  Entity CallerEnt;

  CallGraphNode *CallerNode;

public:
  CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
    : G(g), FD(fd), CallerEnt(E), CallerNode(N) {}

  void VisitStmt(Stmt *S) { VisitChildren(S); }

  void VisitCallExpr(CallExpr *CE);

  void VisitChildren(Stmt *S) {
    for (Stmt::child_range I = S->children(); I; ++I)
      if (*I)
        static_cast<CGBuilder*>(this)->Visit(*I);
  }
};
}

void CGBuilder::VisitCallExpr(CallExpr *CE) {
  if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
    Entity Ent = Entity::get(CalleeDecl, G.getProgram());
    CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
    CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
  }
}

CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
  ExternalCallingNode = getOrInsertFunction(Entity());
}

CallGraph::~CallGraph() {
  if (!FunctionMap.empty()) {
    for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
        I != E; ++I)
      delete I->second;
    FunctionMap.clear();
  }
}

void CallGraph::addTU(ASTContext& Ctx) {
  DeclContext *DC = Ctx.getTranslationUnitDecl();
  for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
       I != E; ++I) {

    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
      if (FD->doesThisDeclarationHaveABody()) {
        // Set caller's ASTContext.
        Entity Ent = Entity::get(FD, Prog);
        CallGraphNode *Node = getOrInsertFunction(Ent);
        CallerCtx[Node] = &Ctx;

        // If this function has external linkage, anything could call it.
        if (FD->isGlobal())
          ExternalCallingNode->addCallee(idx::ASTLocation(), Node);

        // Set root node to 'main' function.
        if (FD->getNameAsString() == "main")
          Root = Node;

        CGBuilder builder(*this, FD, Ent, Node);
        builder.Visit(FD->getBody());
      }
    }
  }
}

CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
  CallGraphNode *&Node = FunctionMap[F];
  if (Node)
    return Node;

  return Node = new CallGraphNode(F);
}

Decl *CallGraph::getDecl(CallGraphNode *Node) {
  // Get the function's context.
  ASTContext *Ctx = CallerCtx[Node];

  return Node->getDecl(*Ctx);
}

void CallGraph::print(raw_ostream &os) {
  for (iterator I = begin(), E = end(); I != E; ++I) {
    if (I->second->hasCallee()) {
      os << "function: " << I->first.getPrintableName()
         << " calls:\n";
      for (CallGraphNode::iterator CI = I->second->begin(),
             CE = I->second->end(); CI != CE; ++CI) {
        os << "    " << CI->second->getName();
      }
      os << '\n';
    }
  }
}

void CallGraph::dump() {
  print(llvm::errs());
}

void CallGraph::ViewCallGraph() const {
  llvm::ViewGraph(*this, "CallGraph");
}

namespace llvm {

template <>
struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {

  DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}

  static std::string getNodeLabel(const CallGraphNode *Node,
                                  const CallGraph &CG) {
    return Node->getName();

  }

};

}
