xref: /openbsd-src/gnu/llvm/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick //==- BlockCounter.h - ADT for counting block visits -------------*- C++ -*-//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick //  This file defines BlockCounter, an abstract data type used to count
10*e5dd7070Spatrick //  the number of times a given block has been visited along a path
11*e5dd7070Spatrick //  analyzed by CoreEngine.
12*e5dd7070Spatrick //
13*e5dd7070Spatrick //===----------------------------------------------------------------------===//
14*e5dd7070Spatrick 
15*e5dd7070Spatrick #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
16*e5dd7070Spatrick #include "llvm/ADT/ImmutableMap.h"
17*e5dd7070Spatrick 
18*e5dd7070Spatrick using namespace clang;
19*e5dd7070Spatrick using namespace ento;
20*e5dd7070Spatrick 
21*e5dd7070Spatrick namespace {
22*e5dd7070Spatrick 
23*e5dd7070Spatrick class CountKey {
24*e5dd7070Spatrick   const StackFrameContext *CallSite;
25*e5dd7070Spatrick   unsigned BlockID;
26*e5dd7070Spatrick 
27*e5dd7070Spatrick public:
CountKey(const StackFrameContext * CS,unsigned ID)28*e5dd7070Spatrick   CountKey(const StackFrameContext *CS, unsigned ID)
29*e5dd7070Spatrick     : CallSite(CS), BlockID(ID) {}
30*e5dd7070Spatrick 
operator ==(const CountKey & RHS) const31*e5dd7070Spatrick   bool operator==(const CountKey &RHS) const {
32*e5dd7070Spatrick     return (CallSite == RHS.CallSite) && (BlockID == RHS.BlockID);
33*e5dd7070Spatrick   }
34*e5dd7070Spatrick 
operator <(const CountKey & RHS) const35*e5dd7070Spatrick   bool operator<(const CountKey &RHS) const {
36*e5dd7070Spatrick     return std::tie(CallSite, BlockID) < std::tie(RHS.CallSite, RHS.BlockID);
37*e5dd7070Spatrick   }
38*e5dd7070Spatrick 
Profile(llvm::FoldingSetNodeID & ID) const39*e5dd7070Spatrick   void Profile(llvm::FoldingSetNodeID &ID) const {
40*e5dd7070Spatrick     ID.AddPointer(CallSite);
41*e5dd7070Spatrick     ID.AddInteger(BlockID);
42*e5dd7070Spatrick   }
43*e5dd7070Spatrick };
44*e5dd7070Spatrick 
45*e5dd7070Spatrick }
46*e5dd7070Spatrick 
47*e5dd7070Spatrick typedef llvm::ImmutableMap<CountKey, unsigned> CountMap;
48*e5dd7070Spatrick 
GetMap(void * D)49*e5dd7070Spatrick static inline CountMap GetMap(void *D) {
50*e5dd7070Spatrick   return CountMap(static_cast<CountMap::TreeTy*>(D));
51*e5dd7070Spatrick }
52*e5dd7070Spatrick 
GetFactory(void * F)53*e5dd7070Spatrick static inline CountMap::Factory& GetFactory(void *F) {
54*e5dd7070Spatrick   return *static_cast<CountMap::Factory*>(F);
55*e5dd7070Spatrick }
56*e5dd7070Spatrick 
getNumVisited(const StackFrameContext * CallSite,unsigned BlockID) const57*e5dd7070Spatrick unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
58*e5dd7070Spatrick                                        unsigned BlockID) const {
59*e5dd7070Spatrick   CountMap M = GetMap(Data);
60*e5dd7070Spatrick   CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID));
61*e5dd7070Spatrick   return T ? *T : 0;
62*e5dd7070Spatrick }
63*e5dd7070Spatrick 
Factory(llvm::BumpPtrAllocator & Alloc)64*e5dd7070Spatrick BlockCounter::Factory::Factory(llvm::BumpPtrAllocator& Alloc) {
65*e5dd7070Spatrick   F = new CountMap::Factory(Alloc);
66*e5dd7070Spatrick }
67*e5dd7070Spatrick 
~Factory()68*e5dd7070Spatrick BlockCounter::Factory::~Factory() {
69*e5dd7070Spatrick   delete static_cast<CountMap::Factory*>(F);
70*e5dd7070Spatrick }
71*e5dd7070Spatrick 
72*e5dd7070Spatrick BlockCounter
IncrementCount(BlockCounter BC,const StackFrameContext * CallSite,unsigned BlockID)73*e5dd7070Spatrick BlockCounter::Factory::IncrementCount(BlockCounter BC,
74*e5dd7070Spatrick                                         const StackFrameContext *CallSite,
75*e5dd7070Spatrick                                         unsigned BlockID) {
76*e5dd7070Spatrick   return BlockCounter(GetFactory(F).add(GetMap(BC.Data),
77*e5dd7070Spatrick                                           CountKey(CallSite, BlockID),
78*e5dd7070Spatrick                              BC.getNumVisited(CallSite, BlockID)+1).getRoot());
79*e5dd7070Spatrick }
80*e5dd7070Spatrick 
81*e5dd7070Spatrick BlockCounter
GetEmptyCounter()82*e5dd7070Spatrick BlockCounter::Factory::GetEmptyCounter() {
83*e5dd7070Spatrick   return BlockCounter(GetFactory(F).getEmptyMap().getRoot());
84*e5dd7070Spatrick }
85