xref: /openbsd-src/gnu/llvm/llvm/lib/Transforms/ObjCARC/BlotMapVector.h (revision 09467b48e8bc8b4905716062da846024139afbf2)
1*09467b48Spatrick //===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===//
2*09467b48Spatrick //
3*09467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*09467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*09467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*09467b48Spatrick //
7*09467b48Spatrick //===----------------------------------------------------------------------===//
8*09467b48Spatrick 
9*09467b48Spatrick #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
10*09467b48Spatrick #define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
11*09467b48Spatrick 
12*09467b48Spatrick #include "llvm/ADT/DenseMap.h"
13*09467b48Spatrick #include <cassert>
14*09467b48Spatrick #include <cstddef>
15*09467b48Spatrick #include <utility>
16*09467b48Spatrick #include <vector>
17*09467b48Spatrick 
18*09467b48Spatrick namespace llvm {
19*09467b48Spatrick 
20*09467b48Spatrick /// An associative container with fast insertion-order (deterministic)
21*09467b48Spatrick /// iteration over its elements. Plus the special blot operation.
22*09467b48Spatrick template <class KeyT, class ValueT> class BlotMapVector {
23*09467b48Spatrick   /// Map keys to indices in Vector.
24*09467b48Spatrick   using MapTy = DenseMap<KeyT, size_t>;
25*09467b48Spatrick   MapTy Map;
26*09467b48Spatrick 
27*09467b48Spatrick   /// Keys and values.
28*09467b48Spatrick   using VectorTy = std::vector<std::pair<KeyT, ValueT>>;
29*09467b48Spatrick   VectorTy Vector;
30*09467b48Spatrick 
31*09467b48Spatrick public:
32*09467b48Spatrick #ifdef EXPENSIVE_CHECKS
~BlotMapVector()33*09467b48Spatrick   ~BlotMapVector() {
34*09467b48Spatrick     assert(Vector.size() >= Map.size()); // May differ due to blotting.
35*09467b48Spatrick     for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E;
36*09467b48Spatrick          ++I) {
37*09467b48Spatrick       assert(I->second < Vector.size());
38*09467b48Spatrick       assert(Vector[I->second].first == I->first);
39*09467b48Spatrick     }
40*09467b48Spatrick     for (typename VectorTy::const_iterator I = Vector.begin(), E = Vector.end();
41*09467b48Spatrick          I != E; ++I)
42*09467b48Spatrick       assert(!I->first || (Map.count(I->first) &&
43*09467b48Spatrick                            Map[I->first] == size_t(I - Vector.begin())));
44*09467b48Spatrick   }
45*09467b48Spatrick #endif
46*09467b48Spatrick 
47*09467b48Spatrick   using iterator = typename VectorTy::iterator;
48*09467b48Spatrick   using const_iterator = typename VectorTy::const_iterator;
49*09467b48Spatrick 
begin()50*09467b48Spatrick   iterator begin() { return Vector.begin(); }
end()51*09467b48Spatrick   iterator end() { return Vector.end(); }
begin()52*09467b48Spatrick   const_iterator begin() const { return Vector.begin(); }
end()53*09467b48Spatrick   const_iterator end() const { return Vector.end(); }
54*09467b48Spatrick 
55*09467b48Spatrick   ValueT &operator[](const KeyT &Arg) {
56*09467b48Spatrick     std::pair<typename MapTy::iterator, bool> Pair =
57*09467b48Spatrick         Map.insert(std::make_pair(Arg, size_t(0)));
58*09467b48Spatrick     if (Pair.second) {
59*09467b48Spatrick       size_t Num = Vector.size();
60*09467b48Spatrick       Pair.first->second = Num;
61*09467b48Spatrick       Vector.push_back(std::make_pair(Arg, ValueT()));
62*09467b48Spatrick       return Vector[Num].second;
63*09467b48Spatrick     }
64*09467b48Spatrick     return Vector[Pair.first->second].second;
65*09467b48Spatrick   }
66*09467b48Spatrick 
insert(const std::pair<KeyT,ValueT> & InsertPair)67*09467b48Spatrick   std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &InsertPair) {
68*09467b48Spatrick     std::pair<typename MapTy::iterator, bool> Pair =
69*09467b48Spatrick         Map.insert(std::make_pair(InsertPair.first, size_t(0)));
70*09467b48Spatrick     if (Pair.second) {
71*09467b48Spatrick       size_t Num = Vector.size();
72*09467b48Spatrick       Pair.first->second = Num;
73*09467b48Spatrick       Vector.push_back(InsertPair);
74*09467b48Spatrick       return std::make_pair(Vector.begin() + Num, true);
75*09467b48Spatrick     }
76*09467b48Spatrick     return std::make_pair(Vector.begin() + Pair.first->second, false);
77*09467b48Spatrick   }
78*09467b48Spatrick 
find(const KeyT & Key)79*09467b48Spatrick   iterator find(const KeyT &Key) {
80*09467b48Spatrick     typename MapTy::iterator It = Map.find(Key);
81*09467b48Spatrick     if (It == Map.end())
82*09467b48Spatrick       return Vector.end();
83*09467b48Spatrick     return Vector.begin() + It->second;
84*09467b48Spatrick   }
85*09467b48Spatrick 
find(const KeyT & Key)86*09467b48Spatrick   const_iterator find(const KeyT &Key) const {
87*09467b48Spatrick     typename MapTy::const_iterator It = Map.find(Key);
88*09467b48Spatrick     if (It == Map.end())
89*09467b48Spatrick       return Vector.end();
90*09467b48Spatrick     return Vector.begin() + It->second;
91*09467b48Spatrick   }
92*09467b48Spatrick 
93*09467b48Spatrick   /// This is similar to erase, but instead of removing the element from the
94*09467b48Spatrick   /// vector, it just zeros out the key in the vector. This leaves iterators
95*09467b48Spatrick   /// intact, but clients must be prepared for zeroed-out keys when iterating.
blot(const KeyT & Key)96*09467b48Spatrick   void blot(const KeyT &Key) {
97*09467b48Spatrick     typename MapTy::iterator It = Map.find(Key);
98*09467b48Spatrick     if (It == Map.end())
99*09467b48Spatrick       return;
100*09467b48Spatrick     Vector[It->second].first = KeyT();
101*09467b48Spatrick     Map.erase(It);
102*09467b48Spatrick   }
103*09467b48Spatrick 
clear()104*09467b48Spatrick   void clear() {
105*09467b48Spatrick     Map.clear();
106*09467b48Spatrick     Vector.clear();
107*09467b48Spatrick   }
108*09467b48Spatrick 
empty()109*09467b48Spatrick   bool empty() const {
110*09467b48Spatrick     assert(Map.empty() == Vector.empty());
111*09467b48Spatrick     return Map.empty();
112*09467b48Spatrick   }
113*09467b48Spatrick };
114*09467b48Spatrick 
115*09467b48Spatrick } // end namespace llvm
116*09467b48Spatrick 
117*09467b48Spatrick #endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
118