#ifndef __TRANSITIVE__DEF__USE__HPP
#define __TRANSITIVE__DEF__USE__HPP

#include "llvm/Pass.h"
#include <tr1/unordered_map>
#include <tr1/unordered_set>

#include <boost/functional/hash.hpp>

#include <deque>
#include <set>
#include <utility>

namespace llvm
{
  class Argument;
  class CallInst;
  class Instruction;
}

typedef std::deque<llvm::Value*> worklist_t;
typedef std::tr1::unordered_set<llvm::Value*> use_set;
typedef std::tr1::unordered_map<const llvm::Value*, use_set> use_map;
typedef std::tr1::unordered_set<llvm::Argument*> aset;
typedef std::pair<llvm::Value*, llvm::CallInst*> argument_key;
typedef std::tr1::unordered_map<const argument_key, aset, boost::hash<argument_key> > amap;

struct TransitiveDefUse : public llvm::ModulePass
{
public:
  static char ID;

  TransitiveDefUse();

  virtual bool runOnModule(llvm::Module &M);
  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;

  const use_set& getTDUChain(llvm::Value* V) const;
  // Returns NULL if the call was through a function pointer
  // Returns a set otherwise (NULL entries in the set indicate varargs)
  const aset* getTDUArgSet(llvm::Value* V, llvm::CallInst* CI) const;

private:
  void calculateFunctionTDU(llvm::Function* F);
  void calculateValueTDU(llvm::Value* V);

private:
  worklist_t _worklist;
  use_map _tuses;
  use_map _rdeps;
  amap _targs;
};


#endif // __TRANSITIVE__DEF__USE__HPP
