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 markReachedMaxBlockCount(const Decl * D)84 void markReachedMaxBlockCount(const Decl *D) { 85 markShouldNotInline(D); 86 } 87 mayInline(const Decl * D)88 std::optional<bool> mayInline(const Decl *D) { 89 MapTy::const_iterator I = Map.find(D); 90 if (I != Map.end() && I->second.InlineChecked) 91 return I->second.MayInline; 92 return std::nullopt; 93 } 94 markVisitedBasicBlock(unsigned ID,const Decl * D,unsigned TotalIDs)95 void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) { 96 MapTy::iterator I = findOrInsertSummary(D); 97 llvm::SmallBitVector &Blocks = I->second.VisitedBasicBlocks; 98 assert(ID < TotalIDs); 99 if (TotalIDs > Blocks.size()) { 100 Blocks.resize(TotalIDs); 101 I->second.TotalBasicBlocks = TotalIDs; 102 } 103 Blocks.set(ID); 104 } 105 getNumVisitedBasicBlocks(const Decl * D)106 unsigned getNumVisitedBasicBlocks(const Decl* D) { 107 MapTy::const_iterator I = Map.find(D); 108 if (I != Map.end()) 109 return I->second.VisitedBasicBlocks.count(); 110 return 0; 111 } 112 getNumTimesInlined(const Decl * D)113 unsigned getNumTimesInlined(const Decl* D) { 114 MapTy::const_iterator I = Map.find(D); 115 if (I != Map.end()) 116 return I->second.TimesInlined; 117 return 0; 118 } 119 bumpNumTimesInlined(const Decl * D)120 void bumpNumTimesInlined(const Decl* D) { 121 MapTy::iterator I = findOrInsertSummary(D); 122 I->second.TimesInlined++; 123 } 124 125 /// Get the percentage of the reachable blocks. getPercentBlocksReachable(const Decl * D)126 unsigned getPercentBlocksReachable(const Decl *D) { 127 MapTy::const_iterator I = Map.find(D); 128 if (I != Map.end()) 129 return ((I->second.VisitedBasicBlocks.count() * 100) / 130 I->second.TotalBasicBlocks); 131 return 0; 132 } 133 134 unsigned getTotalNumBasicBlocks(); 135 unsigned getTotalNumVisitedBasicBlocks(); 136 }; 137 138 } // namespace ento 139 } // namespace clang 140 141 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H 142