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