#ifndef __ALLOCATOR__ANALYSIS__HPP
#define __ALLOCATOR__ANALYSIS__HPP

#include "CommonTypes.hpp"

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

#include <boost/scoped_ptr.hpp>

class AliasHelper;
class EscapeAnalysis;

namespace llvm
{
  class Function;
  class Value;
}

/*!
  TODO: Consider cases where an allocator does not return
  its allocation on the stack, but returns it through an
  output parameter.

  The gamin library has some code like this (although, in
  that case, it is a static, internal only, function).
 */
struct AllocatorAnalysis : public llvm::InstVisitor<AllocatorAnalysis>,
                           public llvm::CallGraphSCCPass
{
  static char ID;
  results_t * _res;
 
  AllocatorAnalysis(results_t * res = NULL);

  // InstVisitor
  void visitCallInst(llvm::CallInst &CI);
  void visitReturnInst(llvm::ReturnInst &RI);

  // CallGraphSCC Pass
  virtual bool onInitialize(llvm::CallGraph & CG);
  virtual bool runOnSCC(const std::vector<llvm::CallGraphNode *> &SCCM);
  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;

  
private:    
  void checkAllocator(llvm::Function &F);
  bool isHeapAllocation(const llvm::Value * v,
                        std::set<const llvm::Function*> & allocators) const;
  void resetStateVariables();

private:
  boost::scoped_ptr<AliasHelper> _AH;
  const EscapeAnalysis * _E;

  // Reset
  value_set functionResults;
  llvm::Value* returnValue;
};
#endif // __ALLOCATOR__ANALYSIS__HPP
