1 // EntryPointStats.h - Tracking statistics per entry point ------*- 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 #ifndef CLANG_INCLUDE_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENTRYPOINTSTATS_H 10 #define CLANG_INCLUDE_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENTRYPOINTSTATS_H 11 12 #include "llvm/ADT/Statistic.h" 13 #include "llvm/ADT/StringRef.h" 14 15 namespace llvm { 16 class raw_ostream; 17 } // namespace llvm 18 19 namespace clang { 20 class Decl; 21 22 namespace ento { 23 24 class EntryPointStat { 25 public: name()26 llvm::StringLiteral name() const { return Name; } 27 28 static void lockRegistry(); 29 30 static void takeSnapshot(const Decl *EntryPoint); 31 static void dumpStatsAsCSV(llvm::raw_ostream &OS); 32 static void dumpStatsAsCSV(llvm::StringRef FileName); 33 34 protected: EntryPointStat(llvm::StringLiteral Name)35 explicit EntryPointStat(llvm::StringLiteral Name) : Name{Name} {} 36 EntryPointStat(const EntryPointStat &) = delete; 37 EntryPointStat(EntryPointStat &&) = delete; 38 EntryPointStat &operator=(EntryPointStat &) = delete; 39 EntryPointStat &operator=(EntryPointStat &&) = delete; 40 41 private: 42 llvm::StringLiteral Name; 43 }; 44 45 class BoolEPStat : public EntryPointStat { 46 std::optional<bool> Value = {}; 47 48 public: 49 explicit BoolEPStat(llvm::StringLiteral Name); value()50 unsigned value() const { return Value && *Value; } set(bool V)51 void set(bool V) { 52 assert(!Value.has_value()); 53 Value = V; 54 } reset()55 void reset() { Value = {}; } 56 }; 57 58 // used by CounterEntryPointTranslationUnitStat 59 class CounterEPStat : public EntryPointStat { 60 using EntryPointStat::EntryPointStat; 61 unsigned Value = {}; 62 63 public: 64 explicit CounterEPStat(llvm::StringLiteral Name); value()65 unsigned value() const { return Value; } reset()66 void reset() { Value = {}; } 67 CounterEPStat &operator++() { 68 ++Value; 69 return *this; 70 } 71 72 CounterEPStat &operator++(int) { 73 // No difference as you can't extract the value 74 return ++(*this); 75 } 76 77 CounterEPStat &operator+=(unsigned Inc) { 78 Value += Inc; 79 return *this; 80 } 81 }; 82 83 // used by UnsignedMaxEtryPointTranslationUnitStatistic 84 class UnsignedMaxEPStat : public EntryPointStat { 85 using EntryPointStat::EntryPointStat; 86 unsigned Value = {}; 87 88 public: 89 explicit UnsignedMaxEPStat(llvm::StringLiteral Name); value()90 unsigned value() const { return Value; } reset()91 void reset() { Value = {}; } updateMax(unsigned X)92 void updateMax(unsigned X) { Value = std::max(Value, X); } 93 }; 94 95 class UnsignedEPStat : public EntryPointStat { 96 using EntryPointStat::EntryPointStat; 97 std::optional<unsigned> Value = {}; 98 99 public: 100 explicit UnsignedEPStat(llvm::StringLiteral Name); value()101 unsigned value() const { return Value.value_or(0); } reset()102 void reset() { Value.reset(); } set(unsigned V)103 void set(unsigned V) { 104 assert(!Value.has_value()); 105 Value = V; 106 } 107 }; 108 109 class CounterEntryPointTranslationUnitStat { 110 CounterEPStat M; 111 llvm::TrackingStatistic S; 112 113 public: CounterEntryPointTranslationUnitStat(const char * DebugType,llvm::StringLiteral Name,llvm::StringLiteral Desc)114 CounterEntryPointTranslationUnitStat(const char *DebugType, 115 llvm::StringLiteral Name, 116 llvm::StringLiteral Desc) 117 : M(Name), S(DebugType, Name.data(), Desc.data()) {} 118 CounterEntryPointTranslationUnitStat &operator++() { 119 ++M; 120 ++S; 121 return *this; 122 } 123 124 CounterEntryPointTranslationUnitStat &operator++(int) { 125 // No difference with prefix as the value is not observable. 126 return ++(*this); 127 } 128 129 CounterEntryPointTranslationUnitStat &operator+=(unsigned Inc) { 130 M += Inc; 131 S += Inc; 132 return *this; 133 } 134 }; 135 136 class UnsignedMaxEntryPointTranslationUnitStatistic { 137 UnsignedMaxEPStat M; 138 llvm::TrackingStatistic S; 139 140 public: UnsignedMaxEntryPointTranslationUnitStatistic(const char * DebugType,llvm::StringLiteral Name,llvm::StringLiteral Desc)141 UnsignedMaxEntryPointTranslationUnitStatistic(const char *DebugType, 142 llvm::StringLiteral Name, 143 llvm::StringLiteral Desc) 144 : M(Name), S(DebugType, Name.data(), Desc.data()) {} updateMax(uint64_t Value)145 void updateMax(uint64_t Value) { 146 M.updateMax(static_cast<unsigned>(Value)); 147 S.updateMax(Value); 148 } 149 }; 150 151 #define STAT_COUNTER(VARNAME, DESC) \ 152 static clang::ento::CounterEntryPointTranslationUnitStat VARNAME = { \ 153 DEBUG_TYPE, #VARNAME, DESC} 154 155 #define STAT_MAX(VARNAME, DESC) \ 156 static clang::ento::UnsignedMaxEntryPointTranslationUnitStatistic VARNAME = \ 157 {DEBUG_TYPE, #VARNAME, DESC} 158 159 } // namespace ento 160 } // namespace clang 161 162 #endif // CLANG_INCLUDE_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENTRYPOINTSTATS_H 163