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