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