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