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