<commit_before>//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LoopInfo class that is used to identify natural loops
// and determine the loop depth of various nodes of the CFG.  Note that the
// loops identified may actually be several natural loops that share the same
// header node... not just a single natural loop.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <algorithm>
using namespace llvm;

// Always verify loopinfo if expensive checking is enabled.
#ifdef XDEBUG
bool VerifyLoopInfo = true;
#else
bool VerifyLoopInfo = false;
#endif
static cl::opt<bool,true>
VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo),
                cl::desc("Verify loop info (time consuming)"));

char LoopInfo::ID = 0;
static RegisterPass<LoopInfo>
X("loops", "Natural Loop Information", true, true);

//===----------------------------------------------------------------------===//
// Loop implementation
//

/// isLoopInvariant - Return true if the specified value is loop invariant
///
bool Loop::isLoopInvariant(Value *V) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return isLoopInvariant(I);
  return true;  // All non-instructions are loop invariant
}

/// isLoopInvariant - Return true if the specified instruction is
/// loop-invariant.
///
bool Loop::isLoopInvariant(Instruction *I) const {
  return !contains(I->getParent());
}

/// makeLoopInvariant - If the given value is an instruciton inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the value after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Value *V, bool &Changed,
                             Instruction *InsertPt) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return makeLoopInvariant(I, Changed, InsertPt);
  return true;  // All non-instructions are loop-invariant.
}

/// makeLoopInvariant - If the given instruction is inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the instruction after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
                             Instruction *InsertPt) const {
  // Test if the value is already loop-invariant.
  if (isLoopInvariant(I))
    return true;
  if (!I->isSafeToSpeculativelyExecute())
    return false;
  if (I->mayReadFromMemory())
    return false;
  // Determine the insertion point, unless one was given.
  if (!InsertPt) {
    BasicBlock *Preheader = getLoopPreheader();
    // Without a preheader, hoisting is not feasible.
    if (!Preheader)
      return false;
    InsertPt = Preheader->getTerminator();
  }
  // Don't hoist instructions with loop-variant operands.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
    if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt))
      return false;
  // Hoist.
  I->moveBefore(InsertPt);
  Changed = true;
  return true;
}

/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable: an integer recurrence that starts at 0 and increments
/// by one each time through the loop.  If so, return the phi node that
/// corresponds to it.
///
/// The IndVarSimplify pass transforms loops to have a canonical induction
/// variable.
///
PHINode *Loop::getCanonicalInductionVariable() const {
  BasicBlock *H = getHeader();

  BasicBlock *Incoming = 0, *Backedge = 0;
  typedef GraphTraits<Inverse<BasicBlock*> > InvBlockTraits;
  InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(H);
  assert(PI != InvBlockTraits::child_end(H) &&
         "Loop must have at least one backedge!");
  Backedge = *PI++;
  if (PI == InvBlockTraits::child_end(H)) return 0;  // dead loop
  Incoming = *PI++;
  if (PI != InvBlockTraits::child_end(H)) return 0;  // multiple backedges?

  if (contains(Incoming)) {
    if (contains(Backedge))
      return 0;
    std::swap(Incoming, Backedge);
  } else if (!contains(Backedge))
    return 0;

  // Loop over all of the PHI nodes, looking for a canonical indvar.
  for (BasicBlock::iterator I = H->begin(); isa<PHINode>(I); ++I) {
    PHINode *PN = cast<PHINode>(I);
    if (ConstantInt *CI =
        dyn_cast<ConstantInt>(PN->getIncomingValueForBlock(Incoming)))
      if (CI->isNullValue())
        if (Instruction *Inc =
            dyn_cast<Instruction>(PN->getIncomingValueForBlock(Backedge)))
          if (Inc->getOpcode() == Instruction::Add &&
                Inc->getOperand(0) == PN)
            if (ConstantInt *CI = dyn_cast<ConstantInt>(Inc->getOperand(1)))
              if (CI->equalsInt(1))
                return PN;
  }
  return 0;
}

/// getCanonicalInductionVariableIncrement - Return the LLVM value that holds
/// the canonical induction variable value for the "next" iteration of the
/// loop.  This always succeeds if getCanonicalInductionVariable succeeds.
///
Instruction *Loop::getCanonicalInductionVariableIncrement() const {
  if (PHINode *PN = getCanonicalInductionVariable()) {
    bool P1InLoop = contains(PN->getIncomingBlock(1));
    return cast<Instruction>(PN->getIncomingValue(P1InLoop));
  }
  return 0;
}

/// getTripCount - Return a loop-invariant LLVM value indicating the number of
/// times the loop will be executed.  Note that this means that the backedge
/// of the loop executes N-1 times.  If the trip-count cannot be determined,
/// this returns null.
///
/// The IndVarSimplify pass transforms loops to have a form that this
/// function easily understands.
///
Value *Loop::getTripCount() const {
  // Canonical loops will end with a 'cmp ne I, V', where I is the incremented
  // canonical induction variable and V is the trip count of the loop.
  Instruction *Inc = getCanonicalInductionVariableIncrement();
  if (Inc == 0) return 0;
  PHINode *IV = cast<PHINode>(Inc->getOperand(0));

  BasicBlock *BackedgeBlock =
    IV->getIncomingBlock(contains(IV->getIncomingBlock(1)));

  if (BranchInst *BI = dyn_cast<BranchInst>(BackedgeBlock->getTerminator()))
    if (BI->isConditional()) {
      if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
        if (ICI->getOperand(0) == Inc) {
          if (BI->getSuccessor(0) == getHeader()) {
            if (ICI->getPredicate() == ICmpInst::ICMP_NE)
              return ICI->getOperand(1);
          } else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) {
            return ICI->getOperand(1);
          }
        }
      }
    }

  return 0;
}

/// getSmallConstantTripCount - Returns the trip count of this loop as a
/// normal unsigned value, if possible. Returns 0 if the trip count is unknown
/// of not constant. Will also return 0 if the trip count is very large
/// (>= 2^32)
unsigned Loop::getSmallConstantTripCount() const {
  Value* TripCount = this->getTripCount();
  if (TripCount) {
    if (ConstantInt *TripCountC = dyn_cast<ConstantInt>(TripCount)) {
      // Guard against huge trip counts.
      if (TripCountC->getValue().getActiveBits() <= 32) {
        return (unsigned)TripCountC->getZExtValue();
      }
    }
  }
  return 0;
}

/// getSmallConstantTripMultiple - Returns the largest constant divisor of the
/// trip count of this loop as a normal unsigned value, if possible. This
/// means that the actual trip count is always a multiple of the returned
/// value (don't forget the trip count could very well be zero as well!).
///
/// Returns 1 if the trip count is unknown or not guaranteed to be the
/// multiple of a constant (which is also the case if the trip count is simply
/// constant, use getSmallConstantTripCount for that case), Will also return 1
/// if the trip count is very large (>= 2^32).
unsigned Loop::getSmallConstantTripMultiple() const {
  Value* TripCount = this->getTripCount();
  // This will hold the ConstantInt result, if any
  ConstantInt *Result = NULL;
  if (TripCount) {
    // See if the trip count is constant itself
    Result = dyn_cast<ConstantInt>(TripCount);
    // if not, see if it is a multiplication
    if (!Result)
      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TripCount)) {
        switch (BO->getOpcode()) {
        case BinaryOperator::Mul:
          Result = dyn_cast<ConstantInt>(BO->getOperand(1));
          break;
        default:
          break;
        }
      }
  }
  // Guard against huge trip counts.
  if (Result && Result->getValue().getActiveBits() <= 32) {
    return (unsigned)Result->getZExtValue();
  } else {
    return 1;
  }
}

/// isLCSSAForm - Return true if the Loop is in LCSSA form
bool Loop::isLCSSAForm() const {
  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());

  for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) {
    BasicBlock  *BB = *BI;
    for (BasicBlock ::iterator I = BB->begin(), E = BB->end(); I != E;++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (PHINode *P = dyn_cast<PHINode>(*UI)) {
          UserBB = P->getIncomingBlock(UI);
        }

        // Check the current block, as a fast-path.  Most values are used in
        // the same block they are defined in.
        if (UserBB != BB && !LoopBBs.count(UserBB))
          return false;
      }
  }

  return true;
}

/// isLoopSimplifyForm - Return true if the Loop is in the form that
/// the LoopSimplify form transforms loops to, which is sometimes called
/// normal form.
bool Loop::isLoopSimplifyForm() const {
  // Normal-form loops have a preheader.
  if (!getLoopPreheader())
    return false;
  // Normal-form loops have a single backedge.
  if (!getLoopLatch())
    return false;
  // Each predecessor of each exit block of a normal loop is contained
  // within the loop.
  SmallVector<BasicBlock *, 4> ExitBlocks;
  getExitBlocks(ExitBlocks);
  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
    for (pred_iterator PI = pred_begin(ExitBlocks[i]),
         PE = pred_end(ExitBlocks[i]); PI != PE; ++PI)
      if (!contains(*PI))
        return false;
  // All the requirements are met.
  return true;
}

/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to.
/// This assumes that loop is in canonical form.
///
void
Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
  assert(isLoopSimplifyForm() &&
         "getUniqueExitBlocks assumes the loop is in canonical form!");

  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallVector<BasicBlock *, 128> LoopBBs(block_begin(), block_end());
  std::sort(LoopBBs.begin(), LoopBBs.end());

  SmallVector<BasicBlock *, 32> switchExitBlocks;

  for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) {

    BasicBlock *current = *BI;
    switchExitBlocks.clear();

    typedef GraphTraits<BasicBlock *> BlockTraits;
    typedef GraphTraits<Inverse<BasicBlock *> > InvBlockTraits;
    for (BlockTraits::ChildIteratorType I =
         BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
         I != E; ++I) {
      // If block is inside the loop then it is not a exit block.
      if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
        continue;

      InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(*I);
      BasicBlock *firstPred = *PI;

      // If current basic block is this exit block's first predecessor
      // then only insert exit block in to the output ExitBlocks vector.
      // This ensures that same exit block is not inserted twice into
      // ExitBlocks vector.
      if (current != firstPred)
        continue;

      // If a terminator has more then two successors, for example SwitchInst,
      // then it is possible that there are multiple edges from current block
      // to one exit block.
      if (std::distance(BlockTraits::child_begin(current),
                        BlockTraits::child_end(current)) <= 2) {
        ExitBlocks.push_back(*I);
        continue;
      }

      // In case of multiple edges from current block to exit block, collect
      // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
      // duplicate edges.
      if (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I)
          == switchExitBlocks.end()) {
        switchExitBlocks.push_back(*I);
        ExitBlocks.push_back(*I);
      }
    }
  }
}

/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
/// block, return that block. Otherwise return null.
BasicBlock *Loop::getUniqueExitBlock() const {
  SmallVector<BasicBlock *, 8> UniqueExitBlocks;
  getUniqueExitBlocks(UniqueExitBlocks);
  if (UniqueExitBlocks.size() == 1)
    return UniqueExitBlocks[0];
  return 0;
}

//===----------------------------------------------------------------------===//
// LoopInfo implementation
//
bool LoopInfo::runOnFunction(Function &) {
  releaseMemory();
  LI.Calculate(getAnalysis<DominatorTree>().getBase());    // Update
  return false;
}

void LoopInfo::verifyAnalysis() const {
  // LoopInfo is a FunctionPass, but verifying every loop in the function
  // each time verifyAnalysis is called is very expensive. The
  // -verify-loop-info option can enable this. In order to perform some
  // checking by default, LoopPass has been taught to call verifyLoop
  // manually during loop pass sequences.

  if (!VerifyLoopInfo) return;

  for (iterator I = begin(), E = end(); I != E; ++I) {
    assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
    (*I)->verifyLoopNest();
  }

  // TODO: check BBMap consistency.
}

void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequired<DominatorTree>();
}

void LoopInfo::print(raw_ostream &OS, const Module*) const {
  LI.print(OS);
}

<commit_msg>Fix another place that calls Loop::contains a lot to construct a sorted container of the blocks and do efficient lookups. This makes isLoopSimplifyForm much faster on large loops, fixing a significant compile-time issue in builds with assertions enabled.<commit_after>//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LoopInfo class that is used to identify natural loops
// and determine the loop depth of various nodes of the CFG.  Note that the
// loops identified may actually be several natural loops that share the same
// header node... not just a single natural loop.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <algorithm>
using namespace llvm;

// Always verify loopinfo if expensive checking is enabled.
#ifdef XDEBUG
bool VerifyLoopInfo = true;
#else
bool VerifyLoopInfo = false;
#endif
static cl::opt<bool,true>
VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo),
                cl::desc("Verify loop info (time consuming)"));

char LoopInfo::ID = 0;
static RegisterPass<LoopInfo>
X("loops", "Natural Loop Information", true, true);

//===----------------------------------------------------------------------===//
// Loop implementation
//

/// isLoopInvariant - Return true if the specified value is loop invariant
///
bool Loop::isLoopInvariant(Value *V) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return isLoopInvariant(I);
  return true;  // All non-instructions are loop invariant
}

/// isLoopInvariant - Return true if the specified instruction is
/// loop-invariant.
///
bool Loop::isLoopInvariant(Instruction *I) const {
  return !contains(I->getParent());
}

/// makeLoopInvariant - If the given value is an instruciton inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the value after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Value *V, bool &Changed,
                             Instruction *InsertPt) const {
  if (Instruction *I = dyn_cast<Instruction>(V))
    return makeLoopInvariant(I, Changed, InsertPt);
  return true;  // All non-instructions are loop-invariant.
}

/// makeLoopInvariant - If the given instruction is inside of the
/// loop and it can be hoisted, do so to make it trivially loop-invariant.
/// Return true if the instruction after any hoisting is loop invariant. This
/// function can be used as a slightly more aggressive replacement for
/// isLoopInvariant.
///
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
///
bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
                             Instruction *InsertPt) const {
  // Test if the value is already loop-invariant.
  if (isLoopInvariant(I))
    return true;
  if (!I->isSafeToSpeculativelyExecute())
    return false;
  if (I->mayReadFromMemory())
    return false;
  // Determine the insertion point, unless one was given.
  if (!InsertPt) {
    BasicBlock *Preheader = getLoopPreheader();
    // Without a preheader, hoisting is not feasible.
    if (!Preheader)
      return false;
    InsertPt = Preheader->getTerminator();
  }
  // Don't hoist instructions with loop-variant operands.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
    if (!makeLoopInvariant(I->getOperand(i), Changed, InsertPt))
      return false;
  // Hoist.
  I->moveBefore(InsertPt);
  Changed = true;
  return true;
}

/// getCanonicalInductionVariable - Check to see if the loop has a canonical
/// induction variable: an integer recurrence that starts at 0 and increments
/// by one each time through the loop.  If so, return the phi node that
/// corresponds to it.
///
/// The IndVarSimplify pass transforms loops to have a canonical induction
/// variable.
///
PHINode *Loop::getCanonicalInductionVariable() const {
  BasicBlock *H = getHeader();

  BasicBlock *Incoming = 0, *Backedge = 0;
  typedef GraphTraits<Inverse<BasicBlock*> > InvBlockTraits;
  InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(H);
  assert(PI != InvBlockTraits::child_end(H) &&
         "Loop must have at least one backedge!");
  Backedge = *PI++;
  if (PI == InvBlockTraits::child_end(H)) return 0;  // dead loop
  Incoming = *PI++;
  if (PI != InvBlockTraits::child_end(H)) return 0;  // multiple backedges?

  if (contains(Incoming)) {
    if (contains(Backedge))
      return 0;
    std::swap(Incoming, Backedge);
  } else if (!contains(Backedge))
    return 0;

  // Loop over all of the PHI nodes, looking for a canonical indvar.
  for (BasicBlock::iterator I = H->begin(); isa<PHINode>(I); ++I) {
    PHINode *PN = cast<PHINode>(I);
    if (ConstantInt *CI =
        dyn_cast<ConstantInt>(PN->getIncomingValueForBlock(Incoming)))
      if (CI->isNullValue())
        if (Instruction *Inc =
            dyn_cast<Instruction>(PN->getIncomingValueForBlock(Backedge)))
          if (Inc->getOpcode() == Instruction::Add &&
                Inc->getOperand(0) == PN)
            if (ConstantInt *CI = dyn_cast<ConstantInt>(Inc->getOperand(1)))
              if (CI->equalsInt(1))
                return PN;
  }
  return 0;
}

/// getCanonicalInductionVariableIncrement - Return the LLVM value that holds
/// the canonical induction variable value for the "next" iteration of the
/// loop.  This always succeeds if getCanonicalInductionVariable succeeds.
///
Instruction *Loop::getCanonicalInductionVariableIncrement() const {
  if (PHINode *PN = getCanonicalInductionVariable()) {
    bool P1InLoop = contains(PN->getIncomingBlock(1));
    return cast<Instruction>(PN->getIncomingValue(P1InLoop));
  }
  return 0;
}

/// getTripCount - Return a loop-invariant LLVM value indicating the number of
/// times the loop will be executed.  Note that this means that the backedge
/// of the loop executes N-1 times.  If the trip-count cannot be determined,
/// this returns null.
///
/// The IndVarSimplify pass transforms loops to have a form that this
/// function easily understands.
///
Value *Loop::getTripCount() const {
  // Canonical loops will end with a 'cmp ne I, V', where I is the incremented
  // canonical induction variable and V is the trip count of the loop.
  Instruction *Inc = getCanonicalInductionVariableIncrement();
  if (Inc == 0) return 0;
  PHINode *IV = cast<PHINode>(Inc->getOperand(0));

  BasicBlock *BackedgeBlock =
    IV->getIncomingBlock(contains(IV->getIncomingBlock(1)));

  if (BranchInst *BI = dyn_cast<BranchInst>(BackedgeBlock->getTerminator()))
    if (BI->isConditional()) {
      if (ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition())) {
        if (ICI->getOperand(0) == Inc) {
          if (BI->getSuccessor(0) == getHeader()) {
            if (ICI->getPredicate() == ICmpInst::ICMP_NE)
              return ICI->getOperand(1);
          } else if (ICI->getPredicate() == ICmpInst::ICMP_EQ) {
            return ICI->getOperand(1);
          }
        }
      }
    }

  return 0;
}

/// getSmallConstantTripCount - Returns the trip count of this loop as a
/// normal unsigned value, if possible. Returns 0 if the trip count is unknown
/// of not constant. Will also return 0 if the trip count is very large
/// (>= 2^32)
unsigned Loop::getSmallConstantTripCount() const {
  Value* TripCount = this->getTripCount();
  if (TripCount) {
    if (ConstantInt *TripCountC = dyn_cast<ConstantInt>(TripCount)) {
      // Guard against huge trip counts.
      if (TripCountC->getValue().getActiveBits() <= 32) {
        return (unsigned)TripCountC->getZExtValue();
      }
    }
  }
  return 0;
}

/// getSmallConstantTripMultiple - Returns the largest constant divisor of the
/// trip count of this loop as a normal unsigned value, if possible. This
/// means that the actual trip count is always a multiple of the returned
/// value (don't forget the trip count could very well be zero as well!).
///
/// Returns 1 if the trip count is unknown or not guaranteed to be the
/// multiple of a constant (which is also the case if the trip count is simply
/// constant, use getSmallConstantTripCount for that case), Will also return 1
/// if the trip count is very large (>= 2^32).
unsigned Loop::getSmallConstantTripMultiple() const {
  Value* TripCount = this->getTripCount();
  // This will hold the ConstantInt result, if any
  ConstantInt *Result = NULL;
  if (TripCount) {
    // See if the trip count is constant itself
    Result = dyn_cast<ConstantInt>(TripCount);
    // if not, see if it is a multiplication
    if (!Result)
      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(TripCount)) {
        switch (BO->getOpcode()) {
        case BinaryOperator::Mul:
          Result = dyn_cast<ConstantInt>(BO->getOperand(1));
          break;
        default:
          break;
        }
      }
  }
  // Guard against huge trip counts.
  if (Result && Result->getValue().getActiveBits() <= 32) {
    return (unsigned)Result->getZExtValue();
  } else {
    return 1;
  }
}

/// isLCSSAForm - Return true if the Loop is in LCSSA form
bool Loop::isLCSSAForm() const {
  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());

  for (block_iterator BI = block_begin(), E = block_end(); BI != E; ++BI) {
    BasicBlock  *BB = *BI;
    for (BasicBlock ::iterator I = BB->begin(), E = BB->end(); I != E;++I)
      for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;
           ++UI) {
        BasicBlock *UserBB = cast<Instruction>(*UI)->getParent();
        if (PHINode *P = dyn_cast<PHINode>(*UI)) {
          UserBB = P->getIncomingBlock(UI);
        }

        // Check the current block, as a fast-path.  Most values are used in
        // the same block they are defined in.
        if (UserBB != BB && !LoopBBs.count(UserBB))
          return false;
      }
  }

  return true;
}

/// isLoopSimplifyForm - Return true if the Loop is in the form that
/// the LoopSimplify form transforms loops to, which is sometimes called
/// normal form.
bool Loop::isLoopSimplifyForm() const {
  // Normal-form loops have a preheader.
  if (!getLoopPreheader())
    return false;
  // Normal-form loops have a single backedge.
  if (!getLoopLatch())
    return false;
  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallPtrSet<BasicBlock *, 16> LoopBBs(block_begin(), block_end());
  // Each predecessor of each exit block of a normal loop is contained
  // within the loop.
  SmallVector<BasicBlock *, 4> ExitBlocks;
  getExitBlocks(ExitBlocks);
  for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i)
    for (pred_iterator PI = pred_begin(ExitBlocks[i]),
         PE = pred_end(ExitBlocks[i]); PI != PE; ++PI)
      if (!LoopBBs.count(*PI))
        return false;
  // All the requirements are met.
  return true;
}

/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to.
/// This assumes that loop is in canonical form.
///
void
Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
  assert(isLoopSimplifyForm() &&
         "getUniqueExitBlocks assumes the loop is in canonical form!");

  // Sort the blocks vector so that we can use binary search to do quick
  // lookups.
  SmallVector<BasicBlock *, 128> LoopBBs(block_begin(), block_end());
  std::sort(LoopBBs.begin(), LoopBBs.end());

  SmallVector<BasicBlock *, 32> switchExitBlocks;

  for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI) {

    BasicBlock *current = *BI;
    switchExitBlocks.clear();

    typedef GraphTraits<BasicBlock *> BlockTraits;
    typedef GraphTraits<Inverse<BasicBlock *> > InvBlockTraits;
    for (BlockTraits::ChildIteratorType I =
         BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
         I != E; ++I) {
      // If block is inside the loop then it is not a exit block.
      if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
        continue;

      InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(*I);
      BasicBlock *firstPred = *PI;

      // If current basic block is this exit block's first predecessor
      // then only insert exit block in to the output ExitBlocks vector.
      // This ensures that same exit block is not inserted twice into
      // ExitBlocks vector.
      if (current != firstPred)
        continue;

      // If a terminator has more then two successors, for example SwitchInst,
      // then it is possible that there are multiple edges from current block
      // to one exit block.
      if (std::distance(BlockTraits::child_begin(current),
                        BlockTraits::child_end(current)) <= 2) {
        ExitBlocks.push_back(*I);
        continue;
      }

      // In case of multiple edges from current block to exit block, collect
      // only one edge in ExitBlocks. Use switchExitBlocks to keep track of
      // duplicate edges.
      if (std::find(switchExitBlocks.begin(), switchExitBlocks.end(), *I)
          == switchExitBlocks.end()) {
        switchExitBlocks.push_back(*I);
        ExitBlocks.push_back(*I);
      }
    }
  }
}

/// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
/// block, return that block. Otherwise return null.
BasicBlock *Loop::getUniqueExitBlock() const {
  SmallVector<BasicBlock *, 8> UniqueExitBlocks;
  getUniqueExitBlocks(UniqueExitBlocks);
  if (UniqueExitBlocks.size() == 1)
    return UniqueExitBlocks[0];
  return 0;
}

//===----------------------------------------------------------------------===//
// LoopInfo implementation
//
bool LoopInfo::runOnFunction(Function &) {
  releaseMemory();
  LI.Calculate(getAnalysis<DominatorTree>().getBase());    // Update
  return false;
}

void LoopInfo::verifyAnalysis() const {
  // LoopInfo is a FunctionPass, but verifying every loop in the function
  // each time verifyAnalysis is called is very expensive. The
  // -verify-loop-info option can enable this. In order to perform some
  // checking by default, LoopPass has been taught to call verifyLoop
  // manually during loop pass sequences.

  if (!VerifyLoopInfo) return;

  for (iterator I = begin(), E = end(); I != E; ++I) {
    assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
    (*I)->verifyLoopNest();
  }

  // TODO: check BBMap consistency.
}

void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequired<DominatorTree>();
}

void LoopInfo::print(raw_ostream &OS, const Module*) const {
  LI.print(OS);
}

<|endoftext|>


<commit_before>//=== FlatStore.cpp - Flat region-based store model -------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Checker/PathSensitive/GRState.h"
#include "llvm/ADT/ImmutableIntervalMap.h"

using namespace clang;
using llvm::Interval;

// The actual store type.
typedef llvm::ImmutableIntervalMap<SVal> BindingVal;
typedef llvm::ImmutableMap<const MemRegion *, BindingVal> RegionBindings;

namespace {
class FlatStoreManager : public StoreManager {
  RegionBindings::Factory RBFactory;
  BindingVal::Factory BVFactory;

public:
  FlatStoreManager(GRStateManager &mgr)
    : StoreManager(mgr),
      RBFactory(mgr.getAllocator()),
      BVFactory(mgr.getAllocator()) {}

  SVal Retrieve(Store store, Loc L, QualType T);
  Store Bind(Store store, Loc L, SVal val);
  Store Remove(Store St, Loc L);
  Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* cl,
                            const LocationContext *LC, SVal v);

  Store getInitialStore(const LocationContext *InitLoc) {
    return RBFactory.GetEmptyMap().getRoot();
  }

  SubRegionMap *getSubRegionMap(Store store) {
    return 0;
  }

  SVal ArrayToPointer(Loc Array);
  Store RemoveDeadBindings(Store store, Stmt* Loc, SymbolReaper& SymReaper,
                         llvm::SmallVectorImpl<const MemRegion*>& RegionRoots){
    return store;
  }

  Store BindDecl(Store store, const VarRegion *VR, SVal initVal);

  Store BindDeclWithNoInit(Store store, const VarRegion *VR);

  typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;

  Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
                         unsigned Count, InvalidatedSymbols *IS);

  void print(Store store, llvm::raw_ostream& Out, const char* nl,
             const char *sep);
  void iterBindings(Store store, BindingsHandler& f);

private:
  static RegionBindings getRegionBindings(Store store) {
    return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
  }

  Interval RegionToInterval(const MemRegion *R);

  SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T);
};
} // end anonymous namespace

StoreManager *clang::CreateFlatStoreManager(GRStateManager &StMgr) {
  return new FlatStoreManager(StMgr);
}

SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) {
  const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
  Interval I = RegionToInterval(R);
  RegionBindings B = getRegionBindings(store);
  const BindingVal *BV = B.lookup(R);
  if (BV) {
    const SVal *V = BVFactory.Lookup(*BV, I);
    if (V)
      return *V;
    else
      return RetrieveRegionWithNoBinding(R, T);
  }
  return RetrieveRegionWithNoBinding(R, T);
}

SVal FlatStoreManager::RetrieveRegionWithNoBinding(const MemRegion *R,
                                                   QualType T) {
  if (R->hasStackNonParametersStorage())
    return UndefinedVal();
  else
    return ValMgr.getRegionValueSymbolVal(R, T);
}

Store FlatStoreManager::Bind(Store store, Loc L, SVal val) {
  const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
  RegionBindings B = getRegionBindings(store);
  const BindingVal *V = B.lookup(R);

  BindingVal BV = BVFactory.GetEmptyMap();
  if (V)
    BV = *V;

  Interval I = RegionToInterval(R);
  BV = BVFactory.Add(BV, I, val);
  B = RBFactory.Add(B, R, BV);
  return B.getRoot();
}

Store FlatStoreManager::Remove(Store store, Loc L) {
  return store;
}

Store FlatStoreManager::BindCompoundLiteral(Store store,
                                            const CompoundLiteralExpr* cl,
                                            const LocationContext *LC,
                                            SVal v) {
  return store;
}

SVal FlatStoreManager::ArrayToPointer(Loc Array) {
  return Array;
}

Store FlatStoreManager::BindDecl(Store store, const VarRegion *VR,
                                 SVal initVal) {
  return store;
}

Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
  return store;
}

Store FlatStoreManager::InvalidateRegion(Store store, const MemRegion *R,
                                         const Expr *E, unsigned Count,
                                         InvalidatedSymbols *IS) {
  return store;
}

void FlatStoreManager::print(Store store, llvm::raw_ostream& Out,
                             const char* nl, const char *sep) {
}

void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) {
}

Interval FlatStoreManager::RegionToInterval(const MemRegion *R) {
  switch (R->getKind()) {
  case MemRegion::VarRegionKind: {
    QualType T = cast<VarRegion>(R)->getValueType(Ctx);
    uint64_t Size = Ctx.getTypeSize(T);
    return Interval(0, Size-1);
  }
  default:
    assert(0 && "Region kind unhandled.");
  }
}
<commit_msg>Fix -Asserts warning.<commit_after>//=== FlatStore.cpp - Flat region-based store model -------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Checker/PathSensitive/GRState.h"
#include "llvm/ADT/ImmutableIntervalMap.h"
#include "llvm/Support/ErrorHandling.h"

using namespace clang;
using llvm::Interval;

// The actual store type.
typedef llvm::ImmutableIntervalMap<SVal> BindingVal;
typedef llvm::ImmutableMap<const MemRegion *, BindingVal> RegionBindings;

namespace {
class FlatStoreManager : public StoreManager {
  RegionBindings::Factory RBFactory;
  BindingVal::Factory BVFactory;

public:
  FlatStoreManager(GRStateManager &mgr)
    : StoreManager(mgr),
      RBFactory(mgr.getAllocator()),
      BVFactory(mgr.getAllocator()) {}

  SVal Retrieve(Store store, Loc L, QualType T);
  Store Bind(Store store, Loc L, SVal val);
  Store Remove(Store St, Loc L);
  Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* cl,
                            const LocationContext *LC, SVal v);

  Store getInitialStore(const LocationContext *InitLoc) {
    return RBFactory.GetEmptyMap().getRoot();
  }

  SubRegionMap *getSubRegionMap(Store store) {
    return 0;
  }

  SVal ArrayToPointer(Loc Array);
  Store RemoveDeadBindings(Store store, Stmt* Loc, SymbolReaper& SymReaper,
                         llvm::SmallVectorImpl<const MemRegion*>& RegionRoots){
    return store;
  }

  Store BindDecl(Store store, const VarRegion *VR, SVal initVal);

  Store BindDeclWithNoInit(Store store, const VarRegion *VR);

  typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;

  Store InvalidateRegion(Store store, const MemRegion *R, const Expr *E,
                         unsigned Count, InvalidatedSymbols *IS);

  void print(Store store, llvm::raw_ostream& Out, const char* nl,
             const char *sep);
  void iterBindings(Store store, BindingsHandler& f);

private:
  static RegionBindings getRegionBindings(Store store) {
    return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
  }

  Interval RegionToInterval(const MemRegion *R);

  SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T);
};
} // end anonymous namespace

StoreManager *clang::CreateFlatStoreManager(GRStateManager &StMgr) {
  return new FlatStoreManager(StMgr);
}

SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) {
  const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
  Interval I = RegionToInterval(R);
  RegionBindings B = getRegionBindings(store);
  const BindingVal *BV = B.lookup(R);
  if (BV) {
    const SVal *V = BVFactory.Lookup(*BV, I);
    if (V)
      return *V;
    else
      return RetrieveRegionWithNoBinding(R, T);
  }
  return RetrieveRegionWithNoBinding(R, T);
}

SVal FlatStoreManager::RetrieveRegionWithNoBinding(const MemRegion *R,
                                                   QualType T) {
  if (R->hasStackNonParametersStorage())
    return UndefinedVal();
  else
    return ValMgr.getRegionValueSymbolVal(R, T);
}

Store FlatStoreManager::Bind(Store store, Loc L, SVal val) {
  const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
  RegionBindings B = getRegionBindings(store);
  const BindingVal *V = B.lookup(R);

  BindingVal BV = BVFactory.GetEmptyMap();
  if (V)
    BV = *V;

  Interval I = RegionToInterval(R);
  BV = BVFactory.Add(BV, I, val);
  B = RBFactory.Add(B, R, BV);
  return B.getRoot();
}

Store FlatStoreManager::Remove(Store store, Loc L) {
  return store;
}

Store FlatStoreManager::BindCompoundLiteral(Store store,
                                            const CompoundLiteralExpr* cl,
                                            const LocationContext *LC,
                                            SVal v) {
  return store;
}

SVal FlatStoreManager::ArrayToPointer(Loc Array) {
  return Array;
}

Store FlatStoreManager::BindDecl(Store store, const VarRegion *VR,
                                 SVal initVal) {
  return store;
}

Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
  return store;
}

Store FlatStoreManager::InvalidateRegion(Store store, const MemRegion *R,
                                         const Expr *E, unsigned Count,
                                         InvalidatedSymbols *IS) {
  return store;
}

void FlatStoreManager::print(Store store, llvm::raw_ostream& Out,
                             const char* nl, const char *sep) {
}

void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) {
}

Interval FlatStoreManager::RegionToInterval(const MemRegion *R) {
  switch (R->getKind()) {
  case MemRegion::VarRegionKind: {
    QualType T = cast<VarRegion>(R)->getValueType(Ctx);
    uint64_t Size = Ctx.getTypeSize(T);
    return Interval(0, Size-1);
  }
  default:
    llvm_unreachable("Region kind unhandled.");
    return Interval(0, 0);
  }
}
<|endoftext|>


<commit_before>//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with code generation of C++ declarations
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CGObjCRuntime.h"
#include "CGCXXABI.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"

using namespace clang;
using namespace CodeGen;

static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
                         llvm::Constant *DeclPtr) {
  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
  assert(!D.getType()->isReferenceType() &&
         "Should not call EmitDeclInit on a reference!");

  ASTContext &Context = CGF.getContext();

  const Expr *Init = D.getInit();
  QualType T = D.getType();
  bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();

  unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
  if (!CGF.hasAggregateLLVMType(T)) {
    llvm::Value *V = CGF.EmitScalarExpr(Init);
    CodeGenModule &CGM = CGF.CGM;
    Qualifiers::GC GCAttr = CGM.getContext().getObjCGCAttrKind(T);
    if (GCAttr == Qualifiers::Strong)
      CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, V, DeclPtr,
                                                D.isThreadSpecified());
    else if (GCAttr == Qualifiers::Weak)
      CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, V, DeclPtr);
    else
      CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
  } else if (T->isAnyComplexType()) {
    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
  } else {
    CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true));
  }
}

/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                            llvm::Constant *DeclPtr) {
  CodeGenModule &CGM = CGF.CGM;
  ASTContext &Context = CGF.getContext();

  QualType T = D.getType();

  // Drill down past array types.
  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
  if (Array)
    T = Context.getBaseElementType(Array);

  /// If that's not a record, we're done.
  /// FIXME:  __attribute__((cleanup)) ?
  const RecordType *RT = T->getAs<RecordType>();
  if (!RT)
    return;

  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
  if (RD->hasTrivialDestructor())
    return;

  CXXDestructorDecl *Dtor = RD->getDestructor();

  llvm::Constant *DtorFn;
  if (Array) {
    DtorFn =
      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
                                                           DeclPtr);
    const llvm::Type *Int8PtrTy =
      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
  } else
    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);

  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
}

void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
                                               llvm::Constant *DeclPtr) {

  const Expr *Init = D.getInit();
  QualType T = D.getType();

  if (!T->isReferenceType()) {
    EmitDeclInit(*this, D, DeclPtr);
    EmitDeclDestroy(*this, D, DeclPtr);
    return;
  }

  unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
  RValue RV = EmitReferenceBindingToExpr(Init, &D);
  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
}

void
CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
                                               llvm::Constant *DeclPtr) {
  // Generate a global destructor entry if not using __cxa_atexit.
  if (!CGM.getCodeGenOpts().CXAAtExit) {
    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
    return;
  }

  std::vector<const llvm::Type *> Params;
  Params.push_back(Int8PtrTy);

  // Get the destructor function type
  const llvm::Type *DtorFnTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
                            Params, false);
  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);

  Params.clear();
  Params.push_back(DtorFnTy);
  Params.push_back(Int8PtrTy);
  Params.push_back(Int8PtrTy);

  // Get the __cxa_atexit function type
  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
  const llvm::FunctionType *AtExitFnTy =
    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);

  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
                                                       "__cxa_atexit");
  if (llvm::Function *Fn = dyn_cast<llvm::Function>(AtExitFn))
    Fn->setDoesNotThrow();

  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
                                                     "__dso_handle");
  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
}

void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
                                         llvm::GlobalVariable *DeclPtr) {
  // If we've been asked to forbid guard variables, emit an error now.
  // This diagnostic is hard-coded for Darwin's use case;  we can find
  // better phrasing if someone else needs it.
  if (CGM.getCodeGenOpts().ForbidGuardVariables)
    CGM.Error(D.getLocation(),
              "this initialization requires a guard variable, which "
              "the kernel does not support");

  CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
}

static llvm::Function *
CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
                                   const llvm::FunctionType *FTy,
                                   llvm::StringRef Name) {
  llvm::Function *Fn =
    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
                           Name, &CGM.getModule());
  if (!CGM.getContext().getLangOptions().AppleKext) {
    // Set the section if needed.
    if (const char *Section =
          CGM.getContext().Target.getStaticInitSectionSpecifier())
      Fn->setSection(Section);
  }

  if (!CGM.getLangOptions().Exceptions)
    Fn->setDoesNotThrow();

  return Fn;
}

void
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
                                            llvm::GlobalVariable *Addr) {
  const llvm::FunctionType *FTy
    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                              false);

  // Create a variable initialization function.
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");

  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);

  if (D->hasAttr<InitPriorityAttr>()) {
    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
    DelayedCXXInitPosition.erase(D);
  }
  else {
    llvm::DenseMap<const Decl *, unsigned>::iterator I =
      DelayedCXXInitPosition.find(D);
    if (I == DelayedCXXInitPosition.end()) {
      CXXGlobalInits.push_back(Fn);
    } else {
      assert(CXXGlobalInits[I->second] == 0);
      CXXGlobalInits[I->second] = Fn;
      DelayedCXXInitPosition.erase(I);
    }
  }
}

void
CodeGenModule::EmitCXXGlobalInitFunc() {
  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
    CXXGlobalInits.pop_back();

  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
    return;

  const llvm::FunctionType *FTy
    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                              false);

  // Create our global initialization function.
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");

  if (!PrioritizedCXXGlobalInits.empty()) {
    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
                         PrioritizedCXXGlobalInits.end());
    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
      LocalCXXGlobalInits.push_back(Fn);
    }
    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
                                                    &LocalCXXGlobalInits[0],
                                                    LocalCXXGlobalInits.size());
  }
  else
    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
                                                     &CXXGlobalInits[0],
                                                     CXXGlobalInits.size());
  AddGlobalCtor(Fn);
}

void CodeGenModule::EmitCXXGlobalDtorFunc() {
  if (CXXGlobalDtors.empty())
    return;

  const llvm::FunctionType *FTy
    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                              false);

  // Create our global destructor function.
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");

  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
  AddGlobalDtor(Fn);
}

/// Emit the code necessary to initialize the given global variable.
void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
                                                       const VarDecl *D,
                                                 llvm::GlobalVariable *Addr) {
  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                getTypes().getNullaryFunctionInfo(),
                FunctionArgList(), SourceLocation());

  // Use guarded initialization if the global variable is weak due to
  // being a class template's static data member.  These will always
  // have weak_odr linkage.
  if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage &&
      D->isStaticDataMember() &&
      D->getInstantiatedFromStaticDataMember()) {
    EmitCXXGuardedInit(*D, Addr);
  } else {
    EmitCXXGlobalVarDeclInit(*D, Addr);
  }

  FinishFunction();
}

void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
                                                llvm::Constant **Decls,
                                                unsigned NumDecls) {
  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                getTypes().getNullaryFunctionInfo(),
                FunctionArgList(), SourceLocation());

  for (unsigned i = 0; i != NumDecls; ++i)
    if (Decls[i])
      Builder.CreateCall(Decls[i]);

  FinishFunction();
}

void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
                                                &DtorsAndObjects) {
  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                getTypes().getNullaryFunctionInfo(),
                FunctionArgList(), SourceLocation());

  // Emit the dtors, in reverse order from construction.
  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
    llvm::CallInst *CI = Builder.CreateCall(Callee,
                                            DtorsAndObjects[e - i - 1].second);
    // Make sure the call and the callee agree on calling convention.
    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
      CI->setCallingConv(F->getCallingConv());
  }

  FinishFunction();
}

/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
/// invoked, calls the default destructor on array elements in reverse order of
/// construction.
llvm::Function *
CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
                                                 const ArrayType *Array,
                                                 llvm::Value *This) {
  FunctionArgList args;
  ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy);
  args.push_back(&dst);

  const CGFunctionInfo &FI =
    CGM.getTypes().getFunctionInfo(getContext().VoidTy, args,
                                   FunctionType::ExtInfo());
  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");

  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FI, args,
                SourceLocation());

  QualType BaseElementTy = getContext().getBaseElementType(Array);
  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);

  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);

  FinishFunction();

  return Fn;
}
<commit_msg>Reset the emitted initializers. This enables incremental codegen, where the initializer array can be removed from the module, such that only new initializers will be emitted and run.<commit_after>//===--- CGDeclCXX.cpp - Emit LLVM Code for C++ declarations --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with code generation of C++ declarations
//
//===----------------------------------------------------------------------===//

#include "CodeGenFunction.h"
#include "CGObjCRuntime.h"
#include "CGCXXABI.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "llvm/Intrinsics.h"

using namespace clang;
using namespace CodeGen;

static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
                         llvm::Constant *DeclPtr) {
  assert(D.hasGlobalStorage() && "VarDecl must have global storage!");
  assert(!D.getType()->isReferenceType() &&
         "Should not call EmitDeclInit on a reference!");

  ASTContext &Context = CGF.getContext();

  const Expr *Init = D.getInit();
  QualType T = D.getType();
  bool isVolatile = Context.getCanonicalType(T).isVolatileQualified();

  unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
  if (!CGF.hasAggregateLLVMType(T)) {
    llvm::Value *V = CGF.EmitScalarExpr(Init);
    CodeGenModule &CGM = CGF.CGM;
    Qualifiers::GC GCAttr = CGM.getContext().getObjCGCAttrKind(T);
    if (GCAttr == Qualifiers::Strong)
      CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, V, DeclPtr,
                                                D.isThreadSpecified());
    else if (GCAttr == Qualifiers::Weak)
      CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, V, DeclPtr);
    else
      CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
  } else if (T->isAnyComplexType()) {
    CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
  } else {
    CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true));
  }
}

/// Emit code to cause the destruction of the given variable with
/// static storage duration.
static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D,
                            llvm::Constant *DeclPtr) {
  CodeGenModule &CGM = CGF.CGM;
  ASTContext &Context = CGF.getContext();

  QualType T = D.getType();

  // Drill down past array types.
  const ConstantArrayType *Array = Context.getAsConstantArrayType(T);
  if (Array)
    T = Context.getBaseElementType(Array);

  /// If that's not a record, we're done.
  /// FIXME:  __attribute__((cleanup)) ?
  const RecordType *RT = T->getAs<RecordType>();
  if (!RT)
    return;

  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
  if (RD->hasTrivialDestructor())
    return;

  CXXDestructorDecl *Dtor = RD->getDestructor();

  llvm::Constant *DtorFn;
  if (Array) {
    DtorFn =
      CodeGenFunction(CGM).GenerateCXXAggrDestructorHelper(Dtor, Array,
                                                           DeclPtr);
    const llvm::Type *Int8PtrTy =
      llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
    DeclPtr = llvm::Constant::getNullValue(Int8PtrTy);
  } else
    DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete);

  CGF.EmitCXXGlobalDtorRegistration(DtorFn, DeclPtr);
}

void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
                                               llvm::Constant *DeclPtr) {

  const Expr *Init = D.getInit();
  QualType T = D.getType();

  if (!T->isReferenceType()) {
    EmitDeclInit(*this, D, DeclPtr);
    EmitDeclDestroy(*this, D, DeclPtr);
    return;
  }

  unsigned Alignment = getContext().getDeclAlign(&D).getQuantity();
  RValue RV = EmitReferenceBindingToExpr(Init, &D);
  EmitStoreOfScalar(RV.getScalarVal(), DeclPtr, false, Alignment, T);
}

void
CodeGenFunction::EmitCXXGlobalDtorRegistration(llvm::Constant *DtorFn,
                                               llvm::Constant *DeclPtr) {
  // Generate a global destructor entry if not using __cxa_atexit.
  if (!CGM.getCodeGenOpts().CXAAtExit) {
    CGM.AddCXXDtorEntry(DtorFn, DeclPtr);
    return;
  }

  std::vector<const llvm::Type *> Params;
  Params.push_back(Int8PtrTy);

  // Get the destructor function type
  const llvm::Type *DtorFnTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
                            Params, false);
  DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy);

  Params.clear();
  Params.push_back(DtorFnTy);
  Params.push_back(Int8PtrTy);
  Params.push_back(Int8PtrTy);

  // Get the __cxa_atexit function type
  // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
  const llvm::FunctionType *AtExitFnTy =
    llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false);

  llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy,
                                                       "__cxa_atexit");
  if (llvm::Function *Fn = dyn_cast<llvm::Function>(AtExitFn))
    Fn->setDoesNotThrow();

  llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy,
                                                     "__dso_handle");
  llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy),
                           llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy),
                           llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) };
  Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args));
}

void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D,
                                         llvm::GlobalVariable *DeclPtr) {
  // If we've been asked to forbid guard variables, emit an error now.
  // This diagnostic is hard-coded for Darwin's use case;  we can find
  // better phrasing if someone else needs it.
  if (CGM.getCodeGenOpts().ForbidGuardVariables)
    CGM.Error(D.getLocation(),
              "this initialization requires a guard variable, which "
              "the kernel does not support");

  CGM.getCXXABI().EmitGuardedInit(*this, D, DeclPtr);
}

static llvm::Function *
CreateGlobalInitOrDestructFunction(CodeGenModule &CGM,
                                   const llvm::FunctionType *FTy,
                                   llvm::StringRef Name) {
  llvm::Function *Fn =
    llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage,
                           Name, &CGM.getModule());
  if (!CGM.getContext().getLangOptions().AppleKext) {
    // Set the section if needed.
    if (const char *Section =
          CGM.getContext().Target.getStaticInitSectionSpecifier())
      Fn->setSection(Section);
  }

  if (!CGM.getLangOptions().Exceptions)
    Fn->setDoesNotThrow();

  return Fn;
}

void
CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
                                            llvm::GlobalVariable *Addr) {
  const llvm::FunctionType *FTy
    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                              false);

  // Create a variable initialization function.
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(*this, FTy, "__cxx_global_var_init");

  CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr);

  if (D->hasAttr<InitPriorityAttr>()) {
    unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
    OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
    PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
    DelayedCXXInitPosition.erase(D);
  }
  else {
    llvm::DenseMap<const Decl *, unsigned>::iterator I =
      DelayedCXXInitPosition.find(D);
    if (I == DelayedCXXInitPosition.end()) {
      CXXGlobalInits.push_back(Fn);
    } else {
      assert(CXXGlobalInits[I->second] == 0);
      CXXGlobalInits[I->second] = Fn;
      DelayedCXXInitPosition.erase(I);
    }
  }
}

void
CodeGenModule::EmitCXXGlobalInitFunc() {
  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
    CXXGlobalInits.pop_back();

  if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
    return;

  const llvm::FunctionType *FTy
    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                              false);

  // Create our global initialization function.
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");

  if (!PrioritizedCXXGlobalInits.empty()) {
    llvm::SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
    llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
                         PrioritizedCXXGlobalInits.end());
    for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
      llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
      LocalCXXGlobalInits.push_back(Fn);
    }
    LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
                                                    &LocalCXXGlobalInits[0],
                                                    LocalCXXGlobalInits.size());
  }
  else
    CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
                                                     &CXXGlobalInits[0],
                                                     CXXGlobalInits.size());
  AddGlobalCtor(Fn);
  CXXGlobalInits.clear();
  PrioritizedCXXGlobalInits.clear();
}

void CodeGenModule::EmitCXXGlobalDtorFunc() {
  if (CXXGlobalDtors.empty())
    return;

  const llvm::FunctionType *FTy
    = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
                              false);

  // Create our global destructor function.
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");

  CodeGenFunction(*this).GenerateCXXGlobalDtorFunc(Fn, CXXGlobalDtors);
  AddGlobalDtor(Fn);
}

/// Emit the code necessary to initialize the given global variable.
void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn,
                                                       const VarDecl *D,
                                                 llvm::GlobalVariable *Addr) {
  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                getTypes().getNullaryFunctionInfo(),
                FunctionArgList(), SourceLocation());

  // Use guarded initialization if the global variable is weak due to
  // being a class template's static data member.  These will always
  // have weak_odr linkage.
  if (Addr->getLinkage() == llvm::GlobalValue::WeakODRLinkage &&
      D->isStaticDataMember() &&
      D->getInstantiatedFromStaticDataMember()) {
    EmitCXXGuardedInit(*D, Addr);
  } else {
    EmitCXXGlobalVarDeclInit(*D, Addr);
  }

  FinishFunction();
}

void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
                                                llvm::Constant **Decls,
                                                unsigned NumDecls) {
  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                getTypes().getNullaryFunctionInfo(),
                FunctionArgList(), SourceLocation());

  for (unsigned i = 0; i != NumDecls; ++i)
    if (Decls[i])
      Builder.CreateCall(Decls[i]);

  FinishFunction();
}

void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn,
                  const std::vector<std::pair<llvm::WeakVH, llvm::Constant*> >
                                                &DtorsAndObjects) {
  StartFunction(GlobalDecl(), getContext().VoidTy, Fn,
                getTypes().getNullaryFunctionInfo(),
                FunctionArgList(), SourceLocation());

  // Emit the dtors, in reverse order from construction.
  for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
    llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
    llvm::CallInst *CI = Builder.CreateCall(Callee,
                                            DtorsAndObjects[e - i - 1].second);
    // Make sure the call and the callee agree on calling convention.
    if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
      CI->setCallingConv(F->getCallingConv());
  }

  FinishFunction();
}

/// GenerateCXXAggrDestructorHelper - Generates a helper function which when
/// invoked, calls the default destructor on array elements in reverse order of
/// construction.
llvm::Function *
CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
                                                 const ArrayType *Array,
                                                 llvm::Value *This) {
  FunctionArgList args;
  ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy);
  args.push_back(&dst);

  const CGFunctionInfo &FI =
    CGM.getTypes().getFunctionInfo(getContext().VoidTy, args,
                                   FunctionType::ExtInfo());
  const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false);
  llvm::Function *Fn =
    CreateGlobalInitOrDestructFunction(CGM, FTy, "__cxx_global_array_dtor");

  StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FI, args,
                SourceLocation());

  QualType BaseElementTy = getContext().getBaseElementType(Array);
  const llvm::Type *BasePtr = ConvertType(BaseElementTy)->getPointerTo();
  llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr);

  EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);

  FinishFunction();

  return Fn;
}
<|endoftext|>


<commit_before>/*
This file is part of HadesMem.
Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).
<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

HadesMem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HadesMem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HadesMem.  If not, see <http://www.gnu.org/licenses/>.
*/

// C++ Standard Library
#include <set>
#include <string>
#include <iostream>
#include <exception>
#include <algorithm>

// Boost
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>

// Windows
#include <crtdbg.h>
#include <Windows.h>

// Hades
#include "HadesCommon/I18n.hpp"
#include "HadesMemory/Memory.hpp"

int wmain(int argc, wchar_t* argv[], wchar_t* /*envp*/[])
{
  try
  {
    // Attempt to detect memory leaks in debug mode
#ifdef _DEBUG
    int CurrentFlags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
    int NewFlags = (_CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF |
      _CRTDBG_CHECK_ALWAYS_DF);
    _CrtSetDbgFlag(CurrentFlags | NewFlags);

    // Get default heap
    HANDLE ProcHeap = GetProcessHeap();
    if (!ProcHeap)
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not get process heap.") <<
        Hades::ErrorCode(LastError));
    }

    // Detect heap corruption
    if (!HeapSetInformation(ProcHeap, HeapEnableTerminationOnCorruption,
      NULL, 0))
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not set heap information.") <<
        Hades::ErrorCode(LastError));
    }
#endif

    // Hades version number
    std::wstring const VerNum(L"TRUNK");

    // Version and copyright output
#if defined(_M_X64)
    std::wcout << "Hades ExportDiff AMD64 [Version " << VerNum << "]\n";
#elif defined(_M_IX86)
    std::wcout << "Hades ExportDiff IA32 [Version " << VerNum << "]\n";
#else
#error "[HadesMem] Unsupported architecture."
#endif
    std::wcout << "Copyright (C) 2011 RaptorFactor. All rights reserved." <<
      std::endl;
    std::wcout << "Website: http://www.raptorfactor.com/, "
      "Email: raptorfactor@raptorfactor.com." << std::endl;
    std::wcout << "Compiler: \"" << BOOST_COMPILER << "\", Standard "
      "Library: \"" << BOOST_STDLIB << "\", Platform: \"" << BOOST_PLATFORM
      << "\", Boost: " << BOOST_VERSION << "." << std::endl;
    std::wcout << "Built on " << __DATE__ << " at " << __TIME__ << "." <<
      std::endl << std::endl;

    // Get target module from args
    if (argc < 2)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a base module path."));
    }
    boost::filesystem::path BaseModulePath;
    try
    {
      BaseModulePath = argv[1];
    }
    catch (std::exception const& /*e*/)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a base module path."));
    }

    // Get target module from args
    if (argc < 3)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a target module path."));
    }
    boost::filesystem::path TargetModulePath;
    try
    {
      TargetModulePath = argv[2];
    }
    catch (std::exception const& /*e*/)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a target module path."));
    }

    // Open memory manager
    Hades::Memory::MemoryMgr MyMemory(GetCurrentProcessId());

    // Load base module
    Hades::Windows::EnsureFreeLibrary BaseMod = LoadLibraryEx(BaseModulePath.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
    if (!BaseMod)
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not load base module.") <<
        Hades::ErrorCode(LastError));
    }

    // Load target module
    Hades::Windows::EnsureFreeLibrary TargetMod = LoadLibraryEx(TargetModulePath.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
    if (!TargetMod)
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not load base module.") <<
        Hades::ErrorCode(LastError));
    }

    // Get exports for module
    auto GetExports = [&MyMemory] (HMODULE Base) -> std::set<std::string>
    {
      // Create PE file object for current module
      Hades::Memory::PeFile MyPeFile(MyMemory, Base);

      // Export list
      std::set<std::string> Result;

      Hades::Memory::ExportList Exports(MyPeFile);
      std::transform(Exports.begin(), Exports.end(), std::inserter(Result, Result.begin()),
        [&] (Hades::Memory::Export& E) -> std::string
        {
          if (E.ByName())
          {
            return E.GetName();
          }
          else
          {
            return "#" + boost::lexical_cast<std::string>(E.GetOrdinal());
          }
        });

      return Result;
    };

    std::set<std::string> BaseExports(GetExports(BaseMod));
    std::set<std::string> TargetExports(GetExports(TargetMod));

    std::set<std::string> NewExports;
    set_difference(TargetExports.begin(), TargetExports.end(), BaseExports.begin(), BaseExports.end(), std::inserter(NewExports, NewExports.begin()));

    std::wcout << "New Exports:\n";
    std::copy(NewExports.begin(), NewExports.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
  }
  catch (std::exception const& e)
  {
    std::cerr << boost::diagnostic_information(e) << std::endl;
  }
}
<commit_msg>* Slight exportdiff cleanup.<commit_after>/*
This file is part of HadesMem.
Copyright (C) 2011 Joshua Boyce (a.k.a. RaptorFactor).
<http://www.raptorfactor.com/> <raptorfactor@raptorfactor.com>

HadesMem is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

HadesMem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HadesMem.  If not, see <http://www.gnu.org/licenses/>.
*/

// C++ Standard Library
#include <set>
#include <string>
#include <iostream>
#include <exception>
#include <algorithm>

// Boost
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>

// Windows
#include <crtdbg.h>
#include <Windows.h>

// Hades
#include "HadesCommon/I18n.hpp"
#include "HadesMemory/Memory.hpp"

int wmain(int argc, wchar_t* argv[], wchar_t* /*envp*/[])
{
  try
  {
    // Attempt to detect memory leaks in debug mode
#ifdef _DEBUG
    int CurrentFlags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
    int NewFlags = (_CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF |
      _CRTDBG_CHECK_ALWAYS_DF);
    _CrtSetDbgFlag(CurrentFlags | NewFlags);

    // Get default heap
    HANDLE ProcHeap = GetProcessHeap();
    if (!ProcHeap)
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not get process heap.") <<
        Hades::ErrorCode(LastError));
    }

    // Detect heap corruption
    if (!HeapSetInformation(ProcHeap, HeapEnableTerminationOnCorruption,
      NULL, 0))
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not set heap information.") <<
        Hades::ErrorCode(LastError));
    }
#endif

    // Hades version number
    std::wstring const VerNum(L"TRUNK");

    // Version and copyright output
#if defined(_M_X64)
    std::wcout << "Hades ExportDiff AMD64 [Version " << VerNum << "]\n";
#elif defined(_M_IX86)
    std::wcout << "Hades ExportDiff IA32 [Version " << VerNum << "]\n";
#else
#error "[HadesMem] Unsupported architecture."
#endif
    std::wcout << "Copyright (C) 2011 RaptorFactor. All rights reserved." <<
      std::endl;
    std::wcout << "Website: http://www.raptorfactor.com/, "
      "Email: raptorfactor@raptorfactor.com." << std::endl;
    std::wcout << "Compiler: \"" << BOOST_COMPILER << "\", Standard "
      "Library: \"" << BOOST_STDLIB << "\", Platform: \"" << BOOST_PLATFORM
      << "\", Boost: " << BOOST_VERSION << "." << std::endl;
    std::wcout << "Built on " << __DATE__ << " at " << __TIME__ << "." <<
      std::endl << std::endl;

    // Get target module from args
    if (argc < 2)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a base module path."));
    }
    boost::filesystem::path BaseModulePath;
    try
    {
      BaseModulePath = argv[1];
    }
    catch (std::exception const& /*e*/)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a base module path."));
    }

    // Get target module from args
    if (argc < 3)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a target module path."));
    }
    boost::filesystem::path TargetModulePath;
    try
    {
      TargetModulePath = argv[2];
    }
    catch (std::exception const& /*e*/)
    {
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("You must supply a target module path."));
    }

    // Open memory manager
    Hades::Memory::MemoryMgr MyMemory(GetCurrentProcessId());

    // Load base module
    Hades::Windows::EnsureFreeLibrary BaseMod = LoadLibraryEx(
      BaseModulePath.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
    if (!BaseMod)
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not load base module.") <<
        Hades::ErrorCode(LastError));
    }

    // Load target module
    Hades::Windows::EnsureFreeLibrary TargetMod = LoadLibraryEx(
      TargetModulePath.c_str(), nullptr, DONT_RESOLVE_DLL_REFERENCES);
    if (!TargetMod)
    {
      std::error_code const LastError = Hades::GetLastErrorCode();
      BOOST_THROW_EXCEPTION(Hades::HadesError() <<
        Hades::ErrorFunction("wmain") <<
        Hades::ErrorString("Could not load base module.") <<
        Hades::ErrorCode(LastError));
    }

    // Get exports for module
    auto GetExports = [&MyMemory] (HMODULE Base) -> std::set<std::string>
    {
      // Create PE file object for current module
      Hades::Memory::PeFile MyPeFile(MyMemory, Base);

      // Export list
      std::set<std::string> Result;

      Hades::Memory::ExportList Exports(MyPeFile);
      std::transform(Exports.begin(), Exports.end(), std::inserter(Result,
        Result.begin()),
        [&] (Hades::Memory::Export& E) -> std::string
        {
          if (E.ByName())
          {
            return E.GetName();
          }
          else
          {
            return "#" + boost::lexical_cast<std::string>(E.GetOrdinal());
          }
        });

      return Result;
    };

    // Get exports for base module
    std::set<std::string> BaseExports(GetExports(BaseMod));

    // Get exports for target module
    std::set<std::string> TargetExports(GetExports(TargetMod));

    // Find exports in target that do not exist in base
    std::set<std::string> NewExports;
    set_difference(TargetExports.begin(), TargetExports.end(),
      BaseExports.begin(), BaseExports.end(), std::inserter(NewExports,
      NewExports.begin()));

    // Dump new exports
    std::wcout << "New Exports:\n";
    std::copy(NewExports.begin(), NewExports.end(),
      std::ostream_iterator<std::string>(std::cout, "\n"));
  }
  catch (std::exception const& e)
  {
    std::cerr << boost::diagnostic_information(e) << std::endl;
  }
}
<|endoftext|>


<commit_before>/* Copyright (c) 2011-2015, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <TAccessValidator>
#include <TAbstractUser>
#include <TActionContext>
#include <TActionController>
#include <TSystemGlobal>

/*!
  \class TAccessValidator
  The TAccessValidator class provides validation of user access.
  \sa TAbstractUser class
*/

/*!
  Constructor.
*/
TAccessValidator::TAccessValidator()
    : allowDefault(true)
{ }

/*!
  Sets to allow a group with \a groupKey to access to the action \a action.
*/
void TAccessValidator::setAllowGroup(const QString &groupKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::Group, groupKey, action, true);
}

/*!
  Sets to allow a group with \a groupKey to access to the actions \a actions.
*/
void TAccessValidator::setAllowGroup(const QString &groupKey, const QStringList &actions)
{
    addRules(AccessRule::Group, groupKey, actions, true);
}

/*!
  Sets to deny a group with \a groupKey to access to the action \a action.
*/
void TAccessValidator::setDenyGroup(const QString &groupKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::Group, groupKey, action, false);
}

/*!
  Sets to deny a group with \a groupKey to access to the actions \a actions.
*/
void TAccessValidator::setDenyGroup(const QString &groupKey, const QStringList &actions)
{
    addRules(AccessRule::Group, groupKey, actions, false);
}

/*!
  Sets to allow a user with the identity \a identityKey to access to
  the action \a action.
*/
void TAccessValidator::setAllowUser(const QString &identityKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::User, identityKey, action, true);
}

/*!
  Sets to allow a user with the identity \a identityKey to access to
  the actions \a actions.
*/
void TAccessValidator::setAllowUser(const QString &identityKey, const QStringList &actions)
{
    addRules(AccessRule::User, identityKey, actions, true);
}

/*!
  Sets to deny a user with the identity \a identityKey to access to
  the action \a action.
*/
void TAccessValidator::setDenyUser(const QString &identityKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::User, identityKey, action, false);
}

/*!
  Sets to deny a user with the identity \a identityKey to access to
  the actions \a actions.
*/
void TAccessValidator::setDenyUser(const QString &identityKey, const QStringList &actions)
{
    addRules(AccessRule::User, identityKey, actions, false);
}

/*!
  Sets to allow an unauthenticated user with the identity \a identityKey
  to access to the action \a action.
*/
void TAccessValidator::setAllowUnauthenticatedUser(const QString &action)
{
    accessRules << AccessRule(AccessRule::UnauthenticatedUser, QString(), action, true);
}

/*!
  Sets to allow an unauthenticated with the identity \a identityKey to
  access to the actions \a actions.
*/
void TAccessValidator::setAllowUnauthenticatedUser(const QStringList &actions)
{
    addRules(AccessRule::UnauthenticatedUser, QString(), actions, true);
}

/*!
  Sets to deny an unauthenticated with the identity \a identityKey to
  access to the action \a action.
*/
void TAccessValidator::setDenyUnauthenticatedUser(const QString &action)
{
    accessRules << AccessRule(AccessRule::UnauthenticatedUser, QString(), action, false);
}

/*!
  Sets to deny an unauthenticated with the identity \a identityKey to
  access to the actions \a actions.
*/
void TAccessValidator::setDenyUnauthenticatedUser(const QStringList &actions)
{
    addRules(AccessRule::UnauthenticatedUser, QString(), actions, false);
}

/*!
  Added a access rule to the list.
*/
void TAccessValidator::addRules(int type, const QString &key, const QStringList &actions, bool allow)
{
    for (QListIterator<QString> it(actions); it.hasNext(); ) {
        accessRules << AccessRule(type, key, it.next(), allow);
    }
}

/*!
  Returns true if the user \a user is allowed to access to the requested
  action; otherwise returns false.
*/
bool TAccessValidator::validate(const TAbstractUser *user) const
{
    bool ret = allowDefault;
    const TActionController *controller = Tf::currentContext()->currentController();
    Q_ASSERT(controller);

    if (accessRules.isEmpty()) {
        tWarn("No rule for access validation: %s", qPrintable(controller->className()));
        return ret;
    }

    if (!user || user->identityKey().isEmpty()) {
        // Searches a access rule for an unauthenticated user
        for (QListIterator<AccessRule> it(accessRules); it.hasNext(); ) {
            const AccessRule &rule = it.next();
            if (rule.type == AccessRule::UnauthenticatedUser
                && rule.action == controller->activeAction()) {
                ret = rule.allow;
                break;
            }
        }
        tSystemDebug("Access '%s' action by an unauthenticated user : %s", qPrintable(controller->activeAction()), (ret ? "Allow" : "Deny"));

    } else {
        for (QListIterator<AccessRule> it(accessRules); it.hasNext(); ) {
            const AccessRule &rule = it.next();
            if (rule.action == controller->activeAction()
                && ((rule.type == AccessRule::User && rule.key == user->identityKey())
                    || (!user->groupKey().isEmpty() && rule.key == user->groupKey()))) {
                ret = rule.allow;
                break;
            }
        }
        tSystemDebug("Access '%s' action by '%s' user : %s", qPrintable(controller->activeAction()), qPrintable(user->identityKey()), (ret ? "Allow" : "Deny"));
    }

    return ret;
}

/*!
  Removes all access rules from the list.
*/
void TAccessValidator::clear()
{
    accessRules.clear();
    allowDefault = true;
}

/*!
  \fn void TAccessValidator::setAllowDefault(bool allow)
  Sets the default rule to allow all users to access to all actions
  if \a allow is true; otherwise sets to deny any user to access
  to any action. The default rule is true.
*/

/*!
  \fn void TAccessValidator::setDenyDefault(bool deny)
  Sets the default rule to deny any user to access to any action
  if \a deny is true; otherwise sets to allow all users to access
  to all actions.
*/

/*!
  \class TAccessValidator::AccessRule
  The AccessRule class is for internal use only.
*/
<commit_msg>update auth log messages.<commit_after>/* Copyright (c) 2011-2015, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <TAccessValidator>
#include <TAbstractUser>
#include <TActionContext>
#include <TActionController>
#include <TSystemGlobal>

/*!
  \class TAccessValidator
  The TAccessValidator class provides validation of user access.
  \sa TAbstractUser class
*/

/*!
  Constructor.
*/
TAccessValidator::TAccessValidator()
    : allowDefault(true)
{ }

/*!
  Sets to allow a group with \a groupKey to access to the action \a action.
*/
void TAccessValidator::setAllowGroup(const QString &groupKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::Group, groupKey, action, true);
}

/*!
  Sets to allow a group with \a groupKey to access to the actions \a actions.
*/
void TAccessValidator::setAllowGroup(const QString &groupKey, const QStringList &actions)
{
    addRules(AccessRule::Group, groupKey, actions, true);
}

/*!
  Sets to deny a group with \a groupKey to access to the action \a action.
*/
void TAccessValidator::setDenyGroup(const QString &groupKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::Group, groupKey, action, false);
}

/*!
  Sets to deny a group with \a groupKey to access to the actions \a actions.
*/
void TAccessValidator::setDenyGroup(const QString &groupKey, const QStringList &actions)
{
    addRules(AccessRule::Group, groupKey, actions, false);
}

/*!
  Sets to allow a user with the identity \a identityKey to access to
  the action \a action.
*/
void TAccessValidator::setAllowUser(const QString &identityKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::User, identityKey, action, true);
}

/*!
  Sets to allow a user with the identity \a identityKey to access to
  the actions \a actions.
*/
void TAccessValidator::setAllowUser(const QString &identityKey, const QStringList &actions)
{
    addRules(AccessRule::User, identityKey, actions, true);
}

/*!
  Sets to deny a user with the identity \a identityKey to access to
  the action \a action.
*/
void TAccessValidator::setDenyUser(const QString &identityKey, const QString &action)
{
    accessRules << AccessRule(AccessRule::User, identityKey, action, false);
}

/*!
  Sets to deny a user with the identity \a identityKey to access to
  the actions \a actions.
*/
void TAccessValidator::setDenyUser(const QString &identityKey, const QStringList &actions)
{
    addRules(AccessRule::User, identityKey, actions, false);
}

/*!
  Sets to allow an unauthenticated user with the identity \a identityKey
  to access to the action \a action.
*/
void TAccessValidator::setAllowUnauthenticatedUser(const QString &action)
{
    accessRules << AccessRule(AccessRule::UnauthenticatedUser, QString(), action, true);
}

/*!
  Sets to allow an unauthenticated with the identity \a identityKey to
  access to the actions \a actions.
*/
void TAccessValidator::setAllowUnauthenticatedUser(const QStringList &actions)
{
    addRules(AccessRule::UnauthenticatedUser, QString(), actions, true);
}

/*!
  Sets to deny an unauthenticated with the identity \a identityKey to
  access to the action \a action.
*/
void TAccessValidator::setDenyUnauthenticatedUser(const QString &action)
{
    accessRules << AccessRule(AccessRule::UnauthenticatedUser, QString(), action, false);
}

/*!
  Sets to deny an unauthenticated with the identity \a identityKey to
  access to the actions \a actions.
*/
void TAccessValidator::setDenyUnauthenticatedUser(const QStringList &actions)
{
    addRules(AccessRule::UnauthenticatedUser, QString(), actions, false);
}

/*!
  Added a access rule to the list.
*/
void TAccessValidator::addRules(int type, const QString &key, const QStringList &actions, bool allow)
{
    for (QListIterator<QString> it(actions); it.hasNext(); ) {
        accessRules << AccessRule(type, key, it.next(), allow);
    }
}

/*!
  Returns true if the user \a user is allowed to access to the requested
  action; otherwise returns false.
*/
bool TAccessValidator::validate(const TAbstractUser *user) const
{
    bool ret = allowDefault;
    const TActionController *controller = Tf::currentContext()->currentController();
    Q_ASSERT(controller);

    if (accessRules.isEmpty()) {
        tWarn("No rule for access validation: %s", qPrintable(controller->className()));
        return ret;
    }

    if (!user || user->identityKey().isEmpty()) {
        // Searches a access rule for an unauthenticated user
        for (QListIterator<AccessRule> it(accessRules); it.hasNext(); ) {
            const AccessRule &rule = it.next();
            if (rule.type == AccessRule::UnauthenticatedUser
                && rule.action == controller->activeAction()) {
                ret = rule.allow;
                break;
            }
        }
        if (ret) {
            tSystemDebug("Access '%s' action by an unauthenticated user : Allow", qPrintable(controller->activeAction()));
        } else {
            tSystemWarn("Access '%s' action by an unauthenticated user : Deny", qPrintable(controller->activeAction()));
        }

    } else {
        for (QListIterator<AccessRule> it(accessRules); it.hasNext(); ) {
            const AccessRule &rule = it.next();
            if (rule.action == controller->activeAction()
                && ((rule.type == AccessRule::User && rule.key == user->identityKey())
                    || (!user->groupKey().isEmpty() && rule.key == user->groupKey()))) {
                ret = rule.allow;
                break;
            }
        }
        if (ret) {
            tSystemDebug("Access '%s' action by '%s' user : Allow", qPrintable(controller->activeAction()), qPrintable(user->identityKey()));
        } else {
            tSystemWarn("Access '%s' action by '%s' user : Deny", qPrintable(controller->activeAction()), qPrintable(user->identityKey()));
        }
    }

    return ret;
}

/*!
  Removes all access rules from the list.
*/
void TAccessValidator::clear()
{
    accessRules.clear();
    allowDefault = true;
}

/*!
  \fn void TAccessValidator::setAllowDefault(bool allow)
  Sets the default rule to allow all users to access to all actions
  if \a allow is true; otherwise sets to deny any user to access
  to any action. The default rule is true.
*/

/*!
  \fn void TAccessValidator::setDenyDefault(bool deny)
  Sets the default rule to deny any user to access to any action
  if \a deny is true; otherwise sets to allow all users to access
  to all actions.
*/

/*!
  \class TAccessValidator::AccessRule
  The AccessRule class is for internal use only.
*/
<|endoftext|>