Home | History | Annotate | Line # | Download | only in Core
      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 
     18 using namespace clang;
     19 using namespace ento;
     20 
     21 namespace {
     22 
     23 class CountKey {
     24   const StackFrameContext *CallSite;
     25   unsigned BlockID;
     26 
     27 public:
     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(CallSite, BlockID) < std::tie(RHS.CallSite, RHS.BlockID);
     37   }
     38 
     39   void Profile(llvm::FoldingSetNodeID &ID) const {
     40     ID.AddPointer(CallSite);
     41     ID.AddInteger(BlockID);
     42   }
     43 };
     44 
     45 }
     46 
     47 typedef llvm::ImmutableMap<CountKey, unsigned> CountMap;
     48 
     49 static inline CountMap GetMap(void *D) {
     50   return CountMap(static_cast<CountMap::TreeTy*>(D));
     51 }
     52 
     53 static inline CountMap::Factory& GetFactory(void *F) {
     54   return *static_cast<CountMap::Factory*>(F);
     55 }
     56 
     57 unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
     58                                        unsigned BlockID) const {
     59   CountMap M = GetMap(Data);
     60   CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID));
     61   return T ? *T : 0;
     62 }
     63 
     64 BlockCounter::Factory::Factory(llvm::BumpPtrAllocator& Alloc) {
     65   F = new CountMap::Factory(Alloc);
     66 }
     67 
     68 BlockCounter::Factory::~Factory() {
     69   delete static_cast<CountMap::Factory*>(F);
     70 }
     71 
     72 BlockCounter
     73 BlockCounter::Factory::IncrementCount(BlockCounter BC,
     74                                         const StackFrameContext *CallSite,
     75                                         unsigned BlockID) {
     76   return BlockCounter(GetFactory(F).add(GetMap(BC.Data),
     77                                           CountKey(CallSite, BlockID),
     78                              BC.getNumVisited(CallSite, BlockID)+1).getRoot());
     79 }
     80 
     81 BlockCounter
     82 BlockCounter::Factory::GetEmptyCounter() {
     83   return BlockCounter(GetFactory(F).getEmptyMap().getRoot());
     84 }
     85