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> getParamAccesses() const;
55};
56
57class StackSafetyGlobalInfo {
58public:
59  struct InfoTy;
60
61private:
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
68public:
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.
83class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
84  friend AnalysisInfoMixin<StackSafetyAnalysis>;
85  static AnalysisKey Key;
86
87public:
88  using Result = StackSafetyInfo;
89  StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
90};
91
92/// Printer pass for the \c StackSafetyAnalysis results.
93class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
94  raw_ostream &OS;
95
96public:
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
102class StackSafetyInfoWrapperPass : public FunctionPass {
103  StackSafetyInfo SSI;
104
105public:
106  static char ID;
107  StackSafetyInfoWrapperPass();
108
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).
119class StackSafetyGlobalAnalysis
120    : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
121  friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
122  static AnalysisKey Key;
123
124public:
125  using Result = StackSafetyGlobalInfo;
126  Result run(Module &M, ModuleAnalysisManager &AM);
127};
128
129/// Printer pass for the \c StackSafetyGlobalAnalysis results.
130class StackSafetyGlobalPrinterPass
131    : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
132  raw_ostream &OS;
133
134public:
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).
141class StackSafetyGlobalInfoWrapperPass : public ModulePass {
142  StackSafetyGlobalInfo SSGI;
143
144public:
145  static char ID;
146
147  StackSafetyGlobalInfoWrapperPass();
148  ~StackSafetyGlobalInfoWrapperPass();
149
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
158bool needsParamAccessSummary(const Module &M);
159
160void generateParamAccessSummary(ModuleSummaryIndex &Index);
161
162} // end namespace llvm
163
164#endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
165