xref: /llvm-project/llvm/lib/Transforms/ObjCARC/BlotMapVector.h (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
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