|  | //===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H | 
|  | #define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H | 
|  |  | 
|  | #include "llvm/ADT/DenseMap.h" | 
|  | #include <cassert> | 
|  | #include <cstddef> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | /// An associative container with fast insertion-order (deterministic) | 
|  | /// iteration over its elements. Plus the special blot operation. | 
|  | template <class KeyT, class ValueT> class BlotMapVector { | 
|  | /// Map keys to indices in Vector. | 
|  | using MapTy = DenseMap<KeyT, size_t>; | 
|  | MapTy Map; | 
|  |  | 
|  | /// Keys and values. | 
|  | using VectorTy = std::vector<std::pair<KeyT, ValueT>>; | 
|  | VectorTy Vector; | 
|  |  | 
|  | public: | 
|  | #ifdef EXPENSIVE_CHECKS | 
|  | ~BlotMapVector() { | 
|  | assert(Vector.size() >= Map.size()); // May differ due to blotting. | 
|  | for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E; | 
|  | ++I) { | 
|  | assert(I->second < Vector.size()); | 
|  | assert(Vector[I->second].first == I->first); | 
|  | } | 
|  | for (typename VectorTy::const_iterator I = Vector.begin(), E = Vector.end(); | 
|  | I != E; ++I) | 
|  | assert(!I->first || (Map.count(I->first) && | 
|  | Map[I->first] == size_t(I - Vector.begin()))); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | using iterator = typename VectorTy::iterator; | 
|  | using const_iterator = typename VectorTy::const_iterator; | 
|  |  | 
|  | iterator begin() { return Vector.begin(); } | 
|  | iterator end() { return Vector.end(); } | 
|  | const_iterator begin() const { return Vector.begin(); } | 
|  | const_iterator end() const { return Vector.end(); } | 
|  |  | 
|  | ValueT &operator[](const KeyT &Arg) { | 
|  | std::pair<typename MapTy::iterator, bool> Pair = | 
|  | Map.insert(std::make_pair(Arg, size_t(0))); | 
|  | if (Pair.second) { | 
|  | size_t Num = Vector.size(); | 
|  | Pair.first->second = Num; | 
|  | Vector.push_back(std::make_pair(Arg, ValueT())); | 
|  | return Vector[Num].second; | 
|  | } | 
|  | return Vector[Pair.first->second].second; | 
|  | } | 
|  |  | 
|  | std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &InsertPair) { | 
|  | std::pair<typename MapTy::iterator, bool> Pair = | 
|  | Map.insert(std::make_pair(InsertPair.first, size_t(0))); | 
|  | if (Pair.second) { | 
|  | size_t Num = Vector.size(); | 
|  | Pair.first->second = Num; | 
|  | Vector.push_back(InsertPair); | 
|  | return std::make_pair(Vector.begin() + Num, true); | 
|  | } | 
|  | return std::make_pair(Vector.begin() + Pair.first->second, false); | 
|  | } | 
|  |  | 
|  | iterator find(const KeyT &Key) { | 
|  | typename MapTy::iterator It = Map.find(Key); | 
|  | if (It == Map.end()) | 
|  | return Vector.end(); | 
|  | return Vector.begin() + It->second; | 
|  | } | 
|  |  | 
|  | const_iterator find(const KeyT &Key) const { | 
|  | typename MapTy::const_iterator It = Map.find(Key); | 
|  | if (It == Map.end()) | 
|  | return Vector.end(); | 
|  | return Vector.begin() + It->second; | 
|  | } | 
|  |  | 
|  | /// This is similar to erase, but instead of removing the element from the | 
|  | /// vector, it just zeros out the key in the vector. This leaves iterators | 
|  | /// intact, but clients must be prepared for zeroed-out keys when iterating. | 
|  | void blot(const KeyT &Key) { | 
|  | typename MapTy::iterator It = Map.find(Key); | 
|  | if (It == Map.end()) | 
|  | return; | 
|  | Vector[It->second].first = KeyT(); | 
|  | Map.erase(It); | 
|  | } | 
|  |  | 
|  | void clear() { | 
|  | Map.clear(); | 
|  | Vector.clear(); | 
|  | } | 
|  |  | 
|  | bool empty() const { | 
|  | assert(Map.empty() == Vector.empty()); | 
|  | return Map.empty(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H |