//===- StackSafetyAnalysis.cpp - Stack memory safety analysis -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/StackSafetyAnalysis.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

#define DEBUG_TYPE "stack-safety"

static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations",
                                             cl::init(20), cl::Hidden);

namespace {

/// Rewrite an SCEV expression for a memory access address to an expression that
/// represents offset from the given alloca.
class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> {
  const Value *AllocaPtr;

public:
  AllocaOffsetRewriter(ScalarEvolution &SE, const Value *AllocaPtr)
      : SCEVRewriteVisitor(SE), AllocaPtr(AllocaPtr) {}

  const SCEV *visit(const SCEV *Expr) {
    // Only re-write the expression if the alloca is used in an addition
    // expression (it can be used in other types of expressions if it's cast to
    // an int and passed as an argument.)
    if (!isa<SCEVAddRecExpr>(Expr) && !isa<SCEVAddExpr>(Expr) &&
        !isa<SCEVUnknown>(Expr))
      return Expr;
    return SCEVRewriteVisitor<AllocaOffsetRewriter>::visit(Expr);
  }

  const SCEV *visitUnknown(const SCEVUnknown *Expr) {
    // FIXME: look through one or several levels of definitions?
    // This can be inttoptr(AllocaPtr) and SCEV would not unwrap
    // it for us.
    if (Expr->getValue() == AllocaPtr)
      return SE.getZero(Expr->getType());
    return Expr;
  }
};

/// Describes use of address in as a function call argument.
struct PassAsArgInfo {
  /// Function being called.
  const GlobalValue *Callee = nullptr;
  /// Index of argument which pass address.
  size_t ParamNo = 0;
  // Offset range of address from base address (alloca or calling function
  // argument).
  // Range should never set to empty-set, that is an invalid access range
  // that can cause empty-set to be propagated with ConstantRange::add
  ConstantRange Offset;
  PassAsArgInfo(const GlobalValue *Callee, size_t ParamNo, ConstantRange Offset)
      : Callee(Callee), ParamNo(ParamNo), Offset(Offset) {}

  StringRef getName() const { return Callee->getName(); }
};

raw_ostream &operator<<(raw_ostream &OS, const PassAsArgInfo &P) {
  return OS << "@" << P.getName() << "(arg" << P.ParamNo << ", " << P.Offset
            << ")";
}

/// Describe uses of address (alloca or parameter) inside of the function.
struct UseInfo {
  // Access range if the address (alloca or parameters).
  // It is allowed to be empty-set when there are no known accesses.
  ConstantRange Range;

  // List of calls which pass address as an argument.
  SmallVector<PassAsArgInfo, 4> Calls;

  explicit UseInfo(unsigned PointerSize) : Range{PointerSize, false} {}

  void updateRange(ConstantRange R) { Range = Range.unionWith(R); }
};

raw_ostream &operator<<(raw_ostream &OS, const UseInfo &U) {
  OS << U.Range;
  for (auto &Call : U.Calls)
    OS << ", " << Call;
  return OS;
}

struct AllocaInfo {
  const AllocaInst *AI = nullptr;
  uint64_t Size = 0;
  UseInfo Use;

  AllocaInfo(unsigned PointerSize, const AllocaInst *AI, uint64_t Size)
      : AI(AI), Size(Size), Use(PointerSize) {}

  StringRef getName() const { return AI->getName(); }
};

raw_ostream &operator<<(raw_ostream &OS, const AllocaInfo &A) {
  return OS << A.getName() << "[" << A.Size << "]: " << A.Use;
}

struct ParamInfo {
  const Argument *Arg = nullptr;
  UseInfo Use;

  explicit ParamInfo(unsigned PointerSize, const Argument *Arg)
      : Arg(Arg), Use(PointerSize) {}

  StringRef getName() const { return Arg ? Arg->getName() : "<N/A>"; }
};

raw_ostream &operator<<(raw_ostream &OS, const ParamInfo &P) {
  return OS << P.getName() << "[]: " << P.Use;
}

/// Calculate the allocation size of a given alloca. Returns 0 if the
/// size can not be statically determined.
uint64_t getStaticAllocaAllocationSize(const AllocaInst *AI) {
  const DataLayout &DL = AI->getModule()->getDataLayout();
  uint64_t Size = DL.getTypeAllocSize(AI->getAllocatedType());
  if (AI->isArrayAllocation()) {
    auto C = dyn_cast<ConstantInt>(AI->getArraySize());
    if (!C)
      return 0;
    Size *= C->getZExtValue();
  }
  return Size;
}

} // end anonymous namespace

/// Describes uses of allocas and parameters inside of a single function.
struct StackSafetyInfo::FunctionInfo {
  // May be a Function or a GlobalAlias
  const GlobalValue *GV = nullptr;
  // Informations about allocas uses.
  SmallVector<AllocaInfo, 4> Allocas;
  // Informations about parameters uses.
  SmallVector<ParamInfo, 4> Params;
  // TODO: describe return value as depending on one or more of its arguments.

  // StackSafetyDataFlowAnalysis counter stored here for faster access.
  int UpdateCount = 0;

  FunctionInfo(const StackSafetyInfo &SSI) : FunctionInfo(*SSI.Info) {}

  explicit FunctionInfo(const Function *F) : GV(F){};
  // Creates FunctionInfo that forwards all the parameters to the aliasee.
  explicit FunctionInfo(const GlobalAlias *A);

  FunctionInfo(FunctionInfo &&) = default;

  bool IsDSOLocal() const { return GV->isDSOLocal(); };

  bool IsInterposable() const { return GV->isInterposable(); };

  StringRef getName() const { return GV->getName(); }

  void print(raw_ostream &O) const {
    // TODO: Consider different printout format after
    // StackSafetyDataFlowAnalysis. Calls and parameters are irrelevant then.
    O << "  @" << getName() << (IsDSOLocal() ? "" : " dso_preemptable")
      << (IsInterposable() ? " interposable" : "") << "\n";
    O << "    args uses:\n";
    for (auto &P : Params)
      O << "      " << P << "\n";
    O << "    allocas uses:\n";
    for (auto &AS : Allocas)
      O << "      " << AS << "\n";
  }

private:
  FunctionInfo(const FunctionInfo &) = default;
};

StackSafetyInfo::FunctionInfo::FunctionInfo(const GlobalAlias *A) : GV(A) {
  unsigned PointerSize = A->getParent()->getDataLayout().getPointerSizeInBits();
  const GlobalObject *Aliasee = A->getBaseObject();
  const FunctionType *Type = cast<FunctionType>(Aliasee->getValueType());
  // 'Forward' all parameters to this alias to the aliasee
  for (unsigned ArgNo = 0; ArgNo < Type->getNumParams(); ArgNo++) {
    Params.emplace_back(PointerSize, nullptr);
    UseInfo &US = Params.back().Use;
    US.Calls.emplace_back(Aliasee, ArgNo, ConstantRange(APInt(PointerSize, 0)));
  }
}

namespace {

class StackSafetyLocalAnalysis {
  const Function &F;
  const DataLayout &DL;
  ScalarEvolution &SE;
  unsigned PointerSize = 0;

  const ConstantRange UnknownRange;

  ConstantRange offsetFromAlloca(Value *Addr, const Value *AllocaPtr);
  ConstantRange getAccessRange(Value *Addr, const Value *AllocaPtr,
                               uint64_t AccessSize);
  ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U,
                                           const Value *AllocaPtr);

  bool analyzeAllUses(const Value *Ptr, UseInfo &AS);

  ConstantRange getRange(uint64_t Lower, uint64_t Upper) const {
    return ConstantRange(APInt(PointerSize, Lower), APInt(PointerSize, Upper));
  }

public:
  StackSafetyLocalAnalysis(const Function &F, ScalarEvolution &SE)
      : F(F), DL(F.getParent()->getDataLayout()), SE(SE),
        PointerSize(DL.getPointerSizeInBits()),
        UnknownRange(PointerSize, true) {}

  // Run the transformation on the associated function.
  StackSafetyInfo run();
};

ConstantRange
StackSafetyLocalAnalysis::offsetFromAlloca(Value *Addr,
                                           const Value *AllocaPtr) {
  if (!SE.isSCEVable(Addr->getType()))
    return UnknownRange;

  AllocaOffsetRewriter Rewriter(SE, AllocaPtr);
  const SCEV *Expr = Rewriter.visit(SE.getSCEV(Addr));
  ConstantRange Offset = SE.getUnsignedRange(Expr).zextOrTrunc(PointerSize);
  assert(!Offset.isEmptySet());
  return Offset;
}

ConstantRange StackSafetyLocalAnalysis::getAccessRange(Value *Addr,
                                                       const Value *AllocaPtr,
                                                       uint64_t AccessSize) {
  if (!SE.isSCEVable(Addr->getType()))
    return UnknownRange;

  AllocaOffsetRewriter Rewriter(SE, AllocaPtr);
  const SCEV *Expr = Rewriter.visit(SE.getSCEV(Addr));

  ConstantRange AccessStartRange =
      SE.getUnsignedRange(Expr).zextOrTrunc(PointerSize);
  ConstantRange SizeRange = getRange(0, AccessSize);
  ConstantRange AccessRange = AccessStartRange.add(SizeRange);
  assert(!AccessRange.isEmptySet());
  return AccessRange;
}

ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange(
    const MemIntrinsic *MI, const Use &U, const Value *AllocaPtr) {
  if (auto MTI = dyn_cast<MemTransferInst>(MI)) {
    if (MTI->getRawSource() != U && MTI->getRawDest() != U)
      return getRange(0, 1);
  } else {
    if (MI->getRawDest() != U)
      return getRange(0, 1);
  }
  const auto *Len = dyn_cast<ConstantInt>(MI->getLength());
  // Non-constant size => unsafe. FIXME: try SCEV getRange.
  if (!Len)
    return UnknownRange;
  ConstantRange AccessRange = getAccessRange(U, AllocaPtr, Len->getZExtValue());
  return AccessRange;
}

/// The function analyzes all local uses of Ptr (alloca or argument) and
/// calculates local access range and all function calls where it was used.
bool StackSafetyLocalAnalysis::analyzeAllUses(const Value *Ptr, UseInfo &US) {
  SmallPtrSet<const Value *, 16> Visited;
  SmallVector<const Value *, 8> WorkList;
  WorkList.push_back(Ptr);

  // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc.
  while (!WorkList.empty()) {
    const Value *V = WorkList.pop_back_val();
    for (const Use &UI : V->uses()) {
      auto I = cast<const Instruction>(UI.getUser());
      assert(V == UI.get());

      switch (I->getOpcode()) {
      case Instruction::Load: {
        US.updateRange(
            getAccessRange(UI, Ptr, DL.getTypeStoreSize(I->getType())));
        break;
      }

      case Instruction::VAArg:
        // "va-arg" from a pointer is safe.
        break;
      case Instruction::Store: {
        if (V == I->getOperand(0)) {
          // Stored the pointer - conservatively assume it may be unsafe.
          US.updateRange(UnknownRange);
          return false;
        }
        US.updateRange(getAccessRange(
            UI, Ptr, DL.getTypeStoreSize(I->getOperand(0)->getType())));
        break;
      }

      case Instruction::Ret:
        // Information leak.
        // FIXME: Process parameters correctly. This is a leak only if we return
        // alloca.
        US.updateRange(UnknownRange);
        return false;

      case Instruction::Call:
      case Instruction::Invoke: {
        ImmutableCallSite CS(I);

        if (I->isLifetimeStartOrEnd())
          break;

        if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) {
          US.updateRange(getMemIntrinsicAccessRange(MI, UI, Ptr));
          break;
        }

        // FIXME: consult devirt?
        // Do not follow aliases, otherwise we could inadvertently follow
        // dso_preemptable aliases or aliases with interposable linkage.
        const GlobalValue *Callee =
            dyn_cast<GlobalValue>(CS.getCalledValue()->stripPointerCasts());
        if (!Callee) {
          US.updateRange(UnknownRange);
          return false;
        }

        assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee));

        ImmutableCallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
        for (ImmutableCallSite::arg_iterator A = B; A != E; ++A) {
          if (A->get() == V) {
            ConstantRange Offset = offsetFromAlloca(UI, Ptr);
            US.Calls.emplace_back(Callee, A - B, Offset);
          }
        }

        break;
      }

      default:
        if (Visited.insert(I).second)
          WorkList.push_back(cast<const Instruction>(I));
      }
    }
  }

  return true;
}

StackSafetyInfo StackSafetyLocalAnalysis::run() {
  StackSafetyInfo::FunctionInfo Info(&F);
  assert(!F.isDeclaration() &&
         "Can't run StackSafety on a function declaration");

  LLVM_DEBUG(dbgs() << "[StackSafety] " << F.getName() << "\n");

  for (auto &I : instructions(F)) {
    if (auto AI = dyn_cast<AllocaInst>(&I)) {
      Info.Allocas.emplace_back(PointerSize, AI,
                                getStaticAllocaAllocationSize(AI));
      AllocaInfo &AS = Info.Allocas.back();
      analyzeAllUses(AI, AS.Use);
    }
  }

  for (const Argument &A : make_range(F.arg_begin(), F.arg_end())) {
    Info.Params.emplace_back(PointerSize, &A);
    ParamInfo &PS = Info.Params.back();
    analyzeAllUses(&A, PS.Use);
  }

  LLVM_DEBUG(dbgs() << "[StackSafety] done\n");
  LLVM_DEBUG(Info.print(dbgs()));
  return StackSafetyInfo(std::move(Info));
}

class StackSafetyDataFlowAnalysis {
  using FunctionMap =
      std::map<const GlobalValue *, StackSafetyInfo::FunctionInfo>;

  FunctionMap Functions;
  // Callee-to-Caller multimap.
  DenseMap<const GlobalValue *, SmallVector<const GlobalValue *, 4>> Callers;
  SetVector<const GlobalValue *> WorkList;

  unsigned PointerSize = 0;
  const ConstantRange UnknownRange;

  ConstantRange getArgumentAccessRange(const GlobalValue *Callee,
                                       unsigned ParamNo) const;
  bool updateOneUse(UseInfo &US, bool UpdateToFullSet);
  void updateOneNode(const GlobalValue *Callee,
                     StackSafetyInfo::FunctionInfo &FS);
  void updateOneNode(const GlobalValue *Callee) {
    updateOneNode(Callee, Functions.find(Callee)->second);
  }
  void updateAllNodes() {
    for (auto &F : Functions)
      updateOneNode(F.first, F.second);
  }
  void runDataFlow();
#ifndef NDEBUG
  void verifyFixedPoint();
#endif

public:
  StackSafetyDataFlowAnalysis(
      Module &M, std::function<const StackSafetyInfo &(Function &)> FI);
  StackSafetyGlobalInfo run();
};

StackSafetyDataFlowAnalysis::StackSafetyDataFlowAnalysis(
    Module &M, std::function<const StackSafetyInfo &(Function &)> FI)
    : PointerSize(M.getDataLayout().getPointerSizeInBits()),
      UnknownRange(PointerSize, true) {
  // Without ThinLTO, run the local analysis for every function in the TU and
  // then run the DFA.
  for (auto &F : M.functions())
    if (!F.isDeclaration())
      Functions.emplace(&F, FI(F));
  for (auto &A : M.aliases())
    if (isa<Function>(A.getBaseObject()))
      Functions.emplace(&A, StackSafetyInfo::FunctionInfo(&A));
}

ConstantRange
StackSafetyDataFlowAnalysis::getArgumentAccessRange(const GlobalValue *Callee,
                                                    unsigned ParamNo) const {
  auto IT = Functions.find(Callee);
  // Unknown callee (outside of LTO domain or an indirect call).
  if (IT == Functions.end())
    return UnknownRange;
  const StackSafetyInfo::FunctionInfo &FS = IT->second;
  // The definition of this symbol may not be the definition in this linkage
  // unit.
  if (!FS.IsDSOLocal() || FS.IsInterposable())
    return UnknownRange;
  if (ParamNo >= FS.Params.size()) // possibly vararg
    return UnknownRange;
  return FS.Params[ParamNo].Use.Range;
}

bool StackSafetyDataFlowAnalysis::updateOneUse(UseInfo &US,
                                               bool UpdateToFullSet) {
  bool Changed = false;
  for (auto &CS : US.Calls) {
    assert(!CS.Offset.isEmptySet() &&
           "Param range can't be empty-set, invalid offset range");

    ConstantRange CalleeRange = getArgumentAccessRange(CS.Callee, CS.ParamNo);
    CalleeRange = CalleeRange.add(CS.Offset);
    if (!US.Range.contains(CalleeRange)) {
      Changed = true;
      if (UpdateToFullSet)
        US.Range = UnknownRange;
      else
        US.Range = US.Range.unionWith(CalleeRange);
    }
  }
  return Changed;
}

void StackSafetyDataFlowAnalysis::updateOneNode(
    const GlobalValue *Callee, StackSafetyInfo::FunctionInfo &FS) {
  bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations;
  bool Changed = false;
  for (auto &AS : FS.Allocas)
    Changed |= updateOneUse(AS.Use, UpdateToFullSet);
  for (auto &PS : FS.Params)
    Changed |= updateOneUse(PS.Use, UpdateToFullSet);

  if (Changed) {
    LLVM_DEBUG(dbgs() << "=== update [" << FS.UpdateCount
                      << (UpdateToFullSet ? ", full-set" : "") << "] "
                      << FS.getName() << "\n");
    // Callers of this function may need updating.
    for (auto &CallerID : Callers[Callee])
      WorkList.insert(CallerID);

    ++FS.UpdateCount;
  }
}

void StackSafetyDataFlowAnalysis::runDataFlow() {
  Callers.clear();
  WorkList.clear();

  SmallVector<const GlobalValue *, 16> Callees;
  for (auto &F : Functions) {
    Callees.clear();
    StackSafetyInfo::FunctionInfo &FS = F.second;
    for (auto &AS : FS.Allocas)
      for (auto &CS : AS.Use.Calls)
        Callees.push_back(CS.Callee);
    for (auto &PS : FS.Params)
      for (auto &CS : PS.Use.Calls)
        Callees.push_back(CS.Callee);

    llvm::sort(Callees);
    Callees.erase(std::unique(Callees.begin(), Callees.end()), Callees.end());

    for (auto &Callee : Callees)
      Callers[Callee].push_back(F.first);
  }

  updateAllNodes();

  while (!WorkList.empty()) {
    const GlobalValue *Callee = WorkList.back();
    WorkList.pop_back();
    updateOneNode(Callee);
  }
}

#ifndef NDEBUG
void StackSafetyDataFlowAnalysis::verifyFixedPoint() {
  WorkList.clear();
  updateAllNodes();
  assert(WorkList.empty());
}
#endif

StackSafetyGlobalInfo StackSafetyDataFlowAnalysis::run() {
  runDataFlow();
  LLVM_DEBUG(verifyFixedPoint());

  StackSafetyGlobalInfo SSI;
  for (auto &F : Functions)
    SSI.emplace(F.first, std::move(F.second));
  return SSI;
}

void print(const StackSafetyGlobalInfo &SSI, raw_ostream &O, const Module &M) {
  size_t Count = 0;
  for (auto &F : M.functions())
    if (!F.isDeclaration()) {
      SSI.find(&F)->second.print(O);
      O << "\n";
      ++Count;
    }
  for (auto &A : M.aliases()) {
    SSI.find(&A)->second.print(O);
    O << "\n";
    ++Count;
  }
  assert(Count == SSI.size() && "Unexpected functions in the result");
}

} // end anonymous namespace

StackSafetyInfo::StackSafetyInfo() = default;
StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default;
StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default;

StackSafetyInfo::StackSafetyInfo(FunctionInfo &&Info)
    : Info(new FunctionInfo(std::move(Info))) {}

StackSafetyInfo::~StackSafetyInfo() = default;

void StackSafetyInfo::print(raw_ostream &O) const { Info->print(O); }

AnalysisKey StackSafetyAnalysis::Key;

StackSafetyInfo StackSafetyAnalysis::run(Function &F,
                                         FunctionAnalysisManager &AM) {
  StackSafetyLocalAnalysis SSLA(F, AM.getResult<ScalarEvolutionAnalysis>(F));
  return SSLA.run();
}

PreservedAnalyses StackSafetyPrinterPass::run(Function &F,
                                              FunctionAnalysisManager &AM) {
  OS << "'Stack Safety Local Analysis' for function '" << F.getName() << "'\n";
  AM.getResult<StackSafetyAnalysis>(F).print(OS);
  return PreservedAnalyses::all();
}

char StackSafetyInfoWrapperPass::ID = 0;

StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) {
  initializeStackSafetyInfoWrapperPassPass(*PassRegistry::getPassRegistry());
}

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

void StackSafetyInfoWrapperPass::print(raw_ostream &O, const Module *M) const {
  SSI.print(O);
}

bool StackSafetyInfoWrapperPass::runOnFunction(Function &F) {
  StackSafetyLocalAnalysis SSLA(
      F, getAnalysis<ScalarEvolutionWrapperPass>().getSE());
  SSI = StackSafetyInfo(SSLA.run());
  return false;
}

AnalysisKey StackSafetyGlobalAnalysis::Key;

StackSafetyGlobalInfo
StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
  FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();

  StackSafetyDataFlowAnalysis SSDFA(
      M, [&FAM](Function &F) -> const StackSafetyInfo & {
        return FAM.getResult<StackSafetyAnalysis>(F);
      });
  return SSDFA.run();
}

PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M,
                                                    ModuleAnalysisManager &AM) {
  OS << "'Stack Safety Analysis' for module '" << M.getName() << "'\n";
  print(AM.getResult<StackSafetyGlobalAnalysis>(M), OS, M);
  return PreservedAnalyses::all();
}

char StackSafetyGlobalInfoWrapperPass::ID = 0;

StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass()
    : ModulePass(ID) {
  initializeStackSafetyGlobalInfoWrapperPassPass(
      *PassRegistry::getPassRegistry());
}

void StackSafetyGlobalInfoWrapperPass::print(raw_ostream &O,
                                             const Module *M) const {
  ::print(SSI, O, *M);
}

void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage(
    AnalysisUsage &AU) const {
  AU.addRequired<StackSafetyInfoWrapperPass>();
}

bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) {
  StackSafetyDataFlowAnalysis SSDFA(
      M, [this](Function &F) -> const StackSafetyInfo & {
        return getAnalysis<StackSafetyInfoWrapperPass>(F).getResult();
      });
  SSI = SSDFA.run();
  return false;
}

static const char LocalPassArg[] = "stack-safety-local";
static const char LocalPassName[] = "Stack Safety Local Analysis";
INITIALIZE_PASS_BEGIN(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName,
                      false, true)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
INITIALIZE_PASS_END(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName,
                    false, true)

static const char GlobalPassName[] = "Stack Safety Analysis";
INITIALIZE_PASS_BEGIN(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE,
                      GlobalPassName, false, false)
INITIALIZE_PASS_DEPENDENCY(StackSafetyInfoWrapperPass)
INITIALIZE_PASS_END(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE,
                    GlobalPassName, false, false)
