//===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Stack Safety Analysis detects allocas and arguments with safe access. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_STACKSAFETYANALYSIS_H #define LLVM_ANALYSIS_STACKSAFETYANALYSIS_H #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" namespace llvm { class AllocaInst; class ScalarEvolution; /// Interface to access stack safety analysis results for single function. class StackSafetyInfo { public: struct InfoTy; private: Function *F = nullptr; std::function GetSE; mutable std::unique_ptr Info; public: LLVM_ABI StackSafetyInfo(); LLVM_ABI StackSafetyInfo(Function *F, std::function GetSE); LLVM_ABI StackSafetyInfo(StackSafetyInfo &&); LLVM_ABI StackSafetyInfo &operator=(StackSafetyInfo &&); LLVM_ABI ~StackSafetyInfo(); LLVM_ABI const InfoTy &getInfo() const; // TODO: Add useful for client methods. LLVM_ABI void print(raw_ostream &O) const; /// Parameters use for a FunctionSummary. /// Function collects access information of all pointer parameters. /// Information includes a range of direct access of parameters by the /// functions and all call sites accepting the parameter. /// StackSafety assumes that missing parameter information means possibility /// of access to the parameter with any offset, so we can correctly link /// code without StackSafety information, e.g. non-ThinLTO. LLVM_ABI std::vector getParamAccesses(ModuleSummaryIndex &Index) const; }; class StackSafetyGlobalInfo { public: struct InfoTy; private: Module *M = nullptr; std::function GetSSI; const ModuleSummaryIndex *Index = nullptr; mutable std::unique_ptr Info; const InfoTy &getInfo() const; public: LLVM_ABI StackSafetyGlobalInfo(); LLVM_ABI StackSafetyGlobalInfo( Module *M, std::function GetSSI, const ModuleSummaryIndex *Index); LLVM_ABI StackSafetyGlobalInfo(StackSafetyGlobalInfo &&); LLVM_ABI StackSafetyGlobalInfo &operator=(StackSafetyGlobalInfo &&); LLVM_ABI ~StackSafetyGlobalInfo(); // Whether we can prove that all accesses to this Alloca are in-range and // during its lifetime. LLVM_ABI bool isSafe(const AllocaInst &AI) const; // Returns true if the instruction can be proven to do only two types of // memory accesses: // (1) live stack locations in-bounds or // (2) non-stack locations. LLVM_ABI bool stackAccessIsSafe(const Instruction &I) const; LLVM_ABI void print(raw_ostream &O) const; LLVM_ABI void dump() const; }; /// StackSafetyInfo wrapper for the new pass manager. class StackSafetyAnalysis : public AnalysisInfoMixin { friend AnalysisInfoMixin; static AnalysisKey Key; public: using Result = StackSafetyInfo; LLVM_ABI StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM); }; /// Printer pass for the \c StackSafetyAnalysis results. class StackSafetyPrinterPass : public RequiredPassInfoMixin { raw_ostream &OS; public: explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {} LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; /// StackSafetyInfo wrapper for the legacy pass manager class LLVM_ABI StackSafetyInfoWrapperPass : public FunctionPass { StackSafetyInfo SSI; public: static char ID; StackSafetyInfoWrapperPass(); const StackSafetyInfo &getResult() const { return SSI; } void print(raw_ostream &O, const Module *M) const override; void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnFunction(Function &F) override; }; /// This pass performs the global (interprocedural) stack safety analysis (new /// pass manager). class StackSafetyGlobalAnalysis : public AnalysisInfoMixin { friend AnalysisInfoMixin; static AnalysisKey Key; public: using Result = StackSafetyGlobalInfo; LLVM_ABI Result run(Module &M, ModuleAnalysisManager &AM); }; /// Printer pass for the \c StackSafetyGlobalAnalysis results. class StackSafetyGlobalPrinterPass : public RequiredPassInfoMixin { raw_ostream &OS; public: explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {} LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; /// This pass performs the global (interprocedural) stack safety analysis /// (legacy pass manager). class LLVM_ABI StackSafetyGlobalInfoWrapperPass : public ModulePass { StackSafetyGlobalInfo SSGI; public: static char ID; StackSafetyGlobalInfoWrapperPass(); ~StackSafetyGlobalInfoWrapperPass() override; const StackSafetyGlobalInfo &getResult() const { return SSGI; } void print(raw_ostream &O, const Module *M) const override; void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnModule(Module &M) override; }; LLVM_ABI bool needsParamAccessSummary(const Module &M); LLVM_ABI void generateParamAccessSummary(ModuleSummaryIndex &Index); } // end namespace llvm #endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H