157bd5a02SEugene Zelenko //===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===// 20be6920eSMichael Gottesman // 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 60be6920eSMichael Gottesman // 70be6920eSMichael Gottesman //===----------------------------------------------------------------------===// 80be6920eSMichael Gottesman 957bd5a02SEugene Zelenko #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H 1057bd5a02SEugene Zelenko #define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H 1157bd5a02SEugene Zelenko 120be6920eSMichael Gottesman #include "llvm/ADT/DenseMap.h" 1357bd5a02SEugene Zelenko #include <cassert> 1457bd5a02SEugene Zelenko #include <cstddef> 1557bd5a02SEugene Zelenko #include <utility> 166bda14b3SChandler Carruth #include <vector> 170be6920eSMichael Gottesman 180be6920eSMichael Gottesman namespace llvm { 1957bd5a02SEugene Zelenko 205f8f34e4SAdrian Prantl /// An associative container with fast insertion-order (deterministic) 210be6920eSMichael Gottesman /// iteration over its elements. Plus the special blot operation. 220be6920eSMichael Gottesman template <class KeyT, class ValueT> class BlotMapVector { 230be6920eSMichael Gottesman /// Map keys to indices in Vector. 2457bd5a02SEugene Zelenko using MapTy = DenseMap<KeyT, size_t>; 250be6920eSMichael Gottesman MapTy Map; 260be6920eSMichael Gottesman 270be6920eSMichael Gottesman /// Keys and values. 2857bd5a02SEugene Zelenko using VectorTy = std::vector<std::pair<KeyT, ValueT>>; 290be6920eSMichael Gottesman VectorTy Vector; 300be6920eSMichael Gottesman 310be6920eSMichael Gottesman public: 320da99375SFilipe Cabecinhas #ifdef EXPENSIVE_CHECKS ~BlotMapVector()330be6920eSMichael Gottesman ~BlotMapVector() { 340be6920eSMichael Gottesman assert(Vector.size() >= Map.size()); // May differ due to blotting. 350be6920eSMichael Gottesman for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E; 360be6920eSMichael Gottesman ++I) { 370be6920eSMichael Gottesman assert(I->second < Vector.size()); 380be6920eSMichael Gottesman assert(Vector[I->second].first == I->first); 390be6920eSMichael Gottesman } 400be6920eSMichael Gottesman for (typename VectorTy::const_iterator I = Vector.begin(), E = Vector.end(); 410be6920eSMichael Gottesman I != E; ++I) 420be6920eSMichael Gottesman assert(!I->first || (Map.count(I->first) && 430be6920eSMichael Gottesman Map[I->first] == size_t(I - Vector.begin()))); 440be6920eSMichael Gottesman } 450be6920eSMichael Gottesman #endif 460be6920eSMichael Gottesman 4757bd5a02SEugene Zelenko using iterator = typename VectorTy::iterator; 4857bd5a02SEugene Zelenko using const_iterator = typename VectorTy::const_iterator; 4957bd5a02SEugene Zelenko begin()5057bd5a02SEugene Zelenko iterator begin() { return Vector.begin(); } end()5157bd5a02SEugene Zelenko iterator end() { return Vector.end(); } begin()5257bd5a02SEugene Zelenko const_iterator begin() const { return Vector.begin(); } end()5357bd5a02SEugene Zelenko const_iterator end() const { return Vector.end(); } 5457bd5a02SEugene Zelenko 550be6920eSMichael Gottesman ValueT &operator[](const KeyT &Arg) { 560be6920eSMichael Gottesman std::pair<typename MapTy::iterator, bool> Pair = 570be6920eSMichael Gottesman Map.insert(std::make_pair(Arg, size_t(0))); 580be6920eSMichael Gottesman if (Pair.second) { 590be6920eSMichael Gottesman size_t Num = Vector.size(); 600be6920eSMichael Gottesman Pair.first->second = Num; 610be6920eSMichael Gottesman Vector.push_back(std::make_pair(Arg, ValueT())); 620be6920eSMichael Gottesman return Vector[Num].second; 630be6920eSMichael Gottesman } 640be6920eSMichael Gottesman return Vector[Pair.first->second].second; 650be6920eSMichael Gottesman } 660be6920eSMichael Gottesman insert(const std::pair<KeyT,ValueT> & InsertPair)670be6920eSMichael Gottesman std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &InsertPair) { 680be6920eSMichael Gottesman std::pair<typename MapTy::iterator, bool> Pair = 690be6920eSMichael Gottesman Map.insert(std::make_pair(InsertPair.first, size_t(0))); 700be6920eSMichael Gottesman if (Pair.second) { 710be6920eSMichael Gottesman size_t Num = Vector.size(); 720be6920eSMichael Gottesman Pair.first->second = Num; 730be6920eSMichael Gottesman Vector.push_back(InsertPair); 740be6920eSMichael Gottesman return std::make_pair(Vector.begin() + Num, true); 750be6920eSMichael Gottesman } 760be6920eSMichael Gottesman return std::make_pair(Vector.begin() + Pair.first->second, false); 770be6920eSMichael Gottesman } 780be6920eSMichael Gottesman find(const KeyT & Key)790be6920eSMichael Gottesman iterator find(const KeyT &Key) { 800be6920eSMichael Gottesman typename MapTy::iterator It = Map.find(Key); 810be6920eSMichael Gottesman if (It == Map.end()) 820be6920eSMichael Gottesman return Vector.end(); 830be6920eSMichael Gottesman return Vector.begin() + It->second; 840be6920eSMichael Gottesman } 850be6920eSMichael Gottesman find(const KeyT & Key)860be6920eSMichael Gottesman const_iterator find(const KeyT &Key) const { 870be6920eSMichael Gottesman typename MapTy::const_iterator It = Map.find(Key); 880be6920eSMichael Gottesman if (It == Map.end()) 890be6920eSMichael Gottesman return Vector.end(); 900be6920eSMichael Gottesman return Vector.begin() + It->second; 910be6920eSMichael Gottesman } 920be6920eSMichael Gottesman 930be6920eSMichael Gottesman /// This is similar to erase, but instead of removing the element from the 940be6920eSMichael Gottesman /// vector, it just zeros out the key in the vector. This leaves iterators 950be6920eSMichael Gottesman /// intact, but clients must be prepared for zeroed-out keys when iterating. blot(const KeyT & Key)960be6920eSMichael Gottesman void blot(const KeyT &Key) { 970be6920eSMichael Gottesman typename MapTy::iterator It = Map.find(Key); 980be6920eSMichael Gottesman if (It == Map.end()) 990be6920eSMichael Gottesman return; 1000be6920eSMichael Gottesman Vector[It->second].first = KeyT(); 1010be6920eSMichael Gottesman Map.erase(It); 1020be6920eSMichael Gottesman } 1030be6920eSMichael Gottesman clear()1040be6920eSMichael Gottesman void clear() { 1050be6920eSMichael Gottesman Map.clear(); 1060be6920eSMichael Gottesman Vector.clear(); 1070be6920eSMichael Gottesman } 108c01ab519SMichael Gottesman empty()109c01ab519SMichael Gottesman bool empty() const { 110c01ab519SMichael Gottesman assert(Map.empty() == Vector.empty()); 111c01ab519SMichael Gottesman return Map.empty(); 112c01ab519SMichael Gottesman } 1130be6920eSMichael Gottesman }; 11457bd5a02SEugene Zelenko 11557bd5a02SEugene Zelenko } // end namespace llvm 11657bd5a02SEugene Zelenko 11757bd5a02SEugene Zelenko #endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H 118