//===- PassManagerT.h - Container for Passes --------------------*- C++ -*-===//
//
//                     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 file defines the PassManagerT class.  This class is used to hold,
// maintain, and optimize execution of Pass's.  The PassManager class ensures
// that analysis results are available before a pass runs, and that Pass's are
// destroyed when the PassManager is destroyed.
//
// The PassManagerT template is instantiated three times to do its job.  The
// public PassManager class is a Pimpl around the PassManagerT<Module> interface
// to avoid having all of the PassManager clients being exposed to the
// implementation details herein.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_PASSMANAGER_T_H
#define LLVM_PASSMANAGER_T_H

#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/Timer.h"
#include <algorithm>
#include <iostream>

namespace llvm {

//===----------------------------------------------------------------------===//
// Pass debugging information.  Often it is useful to find out what pass is
// running when a crash occurs in a utility.  When this library is compiled with
// debugging on, a command line option (--debug-pass) is enabled that causes the
// pass name to be printed before it executes.
//

// Different debug levels that can be enabled...
enum PassDebugLevel {
  None, Arguments, Structure, Executions, Details
};

static cl::opt<enum PassDebugLevel>
PassDebugging("debug-pass", cl::Hidden,
              cl::desc("Print PassManager debugging information"),
              cl::values(
  clEnumVal(None      , "disable debug output"),
  clEnumVal(Arguments , "print pass arguments to pass to 'opt'"),
  clEnumVal(Structure , "print pass structure before run()"),
  clEnumVal(Executions, "print pass name before it is executed"),
  clEnumVal(Details   , "print pass details when it is executed"),
                         clEnumValEnd));

//===----------------------------------------------------------------------===//
// PMDebug class - a set of debugging functions, that are not to be
// instantiated by the template.
//
struct PMDebug {
  static void PerformPassStartupStuff(Pass *P) {
    // If debugging is enabled, print out argument information...
    if (PassDebugging >= Arguments) {
      std::cerr << "Pass Arguments: ";
      PrintArgumentInformation(P);
      std::cerr << "\n";

      // Print the pass execution structure
      if (PassDebugging >= Structure)
        P->dumpPassStructure();
    }
  }

  static void PrintArgumentInformation(const Pass *P);
  static void PrintPassInformation(unsigned,const char*,Pass *, Module *);
  static void PrintPassInformation(unsigned,const char*,Pass *, Function *);
  static void PrintPassInformation(unsigned,const char*,Pass *, BasicBlock *);
  static void PrintAnalysisSetInfo(unsigned,const char*,Pass *P,
                                   const std::vector<AnalysisID> &);
};


//===----------------------------------------------------------------------===//
// TimingInfo Class - This class is used to calculate information about the
// amount of time each pass takes to execute.  This only happens when
// -time-passes is enabled on the command line.
//

class TimingInfo {
  std::map<Pass*, Timer> TimingData;
  TimerGroup TG;

  // Private ctor, must use 'create' member
  TimingInfo() : TG("... Pass execution timing report ...") {}
public:
  // TimingDtor - Print out information about timing information
  ~TimingInfo() {
    // Delete all of the timers...
    TimingData.clear();
    // TimerGroup is deleted next, printing the report.
  }

  // createTheTimeInfo - This method either initializes the TheTimeInfo pointer
  // to a non null value (if the -time-passes option is enabled) or it leaves it
  // null.  It may be called multiple times.
  static void createTheTimeInfo();

  void passStarted(Pass *P) {
    if (dynamic_cast<AnalysisResolver*>(P)) return;
    std::map<Pass*, Timer>::iterator I = TimingData.find(P);
    if (I == TimingData.end())
      I=TimingData.insert(std::make_pair(P, Timer(P->getPassName(), TG))).first;
    I->second.startTimer();
  }
  void passEnded(Pass *P) {
    if (dynamic_cast<AnalysisResolver*>(P)) return;
    std::map<Pass*, Timer>::iterator I = TimingData.find(P);
    assert (I != TimingData.end() && "passStarted/passEnded not nested right!");
    I->second.stopTimer();
  }
};

static TimingInfo *TheTimeInfo;

//===----------------------------------------------------------------------===//
// Declare the PassManagerTraits which will be specialized...
//
template<class UnitType> class PassManagerTraits;   // Do not define.


//===----------------------------------------------------------------------===//
// PassManagerT - Container object for passes.  The PassManagerT destructor
// deletes all passes contained inside of the PassManagerT, so you shouldn't
// delete passes manually, and all passes should be dynamically allocated.
//
template<typename UnitType>
class PassManagerT : public PassManagerTraits<UnitType>,public AnalysisResolver{
  typedef PassManagerTraits<UnitType> Traits;
  typedef typename Traits::PassClass       PassClass;
  typedef typename Traits::SubPassClass SubPassClass;
  typedef typename Traits::BatcherClass BatcherClass;
  typedef typename Traits::ParentClass   ParentClass;

#if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__HP_aCC)
  friend PassClass;
  friend SubPassClass;
#else
  friend class PassManagerTraits<UnitType>::PassClass;
  friend class PassManagerTraits<UnitType>::SubPassClass;
#endif
  friend class PassManagerTraits<UnitType>;
  friend class ImmutablePass;

  std::vector<PassClass*> Passes;    // List of passes to run
  std::vector<ImmutablePass*> ImmutablePasses;  // List of immutable passes

  // The parent of this pass manager...
  ParentClass * const Parent;

  // The current batcher if one is in use, or null
  BatcherClass *Batcher;

  // CurrentAnalyses - As the passes are being run, this map contains the
  // analyses that are available to the current pass for use.  This is accessed
  // through the getAnalysis() function in this class and in Pass.
  //
  std::map<AnalysisID, Pass*> CurrentAnalyses;

  // LastUseOf - This map keeps track of the last usage in our pipeline of a
  // particular pass.  When executing passes, the memory for .first is free'd
  // after .second is run.
  //
  std::map<Pass*, Pass*> LastUseOf;

public:
  PassManagerT(ParentClass *Par = 0) : Parent(Par), Batcher(0) {}
  ~PassManagerT() {
    // Delete all of the contained passes...
    for (typename std::vector<PassClass*>::iterator
           I = Passes.begin(), E = Passes.end(); I != E; ++I)
      delete *I;

    for (std::vector<ImmutablePass*>::iterator
           I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
      delete *I;
  }

  // run - Run all of the queued passes on the specified module in an optimal
  // way.
  virtual bool runOnUnit(UnitType *M) {
    bool MadeChanges = false;
    closeBatcher();
    CurrentAnalyses.clear();

    TimingInfo::createTheTimeInfo();

    // Add any immutable passes to the CurrentAnalyses set...
    for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
      ImmutablePass *IPass = ImmutablePasses[i];
      if (const PassInfo *PI = IPass->getPassInfo()) {
        CurrentAnalyses[PI] = IPass;

        const std::vector<const PassInfo*> &II = PI->getInterfacesImplemented();
        for (unsigned i = 0, e = II.size(); i != e; ++i)
          CurrentAnalyses[II[i]] = IPass;
      }
    }

    // LastUserOf - This contains the inverted LastUseOfMap...
    std::map<Pass *, std::vector<Pass*> > LastUserOf;
    for (std::map<Pass*, Pass*>::iterator I = LastUseOf.begin(),
                                          E = LastUseOf.end(); I != E; ++I)
      LastUserOf[I->second].push_back(I->first);

    // Output debug information...
    if (Parent == 0) PMDebug::PerformPassStartupStuff(this);

    // Run all of the passes
    for (unsigned i = 0, e = Passes.size(); i < e; ++i) {
      PassClass *P = Passes[i];

      PMDebug::PrintPassInformation(getDepth(), "Executing Pass", P, M);

      // Get information about what analyses the pass uses...
      AnalysisUsage AnUsage;
      P->getAnalysisUsage(AnUsage);
      PMDebug::PrintAnalysisSetInfo(getDepth(), "Required", P,
                                    AnUsage.getRequiredSet());

      // All Required analyses should be available to the pass as it runs!  Here
      // we fill in the AnalysisImpls member of the pass so that it can
      // successfully use the getAnalysis() method to retrieve the
      // implementations it needs.
      //
      P->AnalysisImpls.clear();
      P->AnalysisImpls.reserve(AnUsage.getRequiredSet().size());
      for (std::vector<const PassInfo *>::const_iterator
             I = AnUsage.getRequiredSet().begin(),
             E = AnUsage.getRequiredSet().end(); I != E; ++I) {
        Pass *Impl = getAnalysisOrNullUp(*I);
        if (Impl == 0) {
          std::cerr << "Analysis '" << (*I)->getPassName()
                    << "' used but not available!";
          assert(0 && "Analysis used but not available!");
        } else if (PassDebugging == Details) {
          if ((*I)->getPassName() != std::string(Impl->getPassName()))
            std::cerr << "    Interface '" << (*I)->getPassName()
                    << "' implemented by '" << Impl->getPassName() << "'\n";
        }
        P->AnalysisImpls.push_back(std::make_pair(*I, Impl));
      }

      // Run the sub pass!
      if (TheTimeInfo) TheTimeInfo->passStarted(P);
      bool Changed = runPass(P, M);
      if (TheTimeInfo) TheTimeInfo->passEnded(P);
      MadeChanges |= Changed;

      // Check for memory leaks by the pass...
      LeakDetector::checkForGarbage(std::string("after running pass '") +
                                    P->getPassName() + "'");

      if (Changed)
        PMDebug::PrintPassInformation(getDepth()+1, "Made Modification", P, M);
      PMDebug::PrintAnalysisSetInfo(getDepth(), "Preserved", P,
                                    AnUsage.getPreservedSet());


      // Erase all analyses not in the preserved set...
      if (!AnUsage.getPreservesAll()) {
        const std::vector<AnalysisID> &PreservedSet = AnUsage.getPreservedSet();
        for (std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.begin(),
               E = CurrentAnalyses.end(); I != E; )
          if (std::find(PreservedSet.begin(), PreservedSet.end(), I->first) !=
              PreservedSet.end())
            ++I; // This analysis is preserved, leave it in the available set...
          else {
            if (!dynamic_cast<ImmutablePass*>(I->second)) {
              std::map<AnalysisID, Pass*>::iterator J = I++;
              CurrentAnalyses.erase(J);   // Analysis not preserved!
            } else {
              ++I;
            }
          }
      }

      // Add the current pass to the set of passes that have been run, and are
      // thus available to users.
      //
      if (const PassInfo *PI = P->getPassInfo()) {
        CurrentAnalyses[PI] = P;

        // This pass is the current implementation of all of the interfaces it
        // implements as well.
        //
        const std::vector<const PassInfo*> &II = PI->getInterfacesImplemented();
        for (unsigned i = 0, e = II.size(); i != e; ++i)
          CurrentAnalyses[II[i]] = P;
      }

      // Free memory for any passes that we are the last use of...
      std::vector<Pass*> &DeadPass = LastUserOf[P];
      for (std::vector<Pass*>::iterator I = DeadPass.begin(),E = DeadPass.end();
           I != E; ++I) {
        PMDebug::PrintPassInformation(getDepth()+1, "Freeing Pass", *I, M);
        (*I)->releaseMemory();
      }

      // Make sure to remove dead passes from the CurrentAnalyses list...
      for (std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.begin();
           I != CurrentAnalyses.end(); ) {
        std::vector<Pass*>::iterator DPI = std::find(DeadPass.begin(),
                                                     DeadPass.end(), I->second);
        if (DPI != DeadPass.end()) {    // This pass is dead now... remove it
          std::map<AnalysisID, Pass*>::iterator IDead = I++;
          CurrentAnalyses.erase(IDead);
        } else {
          ++I;  // Move on to the next element...
        }
      }
    }

    return MadeChanges;
  }

  // dumpPassStructure - Implement the -debug-passes=PassStructure option
  virtual void dumpPassStructure(unsigned Offset = 0) {
    // Print out the immutable passes...
    for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i)
      ImmutablePasses[i]->dumpPassStructure(0);

    std::cerr << std::string(Offset*2, ' ') << Traits::getPMName()
              << " Pass Manager\n";
    for (typename std::vector<PassClass*>::iterator
           I = Passes.begin(), E = Passes.end(); I != E; ++I) {
      PassClass *P = *I;
      P->dumpPassStructure(Offset+1);

      // Loop through and see which classes are destroyed after this one...
      for (std::map<Pass*, Pass*>::iterator I = LastUseOf.begin(),
                                            E = LastUseOf.end(); I != E; ++I) {
        if (P == I->second) {
          std::cerr << "--" << std::string(Offset*2, ' ');
          I->first->dumpPassStructure(0);
        }
      }
    }
  }

  Pass *getImmutablePassOrNull(const PassInfo *ID) const {
    for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
      const PassInfo *IPID = ImmutablePasses[i]->getPassInfo();
      if (IPID == ID)
        return ImmutablePasses[i];

      // This pass is the current implementation of all of the interfaces it
      // implements as well.
      //
      const std::vector<const PassInfo*> &II =
        IPID->getInterfacesImplemented();
      for (unsigned j = 0, e = II.size(); j != e; ++j)
        if (II[j] == ID) return ImmutablePasses[i];
    }
    return 0;
  }

  Pass *getAnalysisOrNullDown(const PassInfo *ID) const {
    std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID);

    if (I != CurrentAnalyses.end())
      return I->second;  // Found it.

    if (Pass *P = getImmutablePassOrNull(ID))
      return P;

    if (Batcher)
      return ((AnalysisResolver*)Batcher)->getAnalysisOrNullDown(ID);
    return 0;
  }

  Pass *getAnalysisOrNullUp(const PassInfo *ID) const {
    std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(ID);
    if (I != CurrentAnalyses.end())
      return I->second;  // Found it.

    if (Parent)          // Try scanning...
      return Parent->getAnalysisOrNullUp(ID);
    else if (!ImmutablePasses.empty())
      return getImmutablePassOrNull(ID);
    return 0;
  }

  // markPassUsed - Inform higher level pass managers (and ourselves)
  // that these analyses are being used by this pass.  This is used to
  // make sure that analyses are not free'd before we have to use
  // them...
  //
  void markPassUsed(const PassInfo *P, Pass *User) {
    std::map<AnalysisID, Pass*>::const_iterator I = CurrentAnalyses.find(P);

    if (I != CurrentAnalyses.end()) {
      LastUseOf[I->second] = User;    // Local pass, extend the lifetime

      // Prolong live range of analyses that are needed after an analysis pass
      // is destroyed, for querying by subsequent passes
      AnalysisUsage AnUsage;
      I->second->getAnalysisUsage(AnUsage);
      const std::vector<AnalysisID> &IDs = AnUsage.getRequiredTransitiveSet();
      for (std::vector<AnalysisID>::const_iterator i = IDs.begin(),
             e = IDs.end(); i != e; ++i)
        markPassUsed(*i, User);

    } else {
      // Pass not in current available set, must be a higher level pass
      // available to us, propagate to parent pass manager...  We tell the
      // parent that we (the passmanager) are using the analysis so that it
      // frees the analysis AFTER this pass manager runs.
      //
      if (Parent) {
        Parent->markPassUsed(P, this);
      } else {
        assert(getAnalysisOrNullUp(P) &&
               dynamic_cast<ImmutablePass*>(getAnalysisOrNullUp(P)) &&
               "Pass available but not found! "
               "Perhaps this is a module pass requiring a function pass?");
      }
    }
  }

  // Return the number of parent PassManagers that exist
  virtual unsigned getDepth() const {
    if (Parent == 0) return 0;
    return 1 + Parent->getDepth();
  }

  virtual unsigned getNumContainedPasses() const { return Passes.size(); }
  virtual const Pass *getContainedPass(unsigned N) const {
    assert(N < Passes.size() && "Pass number out of range!");
    return Passes[N];
  }

  // add - Add a pass to the queue of passes to run.  This gives ownership of
  // the Pass to the PassManager.  When the PassManager is destroyed, the pass
  // will be destroyed as well, so there is no need to delete the pass.  This
  // implies that all passes MUST be new'd.
  //
  void add(PassClass *P) {
    // Get information about what analyses the pass uses...
    AnalysisUsage AnUsage;
    P->getAnalysisUsage(AnUsage);
    const std::vector<AnalysisID> &Required = AnUsage.getRequiredSet();

    // Loop over all of the analyses used by this pass,
    for (std::vector<AnalysisID>::const_iterator I = Required.begin(),
           E = Required.end(); I != E; ++I) {
      if (getAnalysisOrNullDown(*I) == 0) {
        Pass *AP = (*I)->createPass();
        if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (AP)) { add(IP); }
        else if (PassClass *RP = dynamic_cast<PassClass *> (AP)) { add(RP); }
        else { assert (0 && "Wrong kind of pass for this PassManager"); }
      }
    }

    // Tell the pass to add itself to this PassManager... the way it does so
    // depends on the class of the pass, and is critical to laying out passes in
    // an optimal order..
    //
    P->addToPassManager(this, AnUsage);
  }

  // add - H4x0r an ImmutablePass into a PassManager that might not be
  // expecting one.
  //
  void add(ImmutablePass *P) {
    // Get information about what analyses the pass uses...
    AnalysisUsage AnUsage;
    P->getAnalysisUsage(AnUsage);
    const std::vector<AnalysisID> &Required = AnUsage.getRequiredSet();

    // Loop over all of the analyses used by this pass,
    for (std::vector<AnalysisID>::const_iterator I = Required.begin(),
           E = Required.end(); I != E; ++I) {
      if (getAnalysisOrNullDown(*I) == 0) {
        Pass *AP = (*I)->createPass();
        if (ImmutablePass *IP = dynamic_cast<ImmutablePass *> (AP)) add(IP);
        else if (PassClass *RP = dynamic_cast<PassClass *> (AP)) add(RP);
        else assert (0 && "Wrong kind of pass for this PassManager");
      }
    }

    // Add the ImmutablePass to this PassManager.
    addPass(P, AnUsage);
  }

private:
  // addPass - These functions are used to implement the subclass specific
  // behaviors present in PassManager.  Basically the add(Pass*) method ends up
  // reflecting its behavior into a Pass::addToPassManager call.  Subclasses of
  // Pass override it specifically so that they can reflect the type
  // information inherent in "this" back to the PassManager.
  //
  // For generic Pass subclasses (which are interprocedural passes), we simply
  // add the pass to the end of the pass list and terminate any accumulation of
  // FunctionPass's that are present.
  //
  void addPass(PassClass *P, AnalysisUsage &AnUsage) {
    const std::vector<AnalysisID> &RequiredSet = AnUsage.getRequiredSet();

    // FIXME: If this pass being added isn't killed by any of the passes in the
    // batcher class then we can reorder to pass to execute before the batcher
    // does, which will potentially allow us to batch more passes!
    //
    //const std::vector<AnalysisID> &ProvidedSet = AnUsage.getProvidedSet();
    if (Batcher /*&& ProvidedSet.empty()*/)
      closeBatcher();                     // This pass cannot be batched!

    // Set the Resolver instance variable in the Pass so that it knows where to
    // find this object...
    //
    setAnalysisResolver(P, this);
    Passes.push_back(P);

    // Inform higher level pass managers (and ourselves) that these analyses are
    // being used by this pass.  This is used to make sure that analyses are not
    // free'd before we have to use them...
    //
    for (std::vector<AnalysisID>::const_iterator I = RequiredSet.begin(),
           E = RequiredSet.end(); I != E; ++I)
      markPassUsed(*I, P);     // Mark *I as used by P

    // Erase all analyses not in the preserved set...
    if (!AnUsage.getPreservesAll()) {
      const std::vector<AnalysisID> &PreservedSet = AnUsage.getPreservedSet();
      for (std::map<AnalysisID, Pass*>::iterator I = CurrentAnalyses.begin(),
             E = CurrentAnalyses.end(); I != E; ) {
        if (std::find(PreservedSet.begin(), PreservedSet.end(), I->first) ==
            PreservedSet.end()) {             // Analysis not preserved!
          CurrentAnalyses.erase(I);           // Remove from available analyses
          I = CurrentAnalyses.begin();
        } else {
          ++I;
        }
      }
    }

    // Add this pass to the currently available set...
    if (const PassInfo *PI = P->getPassInfo()) {
      CurrentAnalyses[PI] = P;

      // This pass is the current implementation of all of the interfaces it
      // implements as well.
      //
      const std::vector<const PassInfo*> &II = PI->getInterfacesImplemented();
      for (unsigned i = 0, e = II.size(); i != e; ++i)
        CurrentAnalyses[II[i]] = P;
    }

    // For now assume that our results are never used...
    LastUseOf[P] = P;
  }

  // For FunctionPass subclasses, we must be sure to batch the FunctionPass's
  // together in a BatcherClass object so that all of the analyses are run
  // together a function at a time.
  //
  void addPass(SubPassClass *MP, AnalysisUsage &AnUsage) {
    if (Batcher == 0) // If we don't have a batcher yet, make one now.
      Batcher = new BatcherClass(this);
    // The Batcher will queue the passes up
    MP->addToPassManager(Batcher, AnUsage);
  }

  // closeBatcher - Terminate the batcher that is being worked on.
  void closeBatcher() {
    if (Batcher) {
      Passes.push_back(Batcher);
      Batcher = 0;
    }
  }

public:
  // When an ImmutablePass is added, it gets added to the top level pass
  // manager.
  void addPass(ImmutablePass *IP, AnalysisUsage &AU) {
    if (Parent) { // Make sure this request goes to the top level passmanager...
      Parent->addPass(IP, AU);
      return;
    }

    // Set the Resolver instance variable in the Pass so that it knows where to
    // find this object...
    //
    setAnalysisResolver(IP, this);
    ImmutablePasses.push_back(IP);

    // All Required analyses should be available to the pass as it initializes!
    // Here we fill in the AnalysisImpls member of the pass so that it can
    // successfully use the getAnalysis() method to retrieve the implementations
    // it needs.
    //
    IP->AnalysisImpls.clear();
    IP->AnalysisImpls.reserve(AU.getRequiredSet().size());
    for (std::vector<const PassInfo *>::const_iterator
           I = AU.getRequiredSet().begin(),
           E = AU.getRequiredSet().end(); I != E; ++I) {
      Pass *Impl = getAnalysisOrNullUp(*I);
      if (Impl == 0) {
        std::cerr << "Analysis '" << (*I)->getPassName()
                  << "' used but not available!";
        assert(0 && "Analysis used but not available!");
      } else if (PassDebugging == Details) {
        if ((*I)->getPassName() != std::string(Impl->getPassName()))
          std::cerr << "    Interface '" << (*I)->getPassName()
                    << "' implemented by '" << Impl->getPassName() << "'\n";
      }
      IP->AnalysisImpls.push_back(std::make_pair(*I, Impl));
    }

    // Initialize the immutable pass...
    IP->initializePass();
  }
};



//===----------------------------------------------------------------------===//
// PassManagerTraits<BasicBlock> Specialization
//
// This pass manager is used to group together all of the BasicBlockPass's
// into a single unit.
//
template<> class PassManagerTraits<BasicBlock> : public BasicBlockPass {
public:
  // PassClass - The type of passes tracked by this PassManager
  typedef BasicBlockPass PassClass;

  // SubPassClass - The types of classes that should be collated together
  // This is impossible to match, so BasicBlock instantiations of PassManagerT
  // do not collate.
  //
  typedef PassManagerT<Module> SubPassClass;

  // BatcherClass - The type to use for collation of subtypes... This class is
  // never instantiated for the PassManager<BasicBlock>, but it must be an
  // instance of PassClass to typecheck.
  //
  typedef PassClass BatcherClass;

  // ParentClass - The type of the parent PassManager...
  typedef PassManagerT<Function> ParentClass;

  // PMType - The type of the passmanager that subclasses this class
  typedef PassManagerT<BasicBlock> PMType;

  // runPass - Specify how the pass should be run on the UnitType
  static bool runPass(PassClass *P, BasicBlock *M) {
    // todo, init and finalize
    return P->runOnBasicBlock(*M);
  }

  // getPMName() - Return the name of the unit the PassManager operates on for
  // debugging.
  const char *getPMName() const { return "BasicBlock"; }
  virtual const char *getPassName() const { return "BasicBlock Pass Manager"; }

  // Implement the BasicBlockPass interface...
  virtual bool doInitialization(Module &M);
  virtual bool doInitialization(Function &F);
  virtual bool runOnBasicBlock(BasicBlock &BB);
  virtual bool doFinalization(Function &F);
  virtual bool doFinalization(Module &M);

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};



//===----------------------------------------------------------------------===//
// PassManagerTraits<Function> Specialization
//
// This pass manager is used to group together all of the FunctionPass's
// into a single unit.
//
template<> class PassManagerTraits<Function> : public FunctionPass {
public:
  // PassClass - The type of passes tracked by this PassManager
  typedef FunctionPass PassClass;

  // SubPassClass - The types of classes that should be collated together
  typedef BasicBlockPass SubPassClass;

  // BatcherClass - The type to use for collation of subtypes...
  typedef PassManagerT<BasicBlock> BatcherClass;

  // ParentClass - The type of the parent PassManager...
  typedef PassManagerT<Module> ParentClass;

  // PMType - The type of the passmanager that subclasses this class
  typedef PassManagerT<Function> PMType;

  // runPass - Specify how the pass should be run on the UnitType
  static bool runPass(PassClass *P, Function *F) {
    return P->runOnFunction(*F);
  }

  // getPMName() - Return the name of the unit the PassManager operates on for
  // debugging.
  const char *getPMName() const { return "Function"; }
  virtual const char *getPassName() const { return "Function Pass Manager"; }

  // Implement the FunctionPass interface...
  virtual bool doInitialization(Module &M);
  virtual bool runOnFunction(Function &F);
  virtual bool doFinalization(Module &M);

  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.setPreservesAll();
  }
};



//===----------------------------------------------------------------------===//
// PassManagerTraits<Module> Specialization
//
// This is the top level PassManager implementation that holds generic passes.
//
template<> class PassManagerTraits<Module> : public ModulePass {
public:
  // PassClass - The type of passes tracked by this PassManager
  typedef ModulePass PassClass;

  // SubPassClass - The types of classes that should be collated together
  typedef FunctionPass SubPassClass;

  // BatcherClass - The type to use for collation of subtypes...
  typedef PassManagerT<Function> BatcherClass;

  // ParentClass - The type of the parent PassManager...
  typedef AnalysisResolver ParentClass;

  // runPass - Specify how the pass should be run on the UnitType
  static bool runPass(PassClass *P, Module *M) { return P->runOnModule(*M); }

  // getPMName() - Return the name of the unit the PassManager operates on for
  // debugging.
  const char *getPMName() const { return "Module"; }
  virtual const char *getPassName() const { return "Module Pass Manager"; }

  // runOnModule - Implement the PassManager interface.
  bool runOnModule(Module &M) {
    return ((PassManagerT<Module>*)this)->runOnUnit(&M);
  }
};



//===----------------------------------------------------------------------===//
// PassManagerTraits Method Implementations
//

// PassManagerTraits<BasicBlock> Implementations
//
inline bool PassManagerTraits<BasicBlock>::doInitialization(Module &M) {
  bool Changed = false;
  for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)
    ((PMType*)this)->Passes[i]->doInitialization(M);
  return Changed;
}

inline bool PassManagerTraits<BasicBlock>::doInitialization(Function &F) {
  bool Changed = false;
  for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)
    ((PMType*)this)->Passes[i]->doInitialization(F);
  return Changed;
}

inline bool PassManagerTraits<BasicBlock>::runOnBasicBlock(BasicBlock &BB) {
  return ((PMType*)this)->runOnUnit(&BB);
}

inline bool PassManagerTraits<BasicBlock>::doFinalization(Function &F) {
  bool Changed = false;
  for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)
    ((PMType*)this)->Passes[i]->doFinalization(F);
  return Changed;
}

inline bool PassManagerTraits<BasicBlock>::doFinalization(Module &M) {
  bool Changed = false;
  for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)
    ((PMType*)this)->Passes[i]->doFinalization(M);
  return Changed;
}


// PassManagerTraits<Function> Implementations
//
inline bool PassManagerTraits<Function>::doInitialization(Module &M) {
  bool Changed = false;
  for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)
    ((PMType*)this)->Passes[i]->doInitialization(M);
  return Changed;
}

inline bool PassManagerTraits<Function>::runOnFunction(Function &F) {
  return ((PMType*)this)->runOnUnit(&F);
}

inline bool PassManagerTraits<Function>::doFinalization(Module &M) {
  bool Changed = false;
  for (unsigned i = 0, e = ((PMType*)this)->Passes.size(); i != e; ++i)
    ((PMType*)this)->Passes[i]->doFinalization(M);
  return Changed;
}

} // End llvm namespace

#endif
