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   bool isSafe(const AllocaInst &AI) const;
79   void print(raw_ostream &O) const;
80   void dump() const;
81 };
82 
83 /// StackSafetyInfo wrapper for the new pass manager.
84 class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
85   friend AnalysisInfoMixin<StackSafetyAnalysis>;
86   static AnalysisKey Key;
87 
88 public:
89   using Result = StackSafetyInfo;
90   StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
91 };
92 
93 /// Printer pass for the \c StackSafetyAnalysis results.
94 class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
95   raw_ostream &OS;
96 
97 public:
StackSafetyPrinterPass(raw_ostream & OS)98   explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {}
99   PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
100 };
101 
102 /// StackSafetyInfo wrapper for the legacy pass manager
103 class StackSafetyInfoWrapperPass : public FunctionPass {
104   StackSafetyInfo SSI;
105 
106 public:
107   static char ID;
108   StackSafetyInfoWrapperPass();
109 
getResult()110   const StackSafetyInfo &getResult() const { return SSI; }
111 
112   void print(raw_ostream &O, const Module *M) const override;
113   void getAnalysisUsage(AnalysisUsage &AU) const override;
114 
115   bool runOnFunction(Function &F) override;
116 };
117 
118 /// This pass performs the global (interprocedural) stack safety analysis (new
119 /// pass manager).
120 class StackSafetyGlobalAnalysis
121     : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
122   friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
123   static AnalysisKey Key;
124 
125 public:
126   using Result = StackSafetyGlobalInfo;
127   Result run(Module &M, ModuleAnalysisManager &AM);
128 };
129 
130 /// Printer pass for the \c StackSafetyGlobalAnalysis results.
131 class StackSafetyGlobalPrinterPass
132     : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
133   raw_ostream &OS;
134 
135 public:
StackSafetyGlobalPrinterPass(raw_ostream & OS)136   explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {}
137   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
138 };
139 
140 /// This pass performs the global (interprocedural) stack safety analysis
141 /// (legacy pass manager).
142 class StackSafetyGlobalInfoWrapperPass : public ModulePass {
143   StackSafetyGlobalInfo SSGI;
144 
145 public:
146   static char ID;
147 
148   StackSafetyGlobalInfoWrapperPass();
149   ~StackSafetyGlobalInfoWrapperPass();
150 
getResult()151   const StackSafetyGlobalInfo &getResult() const { return SSGI; }
152 
153   void print(raw_ostream &O, const Module *M) const override;
154   void getAnalysisUsage(AnalysisUsage &AU) const override;
155 
156   bool runOnModule(Module &M) override;
157 };
158 
159 bool needsParamAccessSummary(const Module &M);
160 
161 void generateParamAccessSummary(ModuleSummaryIndex &Index);
162 
163 } // end namespace llvm
164 
165 #endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
166