1 //===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===//
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 // Stack Safety Analysis detects allocas and arguments with safe access.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
14 #define LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
15 
16 #include "llvm/IR/ModuleSummaryIndex.h"
17 #include "llvm/IR/PassManager.h"
18 #include "llvm/Pass.h"
19 
20 namespace llvm {
21 
22 class AllocaInst;
23 class ScalarEvolution;
24 
25 /// Interface to access stack safety analysis results for single function.
26 class StackSafetyInfo {
27 public:
28   struct InfoTy;
29 
30 private:
31   Function *F = nullptr;
32   std::function<ScalarEvolution &()> GetSE;
33   mutable std::unique_ptr<InfoTy> Info;
34 
35 public:
36   StackSafetyInfo();
37   StackSafetyInfo(Function *F, std::function<ScalarEvolution &()> GetSE);
38   StackSafetyInfo(StackSafetyInfo &&);
39   StackSafetyInfo &operator=(StackSafetyInfo &&);
40   ~StackSafetyInfo();
41 
42   const InfoTy &getInfo() const;
43 
44   // TODO: Add useful for client methods.
45   void print(raw_ostream &O) const;
46 
47   /// Parameters use for a FunctionSummary.
48   /// Function collects access information of all pointer parameters.
49   /// Information includes a range of direct access of parameters by the
50   /// functions and all call sites accepting the parameter.
51   /// StackSafety assumes that missing parameter information means possibility
52   /// of access to the parameter with any offset, so we can correctly link
53   /// code without StackSafety information, e.g. non-ThinLTO.
54   std::vector<FunctionSummary::ParamAccess>
55   getParamAccesses(ModuleSummaryIndex &Index) const;
56 };
57 
58 class StackSafetyGlobalInfo {
59 public:
60   struct InfoTy;
61 
62 private:
63   Module *M = nullptr;
64   std::function<const StackSafetyInfo &(Function &F)> GetSSI;
65   const ModuleSummaryIndex *Index = nullptr;
66   mutable std::unique_ptr<InfoTy> Info;
67   const InfoTy &getInfo() const;
68 
69 public:
70   StackSafetyGlobalInfo();
71   StackSafetyGlobalInfo(
72       Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI,
73       const ModuleSummaryIndex *Index);
74   StackSafetyGlobalInfo(StackSafetyGlobalInfo &&);
75   StackSafetyGlobalInfo &operator=(StackSafetyGlobalInfo &&);
76   ~StackSafetyGlobalInfo();
77 
78   // Whether we can prove that all accesses to this Alloca are in-range and
79   // during its lifetime.
80   bool isSafe(const AllocaInst &AI) const;
81 
82   // Returns true if the instruction can be proven to do only two types of
83   // memory accesses:
84   //  (1) live stack locations in-bounds or
85   //  (2) non-stack locations.
86   bool stackAccessIsSafe(const Instruction &I) const;
87   void print(raw_ostream &O) const;
88   void dump() const;
89 };
90 
91 /// StackSafetyInfo wrapper for the new pass manager.
92 class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
93   friend AnalysisInfoMixin<StackSafetyAnalysis>;
94   static AnalysisKey Key;
95 
96 public:
97   using Result = StackSafetyInfo;
98   StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
99 };
100 
101 /// Printer pass for the \c StackSafetyAnalysis results.
102 class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
103   raw_ostream &OS;
104 
105 public:
106   explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {}
107   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
108 };
109 
110 /// StackSafetyInfo wrapper for the legacy pass manager
111 class StackSafetyInfoWrapperPass : public FunctionPass {
112   StackSafetyInfo SSI;
113 
114 public:
115   static char ID;
116   StackSafetyInfoWrapperPass();
117 
118   const StackSafetyInfo &getResult() const { return SSI; }
119 
120   void print(raw_ostream &O, const Module *M) const override;
121   void getAnalysisUsage(AnalysisUsage &AU) const override;
122 
123   bool runOnFunction(Function &F) override;
124 };
125 
126 /// This pass performs the global (interprocedural) stack safety analysis (new
127 /// pass manager).
128 class StackSafetyGlobalAnalysis
129     : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
130   friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
131   static AnalysisKey Key;
132 
133 public:
134   using Result = StackSafetyGlobalInfo;
135   Result run(Module &M, ModuleAnalysisManager &AM);
136 };
137 
138 /// Printer pass for the \c StackSafetyGlobalAnalysis results.
139 class StackSafetyGlobalPrinterPass
140     : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
141   raw_ostream &OS;
142 
143 public:
144   explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {}
145   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
146 };
147 
148 /// This pass performs the global (interprocedural) stack safety analysis
149 /// (legacy pass manager).
150 class StackSafetyGlobalInfoWrapperPass : public ModulePass {
151   StackSafetyGlobalInfo SSGI;
152 
153 public:
154   static char ID;
155 
156   StackSafetyGlobalInfoWrapperPass();
157   ~StackSafetyGlobalInfoWrapperPass();
158 
159   const StackSafetyGlobalInfo &getResult() const { return SSGI; }
160 
161   void print(raw_ostream &O, const Module *M) const override;
162   void getAnalysisUsage(AnalysisUsage &AU) const override;
163 
164   bool runOnModule(Module &M) override;
165 };
166 
167 bool needsParamAccessSummary(const Module &M);
168 
169 void generateParamAccessSummary(ModuleSummaryIndex &Index);
170 
171 } // end namespace llvm
172 
173 #endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
174