xref: /freebsd/contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/EntryPointStats.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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