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