Home | History | Annotate | Line # | Download | only in Analysis
      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   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.
     84 class StackSafetyAnalysis : public AnalysisInfoMixin<StackSafetyAnalysis> {
     85   friend AnalysisInfoMixin<StackSafetyAnalysis>;
     86   static AnalysisKey Key;
     87 
     88 public:
     89   using Result = StackSafetyInfo;
     90   StackSafetyInfo run(Function &F, FunctionAnalysisManager &AM);
     91 };
     92 
     93 /// Printer pass for the \c StackSafetyAnalysis results.
     94 class StackSafetyPrinterPass : public PassInfoMixin<StackSafetyPrinterPass> {
     95   raw_ostream &OS;
     96 
     97 public:
     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
    103 class StackSafetyInfoWrapperPass : public FunctionPass {
    104   StackSafetyInfo SSI;
    105 
    106 public:
    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).
    120 class StackSafetyGlobalAnalysis
    121     : public AnalysisInfoMixin<StackSafetyGlobalAnalysis> {
    122   friend AnalysisInfoMixin<StackSafetyGlobalAnalysis>;
    123   static AnalysisKey Key;
    124 
    125 public:
    126   using Result = StackSafetyGlobalInfo;
    127   Result run(Module &M, ModuleAnalysisManager &AM);
    128 };
    129 
    130 /// Printer pass for the \c StackSafetyGlobalAnalysis results.
    131 class StackSafetyGlobalPrinterPass
    132     : public PassInfoMixin<StackSafetyGlobalPrinterPass> {
    133   raw_ostream &OS;
    134 
    135 public:
    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).
    142 class StackSafetyGlobalInfoWrapperPass : public ModulePass {
    143   StackSafetyGlobalInfo SSGI;
    144 
    145 public:
    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 
    159 bool needsParamAccessSummary(const Module &M);
    160 
    161 void generateParamAccessSummary(ModuleSummaryIndex &Index);
    162 
    163 } // end namespace llvm
    164 
    165 #endif // LLVM_ANALYSIS_STACKSAFETYANALYSIS_H
    166