1//==- BlockCounter.h - ADT for counting block visits -------------*- 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 BlockCounter, an abstract data type used to count
10// the number of times a given block has been visited along a path
11// analyzed by CoreEngine.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
16#include "llvm/ADT/ImmutableMap.h"
17
18using namespace clang;
19using namespace ento;
20
21namespace {
22
23class CountKey {
24 const StackFrameContext *CallSite;
25 unsigned BlockID;
26
27public:
28 CountKey(const StackFrameContext *CS, unsigned ID)
29 : CallSite(CS), BlockID(ID) {}
30
31 bool operator==(const CountKey &RHS) const {
32 return (CallSite == RHS.CallSite) && (BlockID == RHS.BlockID);
33 }
34
35 bool operator<(const CountKey &RHS) const {
36 return std::tie(args: CallSite, args: BlockID) < std::tie(args: RHS.CallSite, args: RHS.BlockID);
37 }
38
39 void Profile(llvm::FoldingSetNodeID &ID) const {
40 ID.AddPointer(Ptr: CallSite);
41 ID.AddInteger(I: BlockID);
42 }
43};
44
45}
46
47typedef llvm::ImmutableMap<CountKey, unsigned> CountMap;
48
49static inline CountMap GetMap(void *D) {
50 return CountMap(static_cast<CountMap::TreeTy*>(D));
51}
52
53static inline CountMap::Factory& GetFactory(void *F) {
54 return *static_cast<CountMap::Factory*>(F);
55}
56
57unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
58 unsigned BlockID) const {
59 CountMap M = GetMap(D: Data);
60 CountMap::data_type* T = M.lookup(K: CountKey(CallSite, BlockID));
61 return T ? *T : 0;
62}
63
64BlockCounter::Factory::Factory(llvm::BumpPtrAllocator& Alloc) {
65 F = new CountMap::Factory(Alloc);
66}
67
68BlockCounter::Factory::~Factory() {
69 delete static_cast<CountMap::Factory*>(F);
70}
71
72BlockCounter
73BlockCounter::Factory::IncrementCount(BlockCounter BC,
74 const StackFrameContext *CallSite,
75 unsigned BlockID) {
76 return BlockCounter(GetFactory(F).add(Old: GetMap(D: BC.Data),
77 K: CountKey(CallSite, BlockID),
78 D: BC.getNumVisited(CallSite, BlockID)+1).getRoot());
79}
80
81BlockCounter
82BlockCounter::Factory::GetEmptyCounter() {
83 return BlockCounter(GetFactory(F).getEmptyMap().getRoot());
84}
85