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