xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Analysis/StackSafetyAnalysis.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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   static bool isRequired() { return true; }
109 };
110 
111 /// StackSafetyInfo wrapper for the legacy pass manager
112 class StackSafetyInfoWrapperPass : public FunctionPass {
113   StackSafetyInfo SSI;
114 
115 public:
116   static char ID;
117   StackSafetyInfoWrapperPass();
118 
119   const StackSafetyInfo &getResult() const { return SSI; }
120 
121   void print(raw_ostream &O, const Module *M) const override;
122   void getAnalysisUsage(AnalysisUsage &AU) const override;
123 
124   bool runOnFunction(Function &F) override;
125 };
126 
127 /// This pass performs the global (interprocedural) stack safety analysis (new
128 /// pass manager).
129 class StackSafetyGlobalAnalysis
130     : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
131   friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
132   static AnalysisKey Key;
133 
134 public:
135   using Result = StackSafetyGlobalInfo;
136   Result run(Module &M, ModuleAnalysisManager &AM);
137 };
138 
139 /// Printer pass for the \c StackSafetyGlobalAnalysis results.
140 class StackSafetyGlobalPrinterPass
141     : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
142   raw_ostream &OS;
143 
144 public:
145   explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {}
146   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
147   static bool isRequired() { return true; }
148 };
149 
150 /// This pass performs the global (interprocedural) stack safety analysis
151 /// (legacy pass manager).
152 class StackSafetyGlobalInfoWrapperPass : public ModulePass {
153   StackSafetyGlobalInfo SSGI;
154 
155 public:
156   static char ID;
157 
158   StackSafetyGlobalInfoWrapperPass();
159   ~StackSafetyGlobalInfoWrapperPass();
160 
161   const StackSafetyGlobalInfo &getResult() const { return SSGI; }
162 
163   void print(raw_ostream &O, const Module *M) const override;
164   void getAnalysisUsage(AnalysisUsage &AU) const override;
165 
166   bool runOnModule(Module &M) override;
167 };
168 
169 bool needsParamAccessSummary(const Module &M);
170 
171 void generateParamAccessSummary(ModuleSummaryIndex &Index);
172 
173 } // end namespace llvm
174 
175 #endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
176