LLVM 22.0.0git
ImmutableMap.h
Go to the documentation of this file.
1//===--- ImmutableMap.h - Immutable (functional) map interface --*- C++ -*-===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the ImmutableMap class.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ADT_IMMUTABLEMAP_H
15#define LLVM_ADT_IMMUTABLEMAP_H
16
17#include "llvm/ADT/FoldingSet.h"
20#include <utility>
21
22namespace llvm {
23
24/// ImutKeyValueInfo -Traits class used by ImmutableMap. While both the first
25/// and second elements in a pair are used to generate profile information,
26/// only the first element (the key) is used by isEqual and isLess.
27template <typename T, typename S>
29 using value_type = const std::pair<T,S>;
30 using value_type_ref = const value_type&;
31 using key_type = const T;
32 using key_type_ref = const T&;
33 using data_type = const S;
34 using data_type_ref = const S&;
35
37 return V.first;
38 }
39
41 return V.second;
42 }
43
44 static inline bool isEqual(key_type_ref L, key_type_ref R) {
46 }
47 static inline bool isLess(key_type_ref L, key_type_ref R) {
49 }
50
51 static inline bool isDataEqual(data_type_ref L, data_type_ref R) {
53 }
54
59};
60
61template <typename KeyT, typename ValT,
62 typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
64public:
65 using value_type = typename ValInfo::value_type;
66 using value_type_ref = typename ValInfo::value_type_ref;
67 using key_type = typename ValInfo::key_type;
68 using key_type_ref = typename ValInfo::key_type_ref;
69 using data_type = typename ValInfo::data_type;
70 using data_type_ref = typename ValInfo::data_type_ref;
72
73protected:
75
76public:
77 /// Constructs a map from a pointer to a tree root. In general one
78 /// should use a Factory object to create maps instead of directly
79 /// invoking the constructor, but there are cases where make this
80 /// constructor public is useful.
81 explicit ImmutableMap(const TreeTy *R) : Root(const_cast<TreeTy *>(R)) {}
82
83 class Factory {
84 typename TreeTy::Factory F;
85 const bool Canonicalize;
86
87 public:
88 Factory(bool canonicalize = true) : Canonicalize(canonicalize) {}
89
90 Factory(BumpPtrAllocator &Alloc, bool canonicalize = true)
91 : F(Alloc), Canonicalize(canonicalize) {}
92
93 Factory(const Factory &) = delete;
94 Factory &operator=(const Factory &) = delete;
95
96 ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
97
100 TreeTy *T = F.add(Old.Root.get(), std::pair<key_type, data_type>(K, D));
101 return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
102 }
103
105 TreeTy *T = F.remove(Old.Root.get(), K);
106 return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
107 }
108
109 typename TreeTy::Factory *getTreeFactory() const {
110 return const_cast<typename TreeTy::Factory *>(&F);
111 }
112 };
113
114 [[nodiscard]] bool contains(key_type_ref K) const {
115 return Root ? Root->contains(K) : false;
116 }
117
118 [[nodiscard]] bool operator==(const ImmutableMap &RHS) const {
119 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
120 }
121
122 [[nodiscard]] bool operator!=(const ImmutableMap &RHS) const {
123 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
124 : Root != RHS.Root;
125 }
126
127 [[nodiscard]] TreeTy *getRoot() const {
128 if (Root) { Root->retain(); }
129 return Root.get();
130 }
131
132 [[nodiscard]] TreeTy *getRootWithoutRetain() const { return Root.get(); }
133
135 if (Root) Root->retain();
136 }
137
139 if (Root) Root->release();
140 }
141
142 [[nodiscard]] bool isEmpty() const { return !Root; }
143
144public:
145 //===--------------------------------------------------===//
146 // For testing.
147 //===--------------------------------------------------===//
148
149 void verify() const { if (Root) Root->verify(); }
150
151 //===--------------------------------------------------===//
152 // Iterators.
153 //===--------------------------------------------------===//
154
155 class iterator : public ImutAVLValueIterator<ImmutableMap> {
156 friend class ImmutableMap;
157
158 iterator() = default;
159 explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
160
161 public:
162 key_type_ref getKey() const { return (*this)->first; }
163 data_type_ref getData() const { return (*this)->second; }
164 };
165
166 [[nodiscard]] iterator begin() const { return iterator(Root.get()); }
167 [[nodiscard]] iterator end() const { return iterator(); }
168
169 [[nodiscard]] data_type *lookup(key_type_ref K) const {
170 if (Root) {
171 TreeTy* T = Root->find(K);
172 if (T) return &T->getValue().second;
173 }
174
175 return nullptr;
176 }
177
178 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
179 /// which key is the highest in the ordering of keys in the map. This
180 /// method returns NULL if the map is empty.
181 [[nodiscard]] value_type *getMaxElement() const {
182 return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
183 }
184
185 //===--------------------------------------------------===//
186 // Utility methods.
187 //===--------------------------------------------------===//
188
189 [[nodiscard]] unsigned getHeight() const {
190 return Root ? Root->getHeight() : 0;
191 }
192
193 static inline void Profile(FoldingSetNodeID& ID, const ImmutableMap& M) {
194 ID.AddPointer(M.Root.get());
195 }
196
197 inline void Profile(FoldingSetNodeID& ID) const {
198 return Profile(ID,*this);
199 }
200};
201
202// NOTE: This will possibly become the new implementation of ImmutableMap some day.
203template <typename KeyT, typename ValT,
204typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
206public:
207 using value_type = typename ValInfo::value_type;
208 using value_type_ref = typename ValInfo::value_type_ref;
209 using key_type = typename ValInfo::key_type;
210 using key_type_ref = typename ValInfo::key_type_ref;
211 using data_type = typename ValInfo::data_type;
212 using data_type_ref = typename ValInfo::data_type_ref;
214 using FactoryTy = typename TreeTy::Factory;
215
216protected:
219
220public:
221 /// Constructs a map from a pointer to a tree root. In general one
222 /// should use a Factory object to create maps instead of directly
223 /// invoking the constructor, but there are cases where make this
224 /// constructor public is useful.
226 : Root(const_cast<TreeTy *>(R)), Factory(F) {}
227
230 : Root(X.getRootWithoutRetain()), Factory(F.getTreeFactory()) {}
231
233 return ImmutableMapRef(nullptr, F);
234 }
235
237 if (Root) Root->retain();
238 }
239
241 if (Root) Root->release();
242 }
243
245 TreeTy *NewT =
246 Factory->add(Root.get(), std::pair<key_type, data_type>(K, D));
247 return ImmutableMapRef(NewT, Factory);
248 }
249
251 TreeTy *NewT = Factory->remove(Root.get(), K);
252 return ImmutableMapRef(NewT, Factory);
253 }
254
255 [[nodiscard]] bool contains(key_type_ref K) const {
256 return Root ? Root->contains(K) : false;
257 }
258
260 return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root.get()));
261 }
262
263 [[nodiscard]] bool operator==(const ImmutableMapRef &RHS) const {
264 return Root && RHS.Root ? Root->isEqual(*RHS.Root.get()) : Root == RHS.Root;
265 }
266
267 [[nodiscard]] bool operator!=(const ImmutableMapRef &RHS) const {
268 return Root && RHS.Root ? Root->isNotEqual(*RHS.Root.get())
269 : Root != RHS.Root;
270 }
271
272 [[nodiscard]] bool isEmpty() const { return !Root; }
273
274 //===--------------------------------------------------===//
275 // For testing.
276 //===--------------------------------------------------===//
277
278 void verify() const {
279 if (Root)
280 Root->verify();
281 }
282
283 //===--------------------------------------------------===//
284 // Iterators.
285 //===--------------------------------------------------===//
286
287 class iterator : public ImutAVLValueIterator<ImmutableMapRef> {
288 friend class ImmutableMapRef;
289
290 iterator() = default;
291 explicit iterator(TreeTy *Tree) : iterator::ImutAVLValueIterator(Tree) {}
292
293 public:
294 key_type_ref getKey() const { return (*this)->first; }
295 data_type_ref getData() const { return (*this)->second; }
296 };
297
298 [[nodiscard]] iterator begin() const { return iterator(Root.get()); }
299 [[nodiscard]] iterator end() const { return iterator(); }
300
301 [[nodiscard]] data_type *lookup(key_type_ref K) const {
302 if (Root) {
303 TreeTy* T = Root->find(K);
304 if (T) return &T->getValue().second;
305 }
306
307 return nullptr;
308 }
309
310 /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
311 /// which key is the highest in the ordering of keys in the map. This
312 /// method returns NULL if the map is empty.
313 [[nodiscard]] value_type *getMaxElement() const {
314 return Root ? &(Root->getMaxElement()->getValue()) : nullptr;
315 }
316
317 //===--------------------------------------------------===//
318 // Utility methods.
319 //===--------------------------------------------------===//
320
321 [[nodiscard]] unsigned getHeight() const {
322 return Root ? Root->getHeight() : 0;
323 }
324
325 static inline void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M) {
326 ID.AddPointer(M.Root.get());
327 }
328
329 inline void Profile(FoldingSetNodeID &ID) const { return Profile(ID, *this); }
330};
331
332} // end namespace llvm
333
334#endif // LLVM_ADT_IMMUTABLEMAP_H
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file defines a hash set that can be used to remove duplication of nodes in a graph.
This file defines the ImutAVLTree and ImmutableSet classes.
#define F(x, y, z)
Definition MD5.cpp:55
Load MIR Sample Profile
#define T
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Value * RHS
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
Definition FoldingSet.h:330
key_type_ref getKey() const
data_type_ref getData() const
unsigned getHeight() const
ImmutableMap< KeyT, ValT > asImmutableMap() const
static ImmutableMapRef getEmptyMap(FactoryTy *F)
void Profile(FoldingSetNodeID &ID) const
bool operator!=(const ImmutableMapRef &RHS) const
bool contains(key_type_ref K) const
static void Profile(FoldingSetNodeID &ID, const ImmutableMapRef &M)
typename ValInfo::data_type data_type
typename ValInfo::data_type_ref data_type_ref
typename ValInfo::key_type key_type
IntrusiveRefCntPtr< TreeTy > Root
ImutAVLTree< ValInfo > TreeTy
typename ValInfo::value_type_ref value_type_ref
bool operator==(const ImmutableMapRef &RHS) const
ImmutableMapRef remove(key_type_ref K) const
typename ValInfo::key_type_ref key_type_ref
value_type * getMaxElement() const
getMaxElement - Returns the <key,value> pair in the ImmutableMap for which key is the highest in the ...
ImmutableMapRef add(key_type_ref K, data_type_ref D) const
typename ValInfo::value_type value_type
iterator begin() const
ImmutableMapRef(const TreeTy *R, FactoryTy *F)
Constructs a map from a pointer to a tree root.
data_type * lookup(key_type_ref K) const
iterator end() const
ImmutableMapRef(const ImmutableMap< KeyT, ValT > &X, typename ImmutableMap< KeyT, ValT >::Factory &F)
typename TreeTy::Factory FactoryTy
ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D)
Factory(bool canonicalize=true)
TreeTy::Factory * getTreeFactory() const
Factory(const Factory &)=delete
Factory(BumpPtrAllocator &Alloc, bool canonicalize=true)
Factory & operator=(const Factory &)=delete
ImmutableMap remove(ImmutableMap Old, key_type_ref K)
key_type_ref getKey() const
data_type_ref getData() const
void verify() const
bool operator==(const ImmutableMap &RHS) const
typename ValInfo::data_type data_type
typename ValInfo::value_type value_type
ImmutableMap(const TreeTy *R)
Constructs a map from a pointer to a tree root.
IntrusiveRefCntPtr< TreeTy > Root
ImutAVLTree< ValInfo > TreeTy
typename ValInfo::key_type key_type
unsigned getHeight() const
iterator begin() const
static void Profile(FoldingSetNodeID &ID, const ImmutableMap &M)
bool contains(key_type_ref K) const
bool isEmpty() const
data_type * lookup(key_type_ref K) const
TreeTy * getRootWithoutRetain() const
typename ValInfo::key_type_ref key_type_ref
void Profile(FoldingSetNodeID &ID) const
bool operator!=(const ImmutableMap &RHS) const
typename ValInfo::data_type_ref data_type_ref
iterator end() const
typename ValInfo::value_type_ref value_type_ref
TreeTy * getRoot() const
value_type * getMaxElement() const
getMaxElement - Returns the <key,value> pair in the ImmutableMap for which key is the highest in the ...
ImutAVLFactory< ValInfo > Factory
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
static bool isLess(key_type_ref LHS, key_type_ref RHS)
static bool isEqual(key_type_ref LHS, key_type_ref RHS)
ImutKeyValueInfo -Traits class used by ImmutableMap.
const value_type & value_type_ref
static void Profile(FoldingSetNodeID &ID, value_type_ref V)
static bool isLess(key_type_ref L, key_type_ref R)
static key_type_ref KeyOfValue(value_type_ref V)
const std::pair< T, S > value_type
static data_type_ref DataOfValue(value_type_ref V)
static bool isDataEqual(data_type_ref L, data_type_ref R)
static bool isEqual(key_type_ref L, key_type_ref R)
static void Profile(FoldingSetNodeID &ID, value_type_ref X)