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