Home | History | Annotate | Line # | Download | only in PathSensitive
      1 //===- FunctionSummary.h - Stores summaries of functions. -------*- 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 // This file defines a summary of a function gathered/used by static analysis.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
     14 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
     15 
     16 #include "clang/AST/Decl.h"
     17 #include "clang/Basic/LLVM.h"
     18 #include "llvm/ADT/DenseMap.h"
     19 #include "llvm/ADT/DenseSet.h"
     20 #include "llvm/ADT/None.h"
     21 #include "llvm/ADT/Optional.h"
     22 #include "llvm/ADT/SmallBitVector.h"
     23 #include <cassert>
     24 #include <deque>
     25 #include <utility>
     26 
     27 namespace clang {
     28 namespace ento {
     29 
     30 using SetOfDecls = std::deque<Decl *>;
     31 using SetOfConstDecls = llvm::DenseSet<const Decl *>;
     32 
     33 class FunctionSummariesTy {
     34   class FunctionSummary {
     35   public:
     36     /// Marks the IDs of the basic blocks visited during the analyzes.
     37     llvm::SmallBitVector VisitedBasicBlocks;
     38 
     39     /// Total number of blocks in the function.
     40     unsigned TotalBasicBlocks : 30;
     41 
     42     /// True if this function has been checked against the rules for which
     43     /// functions may be inlined.
     44     unsigned InlineChecked : 1;
     45 
     46     /// True if this function may be inlined.
     47     unsigned MayInline : 1;
     48 
     49     /// The number of times the function has been inlined.
     50     unsigned TimesInlined : 32;
     51 
     52     FunctionSummary()
     53         : TotalBasicBlocks(0), InlineChecked(0), MayInline(0),
     54           TimesInlined(0) {}
     55   };
     56 
     57   using MapTy = llvm::DenseMap<const Decl *, FunctionSummary>;
     58   MapTy Map;
     59 
     60 public:
     61   MapTy::iterator findOrInsertSummary(const Decl *D) {
     62     MapTy::iterator I = Map.find(D);
     63     if (I != Map.end())
     64       return I;
     65 
     66     using KVPair = std::pair<const Decl *, FunctionSummary>;
     67 
     68     I = Map.insert(KVPair(D, FunctionSummary())).first;
     69     assert(I != Map.end());
     70     return I;
     71   }
     72 
     73   void markMayInline(const Decl *D) {
     74     MapTy::iterator I = findOrInsertSummary(D);
     75     I->second.InlineChecked = 1;
     76     I->second.MayInline = 1;
     77   }
     78 
     79   void markShouldNotInline(const Decl *D) {
     80     MapTy::iterator I = findOrInsertSummary(D);
     81     I->second.InlineChecked = 1;
     82     I->second.MayInline = 0;
     83   }
     84 
     85   void markReachedMaxBlockCount(const Decl *D) {
     86     markShouldNotInline(D);
     87   }
     88 
     89   Optional<bool> mayInline(const Decl *D) {
     90     MapTy::const_iterator I = Map.find(D);
     91     if (I != Map.end() && I->second.InlineChecked)
     92       return I->second.MayInline;
     93     return None;
     94   }
     95 
     96   void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) {
     97     MapTy::iterator I = findOrInsertSummary(D);
     98     llvm::SmallBitVector &Blocks = I->second.VisitedBasicBlocks;
     99     assert(ID < TotalIDs);
    100     if (TotalIDs > Blocks.size()) {
    101       Blocks.resize(TotalIDs);
    102       I->second.TotalBasicBlocks = TotalIDs;
    103     }
    104     Blocks.set(ID);
    105   }
    106 
    107   unsigned getNumVisitedBasicBlocks(const Decl* D) {
    108     MapTy::const_iterator I = Map.find(D);
    109     if (I != Map.end())
    110       return I->second.VisitedBasicBlocks.count();
    111     return 0;
    112   }
    113 
    114   unsigned getNumTimesInlined(const Decl* D) {
    115     MapTy::const_iterator I = Map.find(D);
    116     if (I != Map.end())
    117       return I->second.TimesInlined;
    118     return 0;
    119   }
    120 
    121   void bumpNumTimesInlined(const Decl* D) {
    122     MapTy::iterator I = findOrInsertSummary(D);
    123     I->second.TimesInlined++;
    124   }
    125 
    126   /// Get the percentage of the reachable blocks.
    127   unsigned getPercentBlocksReachable(const Decl *D) {
    128     MapTy::const_iterator I = Map.find(D);
    129       if (I != Map.end())
    130         return ((I->second.VisitedBasicBlocks.count() * 100) /
    131                  I->second.TotalBasicBlocks);
    132     return 0;
    133   }
    134 
    135   unsigned getTotalNumBasicBlocks();
    136   unsigned getTotalNumVisitedBasicBlocks();
    137 };
    138 
    139 } // namespace ento
    140 } // namespace clang
    141 
    142 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
    143