1*0b57cec5SDimitry Andric //===- StackSafetyAnalysis.cpp - Stack memory safety analysis -------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #include "llvm/Analysis/StackSafetyAnalysis.h" 12*0b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionExpressions.h" 13*0b57cec5SDimitry Andric #include "llvm/IR/CallSite.h" 14*0b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 15*0b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 16480093f4SDimitry Andric #include "llvm/InitializePasses.h" 17480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 18*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric using namespace llvm; 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric #define DEBUG_TYPE "stack-safety" 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations", 25*0b57cec5SDimitry Andric cl::init(20), cl::Hidden); 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric namespace { 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric /// Rewrite an SCEV expression for a memory access address to an expression that 30*0b57cec5SDimitry Andric /// represents offset from the given alloca. 31*0b57cec5SDimitry Andric class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> { 32*0b57cec5SDimitry Andric const Value *AllocaPtr; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric public: 35*0b57cec5SDimitry Andric AllocaOffsetRewriter(ScalarEvolution &SE, const Value *AllocaPtr) 36*0b57cec5SDimitry Andric : SCEVRewriteVisitor(SE), AllocaPtr(AllocaPtr) {} 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric const SCEV *visit(const SCEV *Expr) { 39*0b57cec5SDimitry Andric // Only re-write the expression if the alloca is used in an addition 40*0b57cec5SDimitry Andric // expression (it can be used in other types of expressions if it's cast to 41*0b57cec5SDimitry Andric // an int and passed as an argument.) 42*0b57cec5SDimitry Andric if (!isa<SCEVAddRecExpr>(Expr) && !isa<SCEVAddExpr>(Expr) && 43*0b57cec5SDimitry Andric !isa<SCEVUnknown>(Expr)) 44*0b57cec5SDimitry Andric return Expr; 45*0b57cec5SDimitry Andric return SCEVRewriteVisitor<AllocaOffsetRewriter>::visit(Expr); 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric const SCEV *visitUnknown(const SCEVUnknown *Expr) { 49*0b57cec5SDimitry Andric // FIXME: look through one or several levels of definitions? 50*0b57cec5SDimitry Andric // This can be inttoptr(AllocaPtr) and SCEV would not unwrap 51*0b57cec5SDimitry Andric // it for us. 52*0b57cec5SDimitry Andric if (Expr->getValue() == AllocaPtr) 53*0b57cec5SDimitry Andric return SE.getZero(Expr->getType()); 54*0b57cec5SDimitry Andric return Expr; 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric }; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric /// Describes use of address in as a function call argument. 59*0b57cec5SDimitry Andric struct PassAsArgInfo { 60*0b57cec5SDimitry Andric /// Function being called. 61*0b57cec5SDimitry Andric const GlobalValue *Callee = nullptr; 62*0b57cec5SDimitry Andric /// Index of argument which pass address. 63*0b57cec5SDimitry Andric size_t ParamNo = 0; 64*0b57cec5SDimitry Andric // Offset range of address from base address (alloca or calling function 65*0b57cec5SDimitry Andric // argument). 66*0b57cec5SDimitry Andric // Range should never set to empty-set, that is an invalid access range 67*0b57cec5SDimitry Andric // that can cause empty-set to be propagated with ConstantRange::add 68*0b57cec5SDimitry Andric ConstantRange Offset; 69*0b57cec5SDimitry Andric PassAsArgInfo(const GlobalValue *Callee, size_t ParamNo, ConstantRange Offset) 70*0b57cec5SDimitry Andric : Callee(Callee), ParamNo(ParamNo), Offset(Offset) {} 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric StringRef getName() const { return Callee->getName(); } 73*0b57cec5SDimitry Andric }; 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const PassAsArgInfo &P) { 76*0b57cec5SDimitry Andric return OS << "@" << P.getName() << "(arg" << P.ParamNo << ", " << P.Offset 77*0b57cec5SDimitry Andric << ")"; 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric /// Describe uses of address (alloca or parameter) inside of the function. 81*0b57cec5SDimitry Andric struct UseInfo { 82*0b57cec5SDimitry Andric // Access range if the address (alloca or parameters). 83*0b57cec5SDimitry Andric // It is allowed to be empty-set when there are no known accesses. 84*0b57cec5SDimitry Andric ConstantRange Range; 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric // List of calls which pass address as an argument. 87*0b57cec5SDimitry Andric SmallVector<PassAsArgInfo, 4> Calls; 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric explicit UseInfo(unsigned PointerSize) : Range{PointerSize, false} {} 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric void updateRange(ConstantRange R) { Range = Range.unionWith(R); } 92*0b57cec5SDimitry Andric }; 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const UseInfo &U) { 95*0b57cec5SDimitry Andric OS << U.Range; 96*0b57cec5SDimitry Andric for (auto &Call : U.Calls) 97*0b57cec5SDimitry Andric OS << ", " << Call; 98*0b57cec5SDimitry Andric return OS; 99*0b57cec5SDimitry Andric } 100*0b57cec5SDimitry Andric 101*0b57cec5SDimitry Andric struct AllocaInfo { 102*0b57cec5SDimitry Andric const AllocaInst *AI = nullptr; 103*0b57cec5SDimitry Andric uint64_t Size = 0; 104*0b57cec5SDimitry Andric UseInfo Use; 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric AllocaInfo(unsigned PointerSize, const AllocaInst *AI, uint64_t Size) 107*0b57cec5SDimitry Andric : AI(AI), Size(Size), Use(PointerSize) {} 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric StringRef getName() const { return AI->getName(); } 110*0b57cec5SDimitry Andric }; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const AllocaInfo &A) { 113*0b57cec5SDimitry Andric return OS << A.getName() << "[" << A.Size << "]: " << A.Use; 114*0b57cec5SDimitry Andric } 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric struct ParamInfo { 117*0b57cec5SDimitry Andric const Argument *Arg = nullptr; 118*0b57cec5SDimitry Andric UseInfo Use; 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric explicit ParamInfo(unsigned PointerSize, const Argument *Arg) 121*0b57cec5SDimitry Andric : Arg(Arg), Use(PointerSize) {} 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric StringRef getName() const { return Arg ? Arg->getName() : "<N/A>"; } 124*0b57cec5SDimitry Andric }; 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const ParamInfo &P) { 127*0b57cec5SDimitry Andric return OS << P.getName() << "[]: " << P.Use; 128*0b57cec5SDimitry Andric } 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric /// Calculate the allocation size of a given alloca. Returns 0 if the 131*0b57cec5SDimitry Andric /// size can not be statically determined. 132*0b57cec5SDimitry Andric uint64_t getStaticAllocaAllocationSize(const AllocaInst *AI) { 133*0b57cec5SDimitry Andric const DataLayout &DL = AI->getModule()->getDataLayout(); 134*0b57cec5SDimitry Andric uint64_t Size = DL.getTypeAllocSize(AI->getAllocatedType()); 135*0b57cec5SDimitry Andric if (AI->isArrayAllocation()) { 136*0b57cec5SDimitry Andric auto C = dyn_cast<ConstantInt>(AI->getArraySize()); 137*0b57cec5SDimitry Andric if (!C) 138*0b57cec5SDimitry Andric return 0; 139*0b57cec5SDimitry Andric Size *= C->getZExtValue(); 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric return Size; 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric } // end anonymous namespace 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric /// Describes uses of allocas and parameters inside of a single function. 147*0b57cec5SDimitry Andric struct StackSafetyInfo::FunctionInfo { 148*0b57cec5SDimitry Andric // May be a Function or a GlobalAlias 149*0b57cec5SDimitry Andric const GlobalValue *GV = nullptr; 150*0b57cec5SDimitry Andric // Informations about allocas uses. 151*0b57cec5SDimitry Andric SmallVector<AllocaInfo, 4> Allocas; 152*0b57cec5SDimitry Andric // Informations about parameters uses. 153*0b57cec5SDimitry Andric SmallVector<ParamInfo, 4> Params; 154*0b57cec5SDimitry Andric // TODO: describe return value as depending on one or more of its arguments. 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric // StackSafetyDataFlowAnalysis counter stored here for faster access. 157*0b57cec5SDimitry Andric int UpdateCount = 0; 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric FunctionInfo(const StackSafetyInfo &SSI) : FunctionInfo(*SSI.Info) {} 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric explicit FunctionInfo(const Function *F) : GV(F){}; 162*0b57cec5SDimitry Andric // Creates FunctionInfo that forwards all the parameters to the aliasee. 163*0b57cec5SDimitry Andric explicit FunctionInfo(const GlobalAlias *A); 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric FunctionInfo(FunctionInfo &&) = default; 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric bool IsDSOLocal() const { return GV->isDSOLocal(); }; 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric bool IsInterposable() const { return GV->isInterposable(); }; 170*0b57cec5SDimitry Andric 171*0b57cec5SDimitry Andric StringRef getName() const { return GV->getName(); } 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric void print(raw_ostream &O) const { 174*0b57cec5SDimitry Andric // TODO: Consider different printout format after 175*0b57cec5SDimitry Andric // StackSafetyDataFlowAnalysis. Calls and parameters are irrelevant then. 176*0b57cec5SDimitry Andric O << " @" << getName() << (IsDSOLocal() ? "" : " dso_preemptable") 177*0b57cec5SDimitry Andric << (IsInterposable() ? " interposable" : "") << "\n"; 178*0b57cec5SDimitry Andric O << " args uses:\n"; 179*0b57cec5SDimitry Andric for (auto &P : Params) 180*0b57cec5SDimitry Andric O << " " << P << "\n"; 181*0b57cec5SDimitry Andric O << " allocas uses:\n"; 182*0b57cec5SDimitry Andric for (auto &AS : Allocas) 183*0b57cec5SDimitry Andric O << " " << AS << "\n"; 184*0b57cec5SDimitry Andric } 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric private: 187*0b57cec5SDimitry Andric FunctionInfo(const FunctionInfo &) = default; 188*0b57cec5SDimitry Andric }; 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric StackSafetyInfo::FunctionInfo::FunctionInfo(const GlobalAlias *A) : GV(A) { 191*0b57cec5SDimitry Andric unsigned PointerSize = A->getParent()->getDataLayout().getPointerSizeInBits(); 192*0b57cec5SDimitry Andric const GlobalObject *Aliasee = A->getBaseObject(); 193*0b57cec5SDimitry Andric const FunctionType *Type = cast<FunctionType>(Aliasee->getValueType()); 194*0b57cec5SDimitry Andric // 'Forward' all parameters to this alias to the aliasee 195*0b57cec5SDimitry Andric for (unsigned ArgNo = 0; ArgNo < Type->getNumParams(); ArgNo++) { 196*0b57cec5SDimitry Andric Params.emplace_back(PointerSize, nullptr); 197*0b57cec5SDimitry Andric UseInfo &US = Params.back().Use; 198*0b57cec5SDimitry Andric US.Calls.emplace_back(Aliasee, ArgNo, ConstantRange(APInt(PointerSize, 0))); 199*0b57cec5SDimitry Andric } 200*0b57cec5SDimitry Andric } 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric namespace { 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric class StackSafetyLocalAnalysis { 205*0b57cec5SDimitry Andric const Function &F; 206*0b57cec5SDimitry Andric const DataLayout &DL; 207*0b57cec5SDimitry Andric ScalarEvolution &SE; 208*0b57cec5SDimitry Andric unsigned PointerSize = 0; 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric const ConstantRange UnknownRange; 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric ConstantRange offsetFromAlloca(Value *Addr, const Value *AllocaPtr); 213*0b57cec5SDimitry Andric ConstantRange getAccessRange(Value *Addr, const Value *AllocaPtr, 214*0b57cec5SDimitry Andric uint64_t AccessSize); 215*0b57cec5SDimitry Andric ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U, 216*0b57cec5SDimitry Andric const Value *AllocaPtr); 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric bool analyzeAllUses(const Value *Ptr, UseInfo &AS); 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric ConstantRange getRange(uint64_t Lower, uint64_t Upper) const { 221*0b57cec5SDimitry Andric return ConstantRange(APInt(PointerSize, Lower), APInt(PointerSize, Upper)); 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric public: 225*0b57cec5SDimitry Andric StackSafetyLocalAnalysis(const Function &F, ScalarEvolution &SE) 226*0b57cec5SDimitry Andric : F(F), DL(F.getParent()->getDataLayout()), SE(SE), 227*0b57cec5SDimitry Andric PointerSize(DL.getPointerSizeInBits()), 228*0b57cec5SDimitry Andric UnknownRange(PointerSize, true) {} 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric // Run the transformation on the associated function. 231*0b57cec5SDimitry Andric StackSafetyInfo run(); 232*0b57cec5SDimitry Andric }; 233*0b57cec5SDimitry Andric 234*0b57cec5SDimitry Andric ConstantRange 235*0b57cec5SDimitry Andric StackSafetyLocalAnalysis::offsetFromAlloca(Value *Addr, 236*0b57cec5SDimitry Andric const Value *AllocaPtr) { 237*0b57cec5SDimitry Andric if (!SE.isSCEVable(Addr->getType())) 238*0b57cec5SDimitry Andric return UnknownRange; 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric AllocaOffsetRewriter Rewriter(SE, AllocaPtr); 241*0b57cec5SDimitry Andric const SCEV *Expr = Rewriter.visit(SE.getSCEV(Addr)); 242*0b57cec5SDimitry Andric ConstantRange Offset = SE.getUnsignedRange(Expr).zextOrTrunc(PointerSize); 243*0b57cec5SDimitry Andric assert(!Offset.isEmptySet()); 244*0b57cec5SDimitry Andric return Offset; 245*0b57cec5SDimitry Andric } 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric ConstantRange StackSafetyLocalAnalysis::getAccessRange(Value *Addr, 248*0b57cec5SDimitry Andric const Value *AllocaPtr, 249*0b57cec5SDimitry Andric uint64_t AccessSize) { 250*0b57cec5SDimitry Andric if (!SE.isSCEVable(Addr->getType())) 251*0b57cec5SDimitry Andric return UnknownRange; 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric AllocaOffsetRewriter Rewriter(SE, AllocaPtr); 254*0b57cec5SDimitry Andric const SCEV *Expr = Rewriter.visit(SE.getSCEV(Addr)); 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric ConstantRange AccessStartRange = 257*0b57cec5SDimitry Andric SE.getUnsignedRange(Expr).zextOrTrunc(PointerSize); 258*0b57cec5SDimitry Andric ConstantRange SizeRange = getRange(0, AccessSize); 259*0b57cec5SDimitry Andric ConstantRange AccessRange = AccessStartRange.add(SizeRange); 260*0b57cec5SDimitry Andric assert(!AccessRange.isEmptySet()); 261*0b57cec5SDimitry Andric return AccessRange; 262*0b57cec5SDimitry Andric } 263*0b57cec5SDimitry Andric 264*0b57cec5SDimitry Andric ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange( 265*0b57cec5SDimitry Andric const MemIntrinsic *MI, const Use &U, const Value *AllocaPtr) { 266*0b57cec5SDimitry Andric if (auto MTI = dyn_cast<MemTransferInst>(MI)) { 267*0b57cec5SDimitry Andric if (MTI->getRawSource() != U && MTI->getRawDest() != U) 268*0b57cec5SDimitry Andric return getRange(0, 1); 269*0b57cec5SDimitry Andric } else { 270*0b57cec5SDimitry Andric if (MI->getRawDest() != U) 271*0b57cec5SDimitry Andric return getRange(0, 1); 272*0b57cec5SDimitry Andric } 273*0b57cec5SDimitry Andric const auto *Len = dyn_cast<ConstantInt>(MI->getLength()); 274*0b57cec5SDimitry Andric // Non-constant size => unsafe. FIXME: try SCEV getRange. 275*0b57cec5SDimitry Andric if (!Len) 276*0b57cec5SDimitry Andric return UnknownRange; 277*0b57cec5SDimitry Andric ConstantRange AccessRange = getAccessRange(U, AllocaPtr, Len->getZExtValue()); 278*0b57cec5SDimitry Andric return AccessRange; 279*0b57cec5SDimitry Andric } 280*0b57cec5SDimitry Andric 281*0b57cec5SDimitry Andric /// The function analyzes all local uses of Ptr (alloca or argument) and 282*0b57cec5SDimitry Andric /// calculates local access range and all function calls where it was used. 283*0b57cec5SDimitry Andric bool StackSafetyLocalAnalysis::analyzeAllUses(const Value *Ptr, UseInfo &US) { 284*0b57cec5SDimitry Andric SmallPtrSet<const Value *, 16> Visited; 285*0b57cec5SDimitry Andric SmallVector<const Value *, 8> WorkList; 286*0b57cec5SDimitry Andric WorkList.push_back(Ptr); 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. 289*0b57cec5SDimitry Andric while (!WorkList.empty()) { 290*0b57cec5SDimitry Andric const Value *V = WorkList.pop_back_val(); 291*0b57cec5SDimitry Andric for (const Use &UI : V->uses()) { 292*0b57cec5SDimitry Andric auto I = cast<const Instruction>(UI.getUser()); 293*0b57cec5SDimitry Andric assert(V == UI.get()); 294*0b57cec5SDimitry Andric 295*0b57cec5SDimitry Andric switch (I->getOpcode()) { 296*0b57cec5SDimitry Andric case Instruction::Load: { 297*0b57cec5SDimitry Andric US.updateRange( 298*0b57cec5SDimitry Andric getAccessRange(UI, Ptr, DL.getTypeStoreSize(I->getType()))); 299*0b57cec5SDimitry Andric break; 300*0b57cec5SDimitry Andric } 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andric case Instruction::VAArg: 303*0b57cec5SDimitry Andric // "va-arg" from a pointer is safe. 304*0b57cec5SDimitry Andric break; 305*0b57cec5SDimitry Andric case Instruction::Store: { 306*0b57cec5SDimitry Andric if (V == I->getOperand(0)) { 307*0b57cec5SDimitry Andric // Stored the pointer - conservatively assume it may be unsafe. 308*0b57cec5SDimitry Andric US.updateRange(UnknownRange); 309*0b57cec5SDimitry Andric return false; 310*0b57cec5SDimitry Andric } 311*0b57cec5SDimitry Andric US.updateRange(getAccessRange( 312*0b57cec5SDimitry Andric UI, Ptr, DL.getTypeStoreSize(I->getOperand(0)->getType()))); 313*0b57cec5SDimitry Andric break; 314*0b57cec5SDimitry Andric } 315*0b57cec5SDimitry Andric 316*0b57cec5SDimitry Andric case Instruction::Ret: 317*0b57cec5SDimitry Andric // Information leak. 318*0b57cec5SDimitry Andric // FIXME: Process parameters correctly. This is a leak only if we return 319*0b57cec5SDimitry Andric // alloca. 320*0b57cec5SDimitry Andric US.updateRange(UnknownRange); 321*0b57cec5SDimitry Andric return false; 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric case Instruction::Call: 324*0b57cec5SDimitry Andric case Instruction::Invoke: { 325*0b57cec5SDimitry Andric ImmutableCallSite CS(I); 326*0b57cec5SDimitry Andric 327*0b57cec5SDimitry Andric if (I->isLifetimeStartOrEnd()) 328*0b57cec5SDimitry Andric break; 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { 331*0b57cec5SDimitry Andric US.updateRange(getMemIntrinsicAccessRange(MI, UI, Ptr)); 332*0b57cec5SDimitry Andric break; 333*0b57cec5SDimitry Andric } 334*0b57cec5SDimitry Andric 335*0b57cec5SDimitry Andric // FIXME: consult devirt? 336*0b57cec5SDimitry Andric // Do not follow aliases, otherwise we could inadvertently follow 337*0b57cec5SDimitry Andric // dso_preemptable aliases or aliases with interposable linkage. 3388bcb0991SDimitry Andric const GlobalValue *Callee = 3398bcb0991SDimitry Andric dyn_cast<GlobalValue>(CS.getCalledValue()->stripPointerCasts()); 340*0b57cec5SDimitry Andric if (!Callee) { 341*0b57cec5SDimitry Andric US.updateRange(UnknownRange); 342*0b57cec5SDimitry Andric return false; 343*0b57cec5SDimitry Andric } 344*0b57cec5SDimitry Andric 345*0b57cec5SDimitry Andric assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee)); 346*0b57cec5SDimitry Andric 347*0b57cec5SDimitry Andric ImmutableCallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end(); 348*0b57cec5SDimitry Andric for (ImmutableCallSite::arg_iterator A = B; A != E; ++A) { 349*0b57cec5SDimitry Andric if (A->get() == V) { 350*0b57cec5SDimitry Andric ConstantRange Offset = offsetFromAlloca(UI, Ptr); 351*0b57cec5SDimitry Andric US.Calls.emplace_back(Callee, A - B, Offset); 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric } 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric break; 356*0b57cec5SDimitry Andric } 357*0b57cec5SDimitry Andric 358*0b57cec5SDimitry Andric default: 359*0b57cec5SDimitry Andric if (Visited.insert(I).second) 360*0b57cec5SDimitry Andric WorkList.push_back(cast<const Instruction>(I)); 361*0b57cec5SDimitry Andric } 362*0b57cec5SDimitry Andric } 363*0b57cec5SDimitry Andric } 364*0b57cec5SDimitry Andric 365*0b57cec5SDimitry Andric return true; 366*0b57cec5SDimitry Andric } 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric StackSafetyInfo StackSafetyLocalAnalysis::run() { 369*0b57cec5SDimitry Andric StackSafetyInfo::FunctionInfo Info(&F); 370*0b57cec5SDimitry Andric assert(!F.isDeclaration() && 371*0b57cec5SDimitry Andric "Can't run StackSafety on a function declaration"); 372*0b57cec5SDimitry Andric 373*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[StackSafety] " << F.getName() << "\n"); 374*0b57cec5SDimitry Andric 375*0b57cec5SDimitry Andric for (auto &I : instructions(F)) { 376*0b57cec5SDimitry Andric if (auto AI = dyn_cast<AllocaInst>(&I)) { 377*0b57cec5SDimitry Andric Info.Allocas.emplace_back(PointerSize, AI, 378*0b57cec5SDimitry Andric getStaticAllocaAllocationSize(AI)); 379*0b57cec5SDimitry Andric AllocaInfo &AS = Info.Allocas.back(); 380*0b57cec5SDimitry Andric analyzeAllUses(AI, AS.Use); 381*0b57cec5SDimitry Andric } 382*0b57cec5SDimitry Andric } 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric for (const Argument &A : make_range(F.arg_begin(), F.arg_end())) { 385*0b57cec5SDimitry Andric Info.Params.emplace_back(PointerSize, &A); 386*0b57cec5SDimitry Andric ParamInfo &PS = Info.Params.back(); 387*0b57cec5SDimitry Andric analyzeAllUses(&A, PS.Use); 388*0b57cec5SDimitry Andric } 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "[StackSafety] done\n"); 391*0b57cec5SDimitry Andric LLVM_DEBUG(Info.print(dbgs())); 392*0b57cec5SDimitry Andric return StackSafetyInfo(std::move(Info)); 393*0b57cec5SDimitry Andric } 394*0b57cec5SDimitry Andric 395*0b57cec5SDimitry Andric class StackSafetyDataFlowAnalysis { 396*0b57cec5SDimitry Andric using FunctionMap = 397*0b57cec5SDimitry Andric std::map<const GlobalValue *, StackSafetyInfo::FunctionInfo>; 398*0b57cec5SDimitry Andric 399*0b57cec5SDimitry Andric FunctionMap Functions; 400*0b57cec5SDimitry Andric // Callee-to-Caller multimap. 401*0b57cec5SDimitry Andric DenseMap<const GlobalValue *, SmallVector<const GlobalValue *, 4>> Callers; 402*0b57cec5SDimitry Andric SetVector<const GlobalValue *> WorkList; 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric unsigned PointerSize = 0; 405*0b57cec5SDimitry Andric const ConstantRange UnknownRange; 406*0b57cec5SDimitry Andric 407*0b57cec5SDimitry Andric ConstantRange getArgumentAccessRange(const GlobalValue *Callee, 408*0b57cec5SDimitry Andric unsigned ParamNo) const; 409*0b57cec5SDimitry Andric bool updateOneUse(UseInfo &US, bool UpdateToFullSet); 410*0b57cec5SDimitry Andric void updateOneNode(const GlobalValue *Callee, 411*0b57cec5SDimitry Andric StackSafetyInfo::FunctionInfo &FS); 412*0b57cec5SDimitry Andric void updateOneNode(const GlobalValue *Callee) { 413*0b57cec5SDimitry Andric updateOneNode(Callee, Functions.find(Callee)->second); 414*0b57cec5SDimitry Andric } 415*0b57cec5SDimitry Andric void updateAllNodes() { 416*0b57cec5SDimitry Andric for (auto &F : Functions) 417*0b57cec5SDimitry Andric updateOneNode(F.first, F.second); 418*0b57cec5SDimitry Andric } 419*0b57cec5SDimitry Andric void runDataFlow(); 420*0b57cec5SDimitry Andric #ifndef NDEBUG 421*0b57cec5SDimitry Andric void verifyFixedPoint(); 422*0b57cec5SDimitry Andric #endif 423*0b57cec5SDimitry Andric 424*0b57cec5SDimitry Andric public: 425*0b57cec5SDimitry Andric StackSafetyDataFlowAnalysis( 426*0b57cec5SDimitry Andric Module &M, std::function<const StackSafetyInfo &(Function &)> FI); 427*0b57cec5SDimitry Andric StackSafetyGlobalInfo run(); 428*0b57cec5SDimitry Andric }; 429*0b57cec5SDimitry Andric 430*0b57cec5SDimitry Andric StackSafetyDataFlowAnalysis::StackSafetyDataFlowAnalysis( 431*0b57cec5SDimitry Andric Module &M, std::function<const StackSafetyInfo &(Function &)> FI) 432*0b57cec5SDimitry Andric : PointerSize(M.getDataLayout().getPointerSizeInBits()), 433*0b57cec5SDimitry Andric UnknownRange(PointerSize, true) { 434*0b57cec5SDimitry Andric // Without ThinLTO, run the local analysis for every function in the TU and 435*0b57cec5SDimitry Andric // then run the DFA. 436*0b57cec5SDimitry Andric for (auto &F : M.functions()) 437*0b57cec5SDimitry Andric if (!F.isDeclaration()) 438*0b57cec5SDimitry Andric Functions.emplace(&F, FI(F)); 439*0b57cec5SDimitry Andric for (auto &A : M.aliases()) 440*0b57cec5SDimitry Andric if (isa<Function>(A.getBaseObject())) 441*0b57cec5SDimitry Andric Functions.emplace(&A, StackSafetyInfo::FunctionInfo(&A)); 442*0b57cec5SDimitry Andric } 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric ConstantRange 445*0b57cec5SDimitry Andric StackSafetyDataFlowAnalysis::getArgumentAccessRange(const GlobalValue *Callee, 446*0b57cec5SDimitry Andric unsigned ParamNo) const { 447*0b57cec5SDimitry Andric auto IT = Functions.find(Callee); 448*0b57cec5SDimitry Andric // Unknown callee (outside of LTO domain or an indirect call). 449*0b57cec5SDimitry Andric if (IT == Functions.end()) 450*0b57cec5SDimitry Andric return UnknownRange; 451*0b57cec5SDimitry Andric const StackSafetyInfo::FunctionInfo &FS = IT->second; 452*0b57cec5SDimitry Andric // The definition of this symbol may not be the definition in this linkage 453*0b57cec5SDimitry Andric // unit. 454*0b57cec5SDimitry Andric if (!FS.IsDSOLocal() || FS.IsInterposable()) 455*0b57cec5SDimitry Andric return UnknownRange; 456*0b57cec5SDimitry Andric if (ParamNo >= FS.Params.size()) // possibly vararg 457*0b57cec5SDimitry Andric return UnknownRange; 458*0b57cec5SDimitry Andric return FS.Params[ParamNo].Use.Range; 459*0b57cec5SDimitry Andric } 460*0b57cec5SDimitry Andric 461*0b57cec5SDimitry Andric bool StackSafetyDataFlowAnalysis::updateOneUse(UseInfo &US, 462*0b57cec5SDimitry Andric bool UpdateToFullSet) { 463*0b57cec5SDimitry Andric bool Changed = false; 464*0b57cec5SDimitry Andric for (auto &CS : US.Calls) { 465*0b57cec5SDimitry Andric assert(!CS.Offset.isEmptySet() && 466*0b57cec5SDimitry Andric "Param range can't be empty-set, invalid offset range"); 467*0b57cec5SDimitry Andric 468*0b57cec5SDimitry Andric ConstantRange CalleeRange = getArgumentAccessRange(CS.Callee, CS.ParamNo); 469*0b57cec5SDimitry Andric CalleeRange = CalleeRange.add(CS.Offset); 470*0b57cec5SDimitry Andric if (!US.Range.contains(CalleeRange)) { 471*0b57cec5SDimitry Andric Changed = true; 472*0b57cec5SDimitry Andric if (UpdateToFullSet) 473*0b57cec5SDimitry Andric US.Range = UnknownRange; 474*0b57cec5SDimitry Andric else 475*0b57cec5SDimitry Andric US.Range = US.Range.unionWith(CalleeRange); 476*0b57cec5SDimitry Andric } 477*0b57cec5SDimitry Andric } 478*0b57cec5SDimitry Andric return Changed; 479*0b57cec5SDimitry Andric } 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric void StackSafetyDataFlowAnalysis::updateOneNode( 482*0b57cec5SDimitry Andric const GlobalValue *Callee, StackSafetyInfo::FunctionInfo &FS) { 483*0b57cec5SDimitry Andric bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations; 484*0b57cec5SDimitry Andric bool Changed = false; 485*0b57cec5SDimitry Andric for (auto &AS : FS.Allocas) 486*0b57cec5SDimitry Andric Changed |= updateOneUse(AS.Use, UpdateToFullSet); 487*0b57cec5SDimitry Andric for (auto &PS : FS.Params) 488*0b57cec5SDimitry Andric Changed |= updateOneUse(PS.Use, UpdateToFullSet); 489*0b57cec5SDimitry Andric 490*0b57cec5SDimitry Andric if (Changed) { 491*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "=== update [" << FS.UpdateCount 492*0b57cec5SDimitry Andric << (UpdateToFullSet ? ", full-set" : "") << "] " 493*0b57cec5SDimitry Andric << FS.getName() << "\n"); 494*0b57cec5SDimitry Andric // Callers of this function may need updating. 495*0b57cec5SDimitry Andric for (auto &CallerID : Callers[Callee]) 496*0b57cec5SDimitry Andric WorkList.insert(CallerID); 497*0b57cec5SDimitry Andric 498*0b57cec5SDimitry Andric ++FS.UpdateCount; 499*0b57cec5SDimitry Andric } 500*0b57cec5SDimitry Andric } 501*0b57cec5SDimitry Andric 502*0b57cec5SDimitry Andric void StackSafetyDataFlowAnalysis::runDataFlow() { 503*0b57cec5SDimitry Andric Callers.clear(); 504*0b57cec5SDimitry Andric WorkList.clear(); 505*0b57cec5SDimitry Andric 506*0b57cec5SDimitry Andric SmallVector<const GlobalValue *, 16> Callees; 507*0b57cec5SDimitry Andric for (auto &F : Functions) { 508*0b57cec5SDimitry Andric Callees.clear(); 509*0b57cec5SDimitry Andric StackSafetyInfo::FunctionInfo &FS = F.second; 510*0b57cec5SDimitry Andric for (auto &AS : FS.Allocas) 511*0b57cec5SDimitry Andric for (auto &CS : AS.Use.Calls) 512*0b57cec5SDimitry Andric Callees.push_back(CS.Callee); 513*0b57cec5SDimitry Andric for (auto &PS : FS.Params) 514*0b57cec5SDimitry Andric for (auto &CS : PS.Use.Calls) 515*0b57cec5SDimitry Andric Callees.push_back(CS.Callee); 516*0b57cec5SDimitry Andric 517*0b57cec5SDimitry Andric llvm::sort(Callees); 518*0b57cec5SDimitry Andric Callees.erase(std::unique(Callees.begin(), Callees.end()), Callees.end()); 519*0b57cec5SDimitry Andric 520*0b57cec5SDimitry Andric for (auto &Callee : Callees) 521*0b57cec5SDimitry Andric Callers[Callee].push_back(F.first); 522*0b57cec5SDimitry Andric } 523*0b57cec5SDimitry Andric 524*0b57cec5SDimitry Andric updateAllNodes(); 525*0b57cec5SDimitry Andric 526*0b57cec5SDimitry Andric while (!WorkList.empty()) { 527*0b57cec5SDimitry Andric const GlobalValue *Callee = WorkList.back(); 528*0b57cec5SDimitry Andric WorkList.pop_back(); 529*0b57cec5SDimitry Andric updateOneNode(Callee); 530*0b57cec5SDimitry Andric } 531*0b57cec5SDimitry Andric } 532*0b57cec5SDimitry Andric 533*0b57cec5SDimitry Andric #ifndef NDEBUG 534*0b57cec5SDimitry Andric void StackSafetyDataFlowAnalysis::verifyFixedPoint() { 535*0b57cec5SDimitry Andric WorkList.clear(); 536*0b57cec5SDimitry Andric updateAllNodes(); 537*0b57cec5SDimitry Andric assert(WorkList.empty()); 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric #endif 540*0b57cec5SDimitry Andric 541*0b57cec5SDimitry Andric StackSafetyGlobalInfo StackSafetyDataFlowAnalysis::run() { 542*0b57cec5SDimitry Andric runDataFlow(); 543*0b57cec5SDimitry Andric LLVM_DEBUG(verifyFixedPoint()); 544*0b57cec5SDimitry Andric 545*0b57cec5SDimitry Andric StackSafetyGlobalInfo SSI; 546*0b57cec5SDimitry Andric for (auto &F : Functions) 547*0b57cec5SDimitry Andric SSI.emplace(F.first, std::move(F.second)); 548*0b57cec5SDimitry Andric return SSI; 549*0b57cec5SDimitry Andric } 550*0b57cec5SDimitry Andric 551*0b57cec5SDimitry Andric void print(const StackSafetyGlobalInfo &SSI, raw_ostream &O, const Module &M) { 552*0b57cec5SDimitry Andric size_t Count = 0; 553*0b57cec5SDimitry Andric for (auto &F : M.functions()) 554*0b57cec5SDimitry Andric if (!F.isDeclaration()) { 555*0b57cec5SDimitry Andric SSI.find(&F)->second.print(O); 556*0b57cec5SDimitry Andric O << "\n"; 557*0b57cec5SDimitry Andric ++Count; 558*0b57cec5SDimitry Andric } 559*0b57cec5SDimitry Andric for (auto &A : M.aliases()) { 560*0b57cec5SDimitry Andric SSI.find(&A)->second.print(O); 561*0b57cec5SDimitry Andric O << "\n"; 562*0b57cec5SDimitry Andric ++Count; 563*0b57cec5SDimitry Andric } 564*0b57cec5SDimitry Andric assert(Count == SSI.size() && "Unexpected functions in the result"); 565*0b57cec5SDimitry Andric } 566*0b57cec5SDimitry Andric 567*0b57cec5SDimitry Andric } // end anonymous namespace 568*0b57cec5SDimitry Andric 569*0b57cec5SDimitry Andric StackSafetyInfo::StackSafetyInfo() = default; 570*0b57cec5SDimitry Andric StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default; 571*0b57cec5SDimitry Andric StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default; 572*0b57cec5SDimitry Andric 573*0b57cec5SDimitry Andric StackSafetyInfo::StackSafetyInfo(FunctionInfo &&Info) 574*0b57cec5SDimitry Andric : Info(new FunctionInfo(std::move(Info))) {} 575*0b57cec5SDimitry Andric 576*0b57cec5SDimitry Andric StackSafetyInfo::~StackSafetyInfo() = default; 577*0b57cec5SDimitry Andric 578*0b57cec5SDimitry Andric void StackSafetyInfo::print(raw_ostream &O) const { Info->print(O); } 579*0b57cec5SDimitry Andric 580*0b57cec5SDimitry Andric AnalysisKey StackSafetyAnalysis::Key; 581*0b57cec5SDimitry Andric 582*0b57cec5SDimitry Andric StackSafetyInfo StackSafetyAnalysis::run(Function &F, 583*0b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 584*0b57cec5SDimitry Andric StackSafetyLocalAnalysis SSLA(F, AM.getResult<ScalarEvolutionAnalysis>(F)); 585*0b57cec5SDimitry Andric return SSLA.run(); 586*0b57cec5SDimitry Andric } 587*0b57cec5SDimitry Andric 588*0b57cec5SDimitry Andric PreservedAnalyses StackSafetyPrinterPass::run(Function &F, 589*0b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 590*0b57cec5SDimitry Andric OS << "'Stack Safety Local Analysis' for function '" << F.getName() << "'\n"; 591*0b57cec5SDimitry Andric AM.getResult<StackSafetyAnalysis>(F).print(OS); 592*0b57cec5SDimitry Andric return PreservedAnalyses::all(); 593*0b57cec5SDimitry Andric } 594*0b57cec5SDimitry Andric 595*0b57cec5SDimitry Andric char StackSafetyInfoWrapperPass::ID = 0; 596*0b57cec5SDimitry Andric 597*0b57cec5SDimitry Andric StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) { 598*0b57cec5SDimitry Andric initializeStackSafetyInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 599*0b57cec5SDimitry Andric } 600*0b57cec5SDimitry Andric 601*0b57cec5SDimitry Andric void StackSafetyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 602*0b57cec5SDimitry Andric AU.addRequired<ScalarEvolutionWrapperPass>(); 603*0b57cec5SDimitry Andric AU.setPreservesAll(); 604*0b57cec5SDimitry Andric } 605*0b57cec5SDimitry Andric 606*0b57cec5SDimitry Andric void StackSafetyInfoWrapperPass::print(raw_ostream &O, const Module *M) const { 607*0b57cec5SDimitry Andric SSI.print(O); 608*0b57cec5SDimitry Andric } 609*0b57cec5SDimitry Andric 610*0b57cec5SDimitry Andric bool StackSafetyInfoWrapperPass::runOnFunction(Function &F) { 611*0b57cec5SDimitry Andric StackSafetyLocalAnalysis SSLA( 612*0b57cec5SDimitry Andric F, getAnalysis<ScalarEvolutionWrapperPass>().getSE()); 613*0b57cec5SDimitry Andric SSI = StackSafetyInfo(SSLA.run()); 614*0b57cec5SDimitry Andric return false; 615*0b57cec5SDimitry Andric } 616*0b57cec5SDimitry Andric 617*0b57cec5SDimitry Andric AnalysisKey StackSafetyGlobalAnalysis::Key; 618*0b57cec5SDimitry Andric 619*0b57cec5SDimitry Andric StackSafetyGlobalInfo 620*0b57cec5SDimitry Andric StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) { 621*0b57cec5SDimitry Andric FunctionAnalysisManager &FAM = 622*0b57cec5SDimitry Andric AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 623*0b57cec5SDimitry Andric 624*0b57cec5SDimitry Andric StackSafetyDataFlowAnalysis SSDFA( 625*0b57cec5SDimitry Andric M, [&FAM](Function &F) -> const StackSafetyInfo & { 626*0b57cec5SDimitry Andric return FAM.getResult<StackSafetyAnalysis>(F); 627*0b57cec5SDimitry Andric }); 628*0b57cec5SDimitry Andric return SSDFA.run(); 629*0b57cec5SDimitry Andric } 630*0b57cec5SDimitry Andric 631*0b57cec5SDimitry Andric PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M, 632*0b57cec5SDimitry Andric ModuleAnalysisManager &AM) { 633*0b57cec5SDimitry Andric OS << "'Stack Safety Analysis' for module '" << M.getName() << "'\n"; 634*0b57cec5SDimitry Andric print(AM.getResult<StackSafetyGlobalAnalysis>(M), OS, M); 635*0b57cec5SDimitry Andric return PreservedAnalyses::all(); 636*0b57cec5SDimitry Andric } 637*0b57cec5SDimitry Andric 638*0b57cec5SDimitry Andric char StackSafetyGlobalInfoWrapperPass::ID = 0; 639*0b57cec5SDimitry Andric 640*0b57cec5SDimitry Andric StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass() 641*0b57cec5SDimitry Andric : ModulePass(ID) { 642*0b57cec5SDimitry Andric initializeStackSafetyGlobalInfoWrapperPassPass( 643*0b57cec5SDimitry Andric *PassRegistry::getPassRegistry()); 644*0b57cec5SDimitry Andric } 645*0b57cec5SDimitry Andric 646*0b57cec5SDimitry Andric void StackSafetyGlobalInfoWrapperPass::print(raw_ostream &O, 647*0b57cec5SDimitry Andric const Module *M) const { 648*0b57cec5SDimitry Andric ::print(SSI, O, *M); 649*0b57cec5SDimitry Andric } 650*0b57cec5SDimitry Andric 651*0b57cec5SDimitry Andric void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage( 652*0b57cec5SDimitry Andric AnalysisUsage &AU) const { 653*0b57cec5SDimitry Andric AU.addRequired<StackSafetyInfoWrapperPass>(); 654*0b57cec5SDimitry Andric } 655*0b57cec5SDimitry Andric 656*0b57cec5SDimitry Andric bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) { 657*0b57cec5SDimitry Andric StackSafetyDataFlowAnalysis SSDFA( 658*0b57cec5SDimitry Andric M, [this](Function &F) -> const StackSafetyInfo & { 659*0b57cec5SDimitry Andric return getAnalysis<StackSafetyInfoWrapperPass>(F).getResult(); 660*0b57cec5SDimitry Andric }); 661*0b57cec5SDimitry Andric SSI = SSDFA.run(); 662*0b57cec5SDimitry Andric return false; 663*0b57cec5SDimitry Andric } 664*0b57cec5SDimitry Andric 665*0b57cec5SDimitry Andric static const char LocalPassArg[] = "stack-safety-local"; 666*0b57cec5SDimitry Andric static const char LocalPassName[] = "Stack Safety Local Analysis"; 667*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName, 668*0b57cec5SDimitry Andric false, true) 669*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) 670*0b57cec5SDimitry Andric INITIALIZE_PASS_END(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName, 671*0b57cec5SDimitry Andric false, true) 672*0b57cec5SDimitry Andric 673*0b57cec5SDimitry Andric static const char GlobalPassName[] = "Stack Safety Analysis"; 674*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE, 675*0b57cec5SDimitry Andric GlobalPassName, false, false) 676*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(StackSafetyInfoWrapperPass) 677*0b57cec5SDimitry Andric INITIALIZE_PASS_END(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE, 678*0b57cec5SDimitry Andric GlobalPassName, false, false) 679