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