blob: 2fa07cfb32c0c80f7533af215c067d5bca659707 [file] [log] [blame]
Eugene Zelenko57bd5a02017-10-27 01:09:08 +00001//===- BlotMapVector.h - A MapVector with the blot operation ----*- C++ -*-===//
Michael Gottesman0be69202015-03-05 23:28:58 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Michael Gottesman0be69202015-03-05 23:28:58 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenko57bd5a02017-10-27 01:09:08 +00009#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
10#define LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H
11
Michael Gottesman0be69202015-03-05 23:28:58 +000012#include "llvm/ADT/DenseMap.h"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000013#include <cassert>
14#include <cstddef>
15#include <utility>
Chandler Carruth6bda14b2017-06-06 11:49:48 +000016#include <vector>
Michael Gottesman0be69202015-03-05 23:28:58 +000017
18namespace llvm {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000019
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000020/// An associative container with fast insertion-order (deterministic)
Michael Gottesman0be69202015-03-05 23:28:58 +000021/// iteration over its elements. Plus the special blot operation.
22template <class KeyT, class ValueT> class BlotMapVector {
23 /// Map keys to indices in Vector.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000024 using MapTy = DenseMap<KeyT, size_t>;
Michael Gottesman0be69202015-03-05 23:28:58 +000025 MapTy Map;
26
Michael Gottesman0be69202015-03-05 23:28:58 +000027 /// Keys and values.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000028 using VectorTy = std::vector<std::pair<KeyT, ValueT>>;
Michael Gottesman0be69202015-03-05 23:28:58 +000029 VectorTy Vector;
30
31public:
Filipe Cabecinhas0da99372016-04-29 15:22:48 +000032#ifdef EXPENSIVE_CHECKS
Michael Gottesman0be69202015-03-05 23:28:58 +000033 ~BlotMapVector() {
34 assert(Vector.size() >= Map.size()); // May differ due to blotting.
35 for (typename MapTy::const_iterator I = Map.begin(), E = Map.end(); I != E;
36 ++I) {
37 assert(I->second < Vector.size());
38 assert(Vector[I->second].first == I->first);
39 }
40 for (typename VectorTy::const_iterator I = Vector.begin(), E = Vector.end();
41 I != E; ++I)
42 assert(!I->first || (Map.count(I->first) &&
43 Map[I->first] == size_t(I - Vector.begin())));
44 }
45#endif
46
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000047 using iterator = typename VectorTy::iterator;
48 using const_iterator = typename VectorTy::const_iterator;
49
50 iterator begin() { return Vector.begin(); }
51 iterator end() { return Vector.end(); }
52 const_iterator begin() const { return Vector.begin(); }
53 const_iterator end() const { return Vector.end(); }
54
Michael Gottesman0be69202015-03-05 23:28:58 +000055 ValueT &operator[](const KeyT &Arg) {
56 std::pair<typename MapTy::iterator, bool> Pair =
57 Map.insert(std::make_pair(Arg, size_t(0)));
58 if (Pair.second) {
59 size_t Num = Vector.size();
60 Pair.first->second = Num;
61 Vector.push_back(std::make_pair(Arg, ValueT()));
62 return Vector[Num].second;
63 }
64 return Vector[Pair.first->second].second;
65 }
66
67 std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &InsertPair) {
68 std::pair<typename MapTy::iterator, bool> Pair =
69 Map.insert(std::make_pair(InsertPair.first, size_t(0)));
70 if (Pair.second) {
71 size_t Num = Vector.size();
72 Pair.first->second = Num;
73 Vector.push_back(InsertPair);
74 return std::make_pair(Vector.begin() + Num, true);
75 }
76 return std::make_pair(Vector.begin() + Pair.first->second, false);
77 }
78
79 iterator find(const KeyT &Key) {
80 typename MapTy::iterator It = Map.find(Key);
81 if (It == Map.end())
82 return Vector.end();
83 return Vector.begin() + It->second;
84 }
85
86 const_iterator find(const KeyT &Key) const {
87 typename MapTy::const_iterator It = Map.find(Key);
88 if (It == Map.end())
89 return Vector.end();
90 return Vector.begin() + It->second;
91 }
92
93 /// This is similar to erase, but instead of removing the element from the
94 /// vector, it just zeros out the key in the vector. This leaves iterators
95 /// intact, but clients must be prepared for zeroed-out keys when iterating.
96 void blot(const KeyT &Key) {
97 typename MapTy::iterator It = Map.find(Key);
98 if (It == Map.end())
99 return;
100 Vector[It->second].first = KeyT();
101 Map.erase(It);
102 }
103
104 void clear() {
105 Map.clear();
106 Vector.clear();
107 }
Michael Gottesmanc01ab512015-03-16 07:02:39 +0000108
109 bool empty() const {
110 assert(Map.empty() == Vector.empty());
111 return Map.empty();
112 }
Michael Gottesman0be69202015-03-05 23:28:58 +0000113};
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000114
115} // end namespace llvm
116
117#endif // LLVM_LIB_TRANSFORMS_OBJCARC_BLOTMAPVECTOR_H