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