5858
5959namespace swift {
6060
61- template <typename PtrTy> class ImmutablePointerSetFactory ;
61+ template <typename T>
62+ class ImmutablePointerSetFactory ;
6263
6364// / An immutable set of pointers. It is backed by a tail allocated sorted array
6465// / ref.
65- template <typename T> class ImmutablePointerSet : public llvm ::FoldingSetNode {
66- using PtrTy = typename std::add_pointer<T>::type;
66+ template <typename T>
67+ class ImmutablePointerSet : public llvm ::FoldingSetNode {
6768 friend class ImmutablePointerSetFactory <T>;
6869
70+ using PtrTraits = llvm::PointerLikeTypeTraits<T>;
71+
6972 NullablePtr<ImmutablePointerSetFactory<T>> ParentFactory;
70- llvm::ArrayRef<PtrTy > Data;
73+ llvm::ArrayRef<T > Data;
7174
7275 ImmutablePointerSet (ImmutablePointerSetFactory<T> *ParentFactory,
73- llvm::ArrayRef<PtrTy > NewData)
76+ llvm::ArrayRef<T > NewData)
7477 : ParentFactory(ParentFactory), Data(NewData) {}
7578
7679public:
@@ -100,7 +103,7 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
100103 return !(*this == P);
101104 }
102105
103- unsigned count (PtrTy Ptr) const {
106+ unsigned count (T Ptr) const {
104107 // This returns the first element >= Ptr. Since we know that our array is
105108 // sorted and uniqued, Ptr must be that element.
106109 auto LowerBound = std::lower_bound (begin (), end (), Ptr);
@@ -113,17 +116,19 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
113116 return *LowerBound == Ptr;
114117 }
115118
116- using iterator = typename llvm::ArrayRef<PtrTy >::iterator;
119+ using iterator = typename llvm::ArrayRef<T >::iterator;
117120 iterator begin () const { return Data.begin (); }
118121 iterator end () const { return Data.end (); }
122+ llvm::iterator_range<iterator> range () const { return {begin (), end ()}; }
123+ llvm::ArrayRef<T> data () const { return Data; }
119124
120125 unsigned size () const { return Data.size (); }
121126 bool empty () const { return Data.empty (); }
122127
123128 void Profile (llvm::FoldingSetNodeID &ID) const {
124129 assert (!Data.empty () && " Should not profile empty ImmutablePointerSet" );
125- for (PtrTy P : Data) {
126- ID.AddPointer (P );
130+ for (T P : Data) {
131+ ID.AddPointer (PtrTraits::getAsVoidPointer (P) );
127132 }
128133 }
129134
@@ -177,10 +182,11 @@ template <typename T> class ImmutablePointerSet : public llvm::FoldingSetNode {
177182 }
178183};
179184
180- template <typename T> class ImmutablePointerSetFactory {
181- using PtrTy = typename std::add_pointer<T>::type;
182-
185+ template <typename T>
186+ class ImmutablePointerSetFactory {
183187 using PtrSet = ImmutablePointerSet<T>;
188+ using PtrTraits = typename PtrSet::PtrTraits;
189+
184190 // This is computed out-of-line so that ImmutablePointerSetFactory is
185191 // treated as a complete type.
186192 static const unsigned AllocAlignment;
@@ -205,7 +211,7 @@ template <typename T> class ImmutablePointerSetFactory {
205211
206212 // / Given a sorted and uniqued list \p Array, return the ImmutablePointerSet
207213 // / containing Array. Asserts if \p Array is not sorted and uniqued.
208- PtrSet *get (llvm::ArrayRef<PtrTy > Array) {
214+ PtrSet *get (llvm::ArrayRef<T > Array) {
209215 if (Array.empty ())
210216 return ImmutablePointerSetFactory::getEmptySet ();
211217
@@ -215,8 +221,8 @@ template <typename T> class ImmutablePointerSetFactory {
215221 assert (is_sorted_and_uniqued (Array));
216222
217223 llvm::FoldingSetNodeID ID;
218- for (PtrTy Ptr : Array) {
219- ID.AddPointer (Ptr);
224+ for (T Ptr : Array) {
225+ ID.AddPointer (PtrTraits::getAsVoidPointer ( Ptr) );
220226 }
221227
222228 void *InsertPt;
@@ -225,7 +231,7 @@ template <typename T> class ImmutablePointerSetFactory {
225231 }
226232
227233 size_t NumElts = Array.size ();
228- size_t MemSize = sizeof (PtrSet) + sizeof (PtrTy ) * NumElts;
234+ size_t MemSize = sizeof (PtrSet) + sizeof (T ) * NumElts;
229235
230236 // Allocate the memory.
231237 auto *Mem =
@@ -234,8 +240,8 @@ template <typename T> class ImmutablePointerSetFactory {
234240 // Copy in the pointers into the tail allocated memory. We do not need to do
235241 // any sorting/uniquing ourselves since we assume that our users perform
236242 // this task for us.
237- llvm::MutableArrayRef<PtrTy > DataMem (reinterpret_cast <PtrTy *>(&Mem[1 ]),
238- NumElts);
243+ llvm::MutableArrayRef<T > DataMem (reinterpret_cast <T *>(&Mem[1 ]),
244+ NumElts);
239245 std::copy (Array.begin (), Array.end (), DataMem.begin ());
240246
241247 // Allocate the new node and insert it into the Set.
@@ -244,7 +250,35 @@ template <typename T> class ImmutablePointerSetFactory {
244250 return NewNode;
245251 }
246252
247- PtrSet *merge (PtrSet *S1, llvm::ArrayRef<PtrTy> S2) {
253+ PtrSet *get (T value) {
254+ llvm::FoldingSetNodeID ID;
255+ ID.AddPointer (PtrTraits::getAsVoidPointer (value));
256+
257+ void *InsertPt;
258+ if (auto *PSet = Set.FindNodeOrInsertPos (ID, InsertPt)) {
259+ return PSet;
260+ }
261+
262+ size_t NumElts = 1 ;
263+ size_t MemSize = sizeof (PtrSet) + sizeof (T) * NumElts;
264+
265+ // Allocate the memory.
266+ auto *Mem =
267+ reinterpret_cast <PtrSet *>(Allocator.Allocate (MemSize, AllocAlignment));
268+
269+ // Copy in the pointers into the tail allocated memory. We do not need to do
270+ // any sorting/uniquing ourselves since we assume that our users perform
271+ // this task for us.
272+ llvm::MutableArrayRef<T> DataMem (reinterpret_cast <T *>(&Mem[1 ]), NumElts);
273+ DataMem[0 ] = value;
274+
275+ // Allocate the new node and insert it into the Set.
276+ auto *NewNode = new (Mem) PtrSet (this , DataMem);
277+ Set.InsertNode (NewNode, InsertPt);
278+ return NewNode;
279+ }
280+
281+ PtrSet *merge (PtrSet *S1, llvm::ArrayRef<T> S2) {
248282 if (S1->empty ())
249283 return get (S2);
250284
@@ -266,7 +300,7 @@ template <typename T> class ImmutablePointerSetFactory {
266300 // perform a sorted set merging algorithm to create the ID. We also count
267301 // the number of unique elements for allocation purposes.
268302 unsigned NumElts = 0 ;
269- set_union_for_each (*S1, S2, [&ID, &NumElts](const PtrTy Ptr) -> void {
303+ set_union_for_each (*S1, S2, [&ID, &NumElts](const T Ptr) -> void {
270304 ID.AddPointer (Ptr);
271305 NumElts++;
272306 });
@@ -277,7 +311,7 @@ template <typename T> class ImmutablePointerSetFactory {
277311 return PSet;
278312 }
279313
280- unsigned MemSize = sizeof (PtrSet) + sizeof (PtrTy ) * NumElts;
314+ unsigned MemSize = sizeof (PtrSet) + sizeof (T ) * NumElts;
281315
282316 // Allocate the memory.
283317 auto *Mem =
@@ -286,8 +320,7 @@ template <typename T> class ImmutablePointerSetFactory {
286320 // Copy in the union of the two pointer sets into the tail allocated
287321 // memory. Since we know that our sorted arrays are uniqued, we can use
288322 // set_union to get the uniqued sorted array that we want.
289- llvm::MutableArrayRef<PtrTy> DataMem (reinterpret_cast <PtrTy *>(&Mem[1 ]),
290- NumElts);
323+ llvm::MutableArrayRef<T> DataMem (reinterpret_cast <T *>(&Mem[1 ]), NumElts);
291324 std::set_union (S1->begin (), S1->end (), S2.begin (), S2.end (),
292325 DataMem.begin ());
293326
@@ -316,8 +349,8 @@ template <typename T> class ImmutablePointerSetFactory {
316349 // perform a sorted set merging algorithm to create the ID. We also count
317350 // the number of unique elements for allocation purposes.
318351 unsigned NumElts = 0 ;
319- set_union_for_each (*S1, *S2, [&ID, &NumElts](const PtrTy Ptr) -> void {
320- ID.AddPointer (Ptr);
352+ set_union_for_each (*S1, *S2, [&ID, &NumElts](const T Ptr) -> void {
353+ ID.AddPointer (PtrTraits::getAsVoidPointer ( Ptr) );
321354 NumElts++;
322355 });
323356
@@ -327,7 +360,7 @@ template <typename T> class ImmutablePointerSetFactory {
327360 return PSet;
328361 }
329362
330- unsigned MemSize = sizeof (PtrSet) + sizeof (PtrTy ) * NumElts;
363+ unsigned MemSize = sizeof (PtrSet) + sizeof (T ) * NumElts;
331364
332365 // Allocate the memory.
333366 auto *Mem =
@@ -336,8 +369,7 @@ template <typename T> class ImmutablePointerSetFactory {
336369 // Copy in the union of the two pointer sets into the tail allocated
337370 // memory. Since we know that our sorted arrays are uniqued, we can use
338371 // set_union to get the uniqued sorted array that we want.
339- llvm::MutableArrayRef<PtrTy> DataMem (reinterpret_cast <PtrTy *>(&Mem[1 ]),
340- NumElts);
372+ llvm::MutableArrayRef<T> DataMem (reinterpret_cast <T *>(&Mem[1 ]), NumElts);
341373 std::set_union (S1->begin (), S1->end (), S2->begin (), S2->end (),
342374 DataMem.begin ());
343375
@@ -356,8 +388,8 @@ template <typename T>
356388#if !defined(_MSC_VER) || defined(__clang__)
357389constexpr
358390#endif
359- const unsigned ImmutablePointerSetFactory<T>::AllocAlignment =
360- (alignof (PtrSet) > alignof (PtrTy )) ? alignof(PtrSet) : alignof(PtrTy );
391+ const unsigned ImmutablePointerSetFactory<T>::AllocAlignment =
392+ (alignof (PtrSet) > alignof (T )) ? alignof(PtrSet) : alignof(T );
361393
362394} // end swift namespace
363395
0 commit comments