#ifndef __INTERPROCEDURAL__DEF__USE__HPP
#define __INTERPROCEDURAL__DEF__USE__HPP

#include "TransitiveDefUse.hpp"

#include "llvm/Pass.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Support/InstVisitor.h"

namespace llvm
{
  class Function;
}

class TransitiveDefUse;

struct InterproceduralDefUse : public llvm::CallGraphSCCPass
{
public:
  static char ID;

  InterproceduralDefUse();
  
  virtual bool doInitialization(llvm::CallGraph & CG);
  virtual bool runOnSCC(const std::vector<llvm::CallGraphNode *> &SCCM);
  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;
  virtual bool doFinalization(llvm::CallGraph &CG);

  const use_set& getIDUChain(llvm::Value* V) const;
  const aset* getIDUArgSet(llvm::Value* V, llvm::CallInst* CI) const;
  
private:
  bool mergeFunctionTDU(llvm::Function* F);
  bool mergeValueTDU(llvm::Value* V);

  bool mergeFunctionTDUArgSet(llvm::Function* F);
  bool mergeValueTDUArgSet(llvm::Value* V);
  void addArgumentTDUSets(llvm::Function* F, llvm::CallInst* CI);
  void addLocalTDUArgSet(llvm::Value* V);
  bool descendTDUArgSet(llvm::Value* V, llvm::CallInst* CI,
                        const aset& arguses, const use_set& uses);
  
private:
  TransitiveDefUse* _TDU;
  use_map _iuses;
  amap _iargs;
};

#endif // __INTERPROCEDURAL__DEF__USE__HPP
