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