StackSafetyAnalysis.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- StackSafetyAnalysis.h - Stack memory safety analysis -----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // Stack Safety Analysis detects allocas and arguments with safe access.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
  18. #define LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
  19. #include "llvm/IR/ModuleSummaryIndex.h"
  20. #include "llvm/IR/PassManager.h"
  21. #include "llvm/Pass.h"
  22. namespace llvm {
  23. class AllocaInst;
  24. class ScalarEvolution;
  25. /// Interface to access stack safety analysis results for single function.
  26. class StackSafetyInfo {
  27. public:
  28. struct InfoTy;
  29. private:
  30. Function *F = nullptr;
  31. std::function<ScalarEvolution &()> GetSE;
  32. mutable std::unique_ptr<InfoTy> Info;
  33. public:
  34. StackSafetyInfo();
  35. StackSafetyInfo(Function *F, std::function<ScalarEvolution &()> GetSE);
  36. StackSafetyInfo(StackSafetyInfo &&);
  37. StackSafetyInfo &operator=(StackSafetyInfo &&);
  38. ~StackSafetyInfo();
  39. const InfoTy &getInfo() const;
  40. // TODO: Add useful for client methods.
  41. void print(raw_ostream &O) const;
  42. /// Parameters use for a FunctionSummary.
  43. /// Function collects access information of all pointer parameters.
  44. /// Information includes a range of direct access of parameters by the
  45. /// functions and all call sites accepting the parameter.
  46. /// StackSafety assumes that missing parameter information means possibility
  47. /// of access to the parameter with any offset, so we can correctly link
  48. /// code without StackSafety information, e.g. non-ThinLTO.
  49. std::vector<FunctionSummary::ParamAccess>
  50. getParamAccesses(ModuleSummaryIndex &Index) const;
  51. };
  52. class StackSafetyGlobalInfo {
  53. public:
  54. struct InfoTy;
  55. private:
  56. Module *M = nullptr;
  57. std::function<const StackSafetyInfo &(Function &F)> GetSSI;
  58. const ModuleSummaryIndex *Index = nullptr;
  59. mutable std::unique_ptr<InfoTy> Info;
  60. const InfoTy &getInfo() const;
  61. public:
  62. StackSafetyGlobalInfo();
  63. StackSafetyGlobalInfo(
  64. Module *M, std::function<const StackSafetyInfo &(Function &F)> GetSSI,
  65. const ModuleSummaryIndex *Index);
  66. StackSafetyGlobalInfo(StackSafetyGlobalInfo &&);
  67. StackSafetyGlobalInfo &operator=(StackSafetyGlobalInfo &&);
  68. ~StackSafetyGlobalInfo();
  69. // Whether we can prove that all accesses to this Alloca are in-range and
  70. // during its lifetime.
  71. bool isSafe(const AllocaInst &AI) const;
  72. // Returns true if the instruction can be proven to do only two types of
  73. // memory accesses:
  74. // (1) live stack locations in-bounds or
  75. // (2) non-stack locations.
  76. bool stackAccessIsSafe(const Instruction &I) const;
  77. void print(raw_ostream &O) const;
  78. void dump() const;
  79. };
  80. /// StackSafetyInfo wrapper for the new pass manager.
  81. class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
  82. friend AnalysisInfoMixin<StackSafetyAnalysis>;
  83. static AnalysisKey Key;
  84. public:
  85. using Result = StackSafetyInfo;
  86. StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
  87. };
  88. /// Printer pass for the \c StackSafetyAnalysis results.
  89. class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
  90. raw_ostream &OS;
  91. public:
  92. explicit StackSafetyPrinterPass(raw_ostream &OS) : OS(OS) {}
  93. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
  94. };
  95. /// StackSafetyInfo wrapper for the legacy pass manager
  96. class StackSafetyInfoWrapperPass : public FunctionPass {
  97. StackSafetyInfo SSI;
  98. public:
  99. static char ID;
  100. StackSafetyInfoWrapperPass();
  101. const StackSafetyInfo &getResult() const { return SSI; }
  102. void print(raw_ostream &O, const Module *M) const override;
  103. void getAnalysisUsage(AnalysisUsage &AU) const override;
  104. bool runOnFunction(Function &F) override;
  105. };
  106. /// This pass performs the global (interprocedural) stack safety analysis (new
  107. /// pass manager).
  108. class StackSafetyGlobalAnalysis
  109. : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
  110. friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
  111. static AnalysisKey Key;
  112. public:
  113. using Result = StackSafetyGlobalInfo;
  114. Result run(Module &M, ModuleAnalysisManager &AM);
  115. };
  116. /// Printer pass for the \c StackSafetyGlobalAnalysis results.
  117. class StackSafetyGlobalPrinterPass
  118. : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
  119. raw_ostream &OS;
  120. public:
  121. explicit StackSafetyGlobalPrinterPass(raw_ostream &OS) : OS(OS) {}
  122. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  123. };
  124. /// This pass performs the global (interprocedural) stack safety analysis
  125. /// (legacy pass manager).
  126. class StackSafetyGlobalInfoWrapperPass : public ModulePass {
  127. StackSafetyGlobalInfo SSGI;
  128. public:
  129. static char ID;
  130. StackSafetyGlobalInfoWrapperPass();
  131. ~StackSafetyGlobalInfoWrapperPass();
  132. const StackSafetyGlobalInfo &getResult() const { return SSGI; }
  133. void print(raw_ostream &O, const Module *M) const override;
  134. void getAnalysisUsage(AnalysisUsage &AU) const override;
  135. bool runOnModule(Module &M) override;
  136. };
  137. bool needsParamAccessSummary(const Module &M);
  138. void generateParamAccessSummary(ModuleSummaryIndex &Index);
  139. } // end namespace llvm
  140. #endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
  141. #ifdef __GNUC__
  142. #pragma GCC diagnostic pop
  143. #endif