1 //===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_ADT_TINYPTRVECTOR_H
10 #define LLVM_ADT_TINYPTRVECTOR_H
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/PointerUnion.h"
15 #include "llvm/ADT/SmallVector.h"
19 #include <type_traits>
23 /// TinyPtrVector - This class is specialized for cases where there are
24 /// normally 0 or 1 element in a vector, but is general enough to go beyond that
27 /// NOTE: This container doesn't allow you to store a null pointer into it.
29 template <typename EltTy
>
32 using VecTy
= SmallVector
<EltTy
, 4>;
33 using value_type
= typename
VecTy::value_type
;
34 using PtrUnion
= PointerUnion
<EltTy
, VecTy
*>;
40 TinyPtrVector() = default;
43 if (VecTy
*V
= Val
.template dyn_cast
<VecTy
*>())
47 TinyPtrVector(const TinyPtrVector
&RHS
) : Val(RHS
.Val
) {
48 if (VecTy
*V
= Val
.template dyn_cast
<VecTy
*>())
52 TinyPtrVector
&operator=(const TinyPtrVector
&RHS
) {
60 // Try to squeeze into the single slot. If it won't fit, allocate a copied
62 if (Val
.template is
<EltTy
>()) {
66 Val
= new VecTy(*RHS
.Val
.template get
<VecTy
*>());
70 // If we have a full vector allocated, try to re-use it.
71 if (RHS
.Val
.template is
<EltTy
>()) {
72 Val
.template get
<VecTy
*>()->clear();
73 Val
.template get
<VecTy
*>()->push_back(RHS
.front());
75 *Val
.template get
<VecTy
*>() = *RHS
.Val
.template get
<VecTy
*>();
80 TinyPtrVector(TinyPtrVector
&&RHS
) : Val(RHS
.Val
) {
81 RHS
.Val
= (EltTy
)nullptr;
84 TinyPtrVector
&operator=(TinyPtrVector
&&RHS
) {
92 // If this vector has been allocated on the heap, re-use it if cheap. If it
93 // would require more copying, just delete it and we'll steal the other
95 if (VecTy
*V
= Val
.template dyn_cast
<VecTy
*>()) {
96 if (RHS
.Val
.template is
<EltTy
>()) {
98 V
->push_back(RHS
.front());
99 RHS
.Val
= (EltTy
)nullptr;
106 RHS
.Val
= (EltTy
)nullptr;
110 TinyPtrVector(std::initializer_list
<EltTy
> IL
)
113 : IL
.size() == 1 ? PtrUnion(*IL
.begin())
114 : PtrUnion(new VecTy(IL
.begin(), IL
.end()))) {}
116 /// Constructor from an ArrayRef.
118 /// This also is a constructor for individual array elements due to the single
119 /// element constructor for ArrayRef.
120 explicit TinyPtrVector(ArrayRef
<EltTy
> Elts
)
125 : PtrUnion(new VecTy(Elts
.begin(), Elts
.end()))) {}
127 TinyPtrVector(size_t Count
, EltTy Value
)
128 : Val(Count
== 0 ? PtrUnion()
129 : Count
== 1 ? PtrUnion(Value
)
130 : PtrUnion(new VecTy(Count
, Value
))) {}
132 // implicit conversion operator to ArrayRef.
133 operator ArrayRef
<EltTy
>() const {
136 if (Val
.template is
<EltTy
>())
137 return *Val
.getAddrOfPtr1();
138 return *Val
.template get
<VecTy
*>();
141 // implicit conversion operator to MutableArrayRef.
142 operator MutableArrayRef
<EltTy
>() {
145 if (Val
.template is
<EltTy
>())
146 return *Val
.getAddrOfPtr1();
147 return *Val
.template get
<VecTy
*>();
150 // Implicit conversion to ArrayRef<U> if EltTy* implicitly converts to U*.
152 typename
std::enable_if
<
153 std::is_convertible
<ArrayRef
<EltTy
>, ArrayRef
<U
>>::value
,
155 operator ArrayRef
<U
>() const {
156 return operator ArrayRef
<EltTy
>();
160 // This vector can be empty if it contains no element, or if it
161 // contains a pointer to an empty vector.
162 if (Val
.isNull()) return true;
163 if (VecTy
*Vec
= Val
.template dyn_cast
<VecTy
*>())
168 unsigned size() const {
171 if (Val
.template is
<EltTy
>())
173 return Val
.template get
<VecTy
*>()->size();
176 using iterator
= EltTy
*;
177 using const_iterator
= const EltTy
*;
178 using reverse_iterator
= std::reverse_iterator
<iterator
>;
179 using const_reverse_iterator
= std::reverse_iterator
<const_iterator
>;
182 if (Val
.template is
<EltTy
>())
183 return Val
.getAddrOfPtr1();
185 return Val
.template get
<VecTy
*>()->begin();
189 if (Val
.template is
<EltTy
>())
190 return begin() + (Val
.isNull() ? 0 : 1);
192 return Val
.template get
<VecTy
*>()->end();
195 const_iterator
begin() const {
196 return (const_iterator
)const_cast<TinyPtrVector
*>(this)->begin();
199 const_iterator
end() const {
200 return (const_iterator
)const_cast<TinyPtrVector
*>(this)->end();
203 reverse_iterator
rbegin() { return reverse_iterator(end()); }
204 reverse_iterator
rend() { return reverse_iterator(begin()); }
206 const_reverse_iterator
rbegin() const {
207 return const_reverse_iterator(end());
210 const_reverse_iterator
rend() const {
211 return const_reverse_iterator(begin());
214 EltTy
operator[](unsigned i
) const {
215 assert(!Val
.isNull() && "can't index into an empty vector");
216 if (EltTy V
= Val
.template dyn_cast
<EltTy
>()) {
217 assert(i
== 0 && "tinyvector index out of range");
221 assert(i
< Val
.template get
<VecTy
*>()->size() &&
222 "tinyvector index out of range");
223 return (*Val
.template get
<VecTy
*>())[i
];
226 EltTy
front() const {
227 assert(!empty() && "vector empty");
228 if (EltTy V
= Val
.template dyn_cast
<EltTy
>())
230 return Val
.template get
<VecTy
*>()->front();
234 assert(!empty() && "vector empty");
235 if (EltTy V
= Val
.template dyn_cast
<EltTy
>())
237 return Val
.template get
<VecTy
*>()->back();
240 void push_back(EltTy NewVal
) {
241 assert(NewVal
&& "Can't add a null value");
243 // If we have nothing, add something.
249 // If we have a single value, convert to a vector.
250 if (EltTy V
= Val
.template dyn_cast
<EltTy
>()) {
252 Val
.template get
<VecTy
*>()->push_back(V
);
255 // Add the new value, we know we have a vector.
256 Val
.template get
<VecTy
*>()->push_back(NewVal
);
260 // If we have a single value, convert to empty.
261 if (Val
.template is
<EltTy
>())
262 Val
= (EltTy
)nullptr;
263 else if (VecTy
*Vec
= Val
.template get
<VecTy
*>())
268 // If we have a single value, convert to empty.
269 if (Val
.template is
<EltTy
>()) {
270 Val
= (EltTy
)nullptr;
271 } else if (VecTy
*Vec
= Val
.template dyn_cast
<VecTy
*>()) {
272 // If we have a vector form, just clear it.
275 // Otherwise, we're already empty.
278 iterator
erase(iterator I
) {
279 assert(I
>= begin() && "Iterator to erase is out of bounds.");
280 assert(I
< end() && "Erasing at past-the-end iterator.");
282 // If we have a single value, convert to empty.
283 if (Val
.template is
<EltTy
>()) {
285 Val
= (EltTy
)nullptr;
286 } else if (VecTy
*Vec
= Val
.template dyn_cast
<VecTy
*>()) {
287 // multiple items in a vector; just do the erase, there is no
288 // benefit to collapsing back to a pointer
289 return Vec
->erase(I
);
294 iterator
erase(iterator S
, iterator E
) {
295 assert(S
>= begin() && "Range to erase is out of bounds.");
296 assert(S
<= E
&& "Trying to erase invalid range.");
297 assert(E
<= end() && "Trying to erase past the end.");
299 if (Val
.template is
<EltTy
>()) {
300 if (S
== begin() && S
!= E
)
301 Val
= (EltTy
)nullptr;
302 } else if (VecTy
*Vec
= Val
.template dyn_cast
<VecTy
*>()) {
303 return Vec
->erase(S
, E
);
308 iterator
insert(iterator I
, const EltTy
&Elt
) {
309 assert(I
>= this->begin() && "Insertion iterator is out of bounds.");
310 assert(I
<= this->end() && "Inserting past the end of the vector.");
313 return std::prev(end());
315 assert(!Val
.isNull() && "Null value with non-end insert iterator.");
316 if (EltTy V
= Val
.template dyn_cast
<EltTy
>()) {
317 assert(I
== begin());
323 return Val
.template get
<VecTy
*>()->insert(I
, Elt
);
326 template<typename ItTy
>
327 iterator
insert(iterator I
, ItTy From
, ItTy To
) {
328 assert(I
>= this->begin() && "Insertion iterator is out of bounds.");
329 assert(I
<= this->end() && "Inserting past the end of the vector.");
333 // If we have a single value, convert to a vector.
334 ptrdiff_t Offset
= I
- begin();
336 if (std::next(From
) == To
) {
342 } else if (EltTy V
= Val
.template dyn_cast
<EltTy
>()) {
344 Val
.template get
<VecTy
*>()->push_back(V
);
346 return Val
.template get
<VecTy
*>()->insert(begin() + Offset
, From
, To
);
350 } // end namespace llvm
352 #endif // LLVM_ADT_TINYPTRVECTOR_H