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
20namespace llvm {
21
22class AllocaInst;
23class ScalarEvolution;
24
25/// Interface to access stack safety analysis results for single function.
26class StackSafetyInfo {
27public:
28  struct InfoTy;
29
30private:
31  Function *F = nullptr;
32  std::function<ScalarEvolution &()> GetSE;
33  mutable std::unique_ptr<InfoTy> Info;
34
35public:
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
58class StackSafetyGlobalInfo {
59public:
60  struct InfoTy;
61
62private:
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
69public:
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.
84class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
85  friend AnalysisInfoMixin<StackSafetyAnalysis>;
86  static AnalysisKey Key;
87
88public:
89  using Result = StackSafetyInfo;
90  StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
91};
92
93/// Printer pass for the \c StackSafetyAnalysis results.
94class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
95  raw_ostream &OS;
96
97public:
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
103class StackSafetyInfoWrapperPass : public FunctionPass {
104  StackSafetyInfo SSI;
105
106public:
107  static char ID;
108  StackSafetyInfoWrapperPass();
109
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).
120class StackSafetyGlobalAnalysis
121    : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
122  friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
123  static AnalysisKey Key;
124
125public:
126  using Result = StackSafetyGlobalInfo;
127  Result run(Module &M, ModuleAnalysisManager &AM);
128};
129
130/// Printer pass for the \c StackSafetyGlobalAnalysis results.
131class StackSafetyGlobalPrinterPass
132    : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
133  raw_ostream &OS;
134
135public:
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).
142class StackSafetyGlobalInfoWrapperPass : public ModulePass {
143  StackSafetyGlobalInfo SSGI;
144
145public:
146  static char ID;
147
148  StackSafetyGlobalInfoWrapperPass();
149  ~StackSafetyGlobalInfoWrapperPass();
150
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
159bool needsParamAccessSummary(const Module &M);
160
161void generateParamAccessSummary(ModuleSummaryIndex &Index);
162
163} // end namespace llvm
164
165#endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
166