14 #ifndef LLVM_ADT_SMALLVECTOR_H
15 #define LLVM_ADT_SMALLVECTOR_H
27 #include <initializer_list>
44 void grow_pod(
void *FirstEl,
size_t MinSizeInBytes,
size_t TSize);
65 template <
typename T,
typename =
void>
80 void grow_pod(
size_t MinSizeInBytes,
size_t TSize) {
87 return BeginX ==
static_cast<const void*
>(&FirstEl);
139 assert(idx <
size());
143 assert(idx <
size());
168 template <
typename T,
bool isPodLike>
183 template<
typename It1,
typename It2>
184 static It2
move(It1
I, It1 E, It2 Dest) {
185 for (; I != E; ++
I, ++Dest)
186 *Dest = ::std::move(*I);
194 template<
typename It1,
typename It2>
197 *--Dest = ::std::move(*--E);
203 template<
typename It1,
typename It2>
205 for (; I != E; ++
I, ++Dest)
206 ::
new ((
void*) &*Dest)
T(::std::move(*I));
211 template<
typename It1,
typename It2>
213 std::uninitialized_copy(I, E, Dest);
219 void grow(
size_t MinSize = 0);
225 ::new ((
void*) this->
end())
T(Elt);
232 ::new ((
void*) this->
end())
T(::std::move(Elt));
243 template <
typename T,
bool isPodLike>
245 size_t CurCapacity = this->capacity();
246 size_t CurSize = this->
size();
248 size_t NewCapacity = size_t(
NextPowerOf2(CurCapacity+2));
249 if (NewCapacity < MinSize)
250 NewCapacity = MinSize;
251 T *NewElts =
static_cast<T*
>(malloc(NewCapacity*
sizeof(
T)));
254 this->uninitialized_move(this->
begin(), this->
end(), NewElts);
257 destroy_range(this->
begin(), this->
end());
260 if (!this->isSmall())
263 this->setEnd(NewElts+CurSize);
264 this->BeginX = NewElts;
265 this->CapacityX = this->
begin()+NewCapacity;
271 template <
typename T>
281 template<
typename It1,
typename It2>
282 static It2
move(It1
I, It1 E, It2 Dest) {
283 return ::std::copy(I, E, Dest);
288 template<
typename It1,
typename It2>
290 return ::std::copy_backward(I, E, Dest);
295 template<
typename It1,
typename It2>
303 template<
typename It1,
typename It2>
306 std::uninitialized_copy(I, E, Dest);
311 template <
typename T1,
typename T2>
313 T1 *
I,
T1 *E, T2 *Dest,
314 typename std::enable_if<std::is_same<
typename std::remove_const<T1>::type,
315 T2>::value>::type * =
nullptr) {
321 memcpy(Dest, I, (E - I) *
sizeof(
T));
326 void grow(
size_t MinSize = 0) {
333 memcpy(this->
end(), &Elt,
sizeof(
T));
345 template <
typename T>
346 class SmallVectorImpl :
public SmallVectorTemplateBase<T, isPodLike<T>::value> {
347 typedef SmallVectorTemplateBase<T, isPodLike<T>::value >
SuperClass;
349 SmallVectorImpl(
const SmallVectorImpl&) =
delete;
377 if (N < this->
size()) {
380 }
else if (N > this->
size()) {
383 for (
auto I = this->
end(), E = this->
begin() + N;
I != E; ++
I)
390 if (N < this->
size()) {
393 }
else if (N > this->
size()) {
396 std::uninitialized_fill(this->
end(), this->
begin()+N, NV);
407 T Result = ::std::move(this->
back());
415 template<
typename in_iter>
416 void append(in_iter in_start, in_iter in_end) {
417 size_type NumInputs = std::distance(in_start, in_end);
434 std::uninitialized_fill_n(this->
end(), NumInputs, Elt);
438 void append(std::initializer_list<T> IL) {
439 append(IL.begin(), IL.end());
447 std::uninitialized_fill(this->
begin(), this->
end(), Elt);
450 void assign(std::initializer_list<T> IL) {
456 assert(I >= this->
begin() &&
"Iterator to erase is out of bounds.");
457 assert(I < this->
end() &&
"Erasing at past-the-end iterator.");
461 this->
move(I+1, this->
end(), I);
468 assert(S >= this->
begin() &&
"Range to erase is out of bounds.");
469 assert(S <= E &&
"Trying to erase invalid range.");
470 assert(E <= this->
end() &&
"Trying to erase past the end.");
482 if (I == this->
end()) {
484 return this->
end()-1;
487 assert(I >= this->
begin() &&
"Insertion iterator is out of bounds.");
488 assert(I <= this->
end() &&
"Inserting past the end of the vector.");
491 size_t EltNo = I-this->
begin();
493 I = this->
begin()+EltNo;
496 ::new ((
void*) this->
end())
T(::std::move(this->
back()));
504 if (I <= EltPtr && EltPtr < this->
EndX)
507 *I = ::std::move(*EltPtr);
512 if (I == this->
end()) {
514 return this->
end()-1;
517 assert(I >= this->
begin() &&
"Insertion iterator is out of bounds.");
518 assert(I <= this->
end() &&
"Inserting past the end of the vector.");
521 size_t EltNo = I-this->
begin();
523 I = this->
begin()+EltNo;
525 ::new ((
void*) this->
end())
T(std::move(this->
back()));
532 const T *EltPtr = &Elt;
533 if (I <= EltPtr && EltPtr < this->
EndX)
542 size_t InsertElt = I - this->
begin();
544 if (I == this->
end()) {
546 return this->
begin()+InsertElt;
549 assert(I >= this->
begin() &&
"Insertion iterator is out of bounds.");
550 assert(I <= this->
end() &&
"Inserting past the end of the vector.");
556 I = this->
begin()+InsertElt;
562 if (
size_t(this->
end()-I) >= NumToInsert) {
563 T *OldEnd = this->
end();
564 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
565 std::move_iterator<iterator>(this->
end()));
570 std::fill_n(I, NumToInsert, Elt);
578 T *OldEnd = this->
end();
580 size_t NumOverwritten = OldEnd-
I;
584 std::fill_n(I, NumOverwritten, Elt);
587 std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
591 template<
typename ItTy>
594 size_t InsertElt = I - this->
begin();
596 if (I == this->
end()) {
598 return this->
begin()+InsertElt;
601 assert(I >= this->
begin() &&
"Insertion iterator is out of bounds.");
602 assert(I <= this->
end() &&
"Inserting past the end of the vector.");
604 size_t NumToInsert = std::distance(From, To);
610 I = this->
begin()+InsertElt;
616 if (
size_t(this->
end()-I) >= NumToInsert) {
617 T *OldEnd = this->
end();
618 append(std::move_iterator<iterator>(this->
end() - NumToInsert),
619 std::move_iterator<iterator>(this->
end()));
624 std::copy(From, To, I);
632 T *OldEnd = this->
end();
634 size_t NumOverwritten = OldEnd-
I;
638 for (
T *J = I; NumOverwritten > 0; --NumOverwritten) {
649 insert(I, IL.begin(), IL.end());
652 template <
typename... ArgTypes>
void emplace_back(ArgTypes &&... Args) {
655 ::new ((
void *)this->
end())
T(std::forward<ArgTypes>(Args)...);
664 if (this->
size() != RHS.size())
return false;
668 return !(*
this == RHS);
672 return std::lexicographical_compare(this->
begin(), this->
end(),
673 RHS.begin(), RHS.end());
692 template <
typename T>
694 if (
this == &RHS)
return;
697 if (!this->isSmall() && !RHS.isSmall()) {
700 std::swap(this->CapacityX, RHS.CapacityX);
703 if (RHS.size() > this->capacity())
704 this->grow(RHS.size());
705 if (this->
size() > RHS.capacity())
706 RHS.grow(this->size());
709 size_t NumShared = this->
size();
710 if (NumShared > RHS.size()) NumShared = RHS.size();
711 for (
size_type i = 0; i != NumShared; ++i)
715 if (this->
size() > RHS.size()) {
716 size_t EltDiff = this->
size() - RHS.size();
717 this->uninitialized_copy(this->
begin()+NumShared, this->
end(), RHS.end());
718 RHS.setEnd(RHS.end()+EltDiff);
719 this->destroy_range(this->
begin()+NumShared, this->
end());
720 this->setEnd(this->
begin()+NumShared);
721 }
else if (RHS.size() > this->
size()) {
722 size_t EltDiff = RHS.size() - this->
size();
723 this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->
end());
724 this->setEnd(this->
end() + EltDiff);
725 this->destroy_range(RHS.begin()+NumShared, RHS.end());
726 RHS.setEnd(RHS.begin()+NumShared);
730 template <
typename T>
734 if (
this == &RHS)
return *
this;
738 size_t RHSSize = RHS.size();
739 size_t CurSize = this->
size();
740 if (CurSize >= RHSSize) {
744 NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->
begin());
746 NewEnd = this->
begin();
749 this->destroy_range(NewEnd, this->
end());
752 this->setEnd(NewEnd);
759 if (this->capacity() < RHSSize) {
761 this->destroy_range(this->
begin(), this->
end());
762 this->setEnd(this->
begin());
765 }
else if (CurSize) {
767 std::copy(RHS.begin(), RHS.begin()+CurSize, this->
begin());
771 this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
772 this->
begin()+CurSize);
775 this->setEnd(this->
begin()+RHSSize);
779 template <
typename T>
782 if (
this == &RHS)
return *
this;
785 if (!RHS.isSmall()) {
786 this->destroy_range(this->
begin(), this->
end());
787 if (!this->isSmall()) free(this->
begin());
788 this->BeginX = RHS.BeginX;
789 this->EndX = RHS.EndX;
790 this->CapacityX = RHS.CapacityX;
797 size_t RHSSize = RHS.size();
798 size_t CurSize = this->
size();
799 if (CurSize >= RHSSize) {
803 NewEnd = this->move(RHS.begin(), RHS.end(), NewEnd);
806 this->destroy_range(NewEnd, this->
end());
807 this->setEnd(NewEnd);
819 if (this->capacity() < RHSSize) {
821 this->destroy_range(this->
begin(), this->
end());
822 this->setEnd(this->
begin());
825 }
else if (CurSize) {
827 this->move(RHS.begin(), RHS.begin()+CurSize, this->
begin());
831 this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
832 this->
begin()+CurSize);
835 this->setEnd(this->
begin()+RHSSize);
845 template <
typename T,
unsigned N>
860 template <
typename T,
unsigned N>
873 template<
typename ItTy>
878 template <
typename RangeTy>
924 template<
typename T,
unsigned N>
940 template<
typename T,
unsigned N>
SuperClass::iterator iterator
std::reverse_iterator< iterator > reverse_iterator
void push_back(const T &Elt)
const_iterator end(StringRef path)
Get end iterator over path.
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
#define LLVM_ATTRIBUTE_UNUSED_RESULT
size_t capacity() const
Return the total number of elements in the currently allocated buffer.
#define LLVM_UNLIKELY(EXPR)
static It2 move_backward(It1 I, It1 E, It2 Dest)
Use move-assignment to move the range [I, E) onto the objects ending at "Dest", moving objects in rev...
static It2 move(It1 I, It1 E, It2 Dest)
Use move-assignment to move the range [I, E) onto the objects starting with "Dest".
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
const SmallVector & operator=(SmallVector &&RHS)
iterator insert(iterator I, const T &Elt)
iterator insert(iterator I, size_type NumToInsert, const T &Elt)
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) into the uninitialized memory starting with "Dest", constructing elements as ne...
const_iterator begin(StringRef path)
Get begin iterator over path.
void append(size_type NumInputs, const T &Elt)
Add the specified range to the end of the SmallVector.
size_t capacity_in_bytes() const
capacity_in_bytes - This returns capacity()*sizeof(T).
void reserve(size_type N)
const T & const_reference
static It2 move_backward(It1 I, It1 E, It2 Dest)
Use move-assignment to move the range [I, E) onto the objects ending at "Dest", moving objects in rev...
const_iterator end() const
SmallVectorTemplateBase(size_t Size)
static void uninitialized_copy(It1 I, It1 E, It2 Dest)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements as ne...
T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val()
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize(size_type N, const T &NV)
void assign(size_type NumElts, const T &Elt)
const_reverse_iterator rend() const
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
SmallVectorTemplateBase(size_t Size)
SmallVector(SmallVectorImpl< T > &&RHS)
const SmallVector & operator=(const SmallVector &RHS)
ptrdiff_t difference_type
SmallVector(SmallVector &&RHS)
SmallVectorTemplateBase<isPodLike = false> - This is where we put method implementations that are desig...
static It2 move(It1 I, It1 E, It2 Dest)
Use move-assignment to move the range [I, E) onto the objects starting with "Dest".
const_reference front() const
bool operator==(const SmallVectorImpl &RHS) const
void swap(SmallVectorImpl &RHS)
const_iterator begin() const
const_reference back() const
void grow(size_t MinSize=0)
Grow the allocated memory (without initializing new elements), doubling the size of the allocated mem...
reference operator[](size_type idx)
bool operator!=(const SmallVectorImpl &RHS) const
SmallVectorImpl(unsigned N)
bool operator<(const SmallVectorImpl &RHS) const
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
SmallVectorBase(void *FirstEl, size_t Size)
void assign(std::initializer_list< T > IL)
iterator erase(iterator S, iterator E)
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
uint64_t NextPowerOf2(uint64_t A)
NextPowerOf2 - Returns the next power of two (in 64-bits) that is strictly greater than A...
iterator erase(iterator I)
const_reference operator[](size_type idx) const
const_iterator capacity_ptr() const
isPodLike - This is a type trait that is used to determine whether a given type can be copied around ...
const SmallVector & operator=(SmallVectorImpl< T > &&RHS)
SmallVector(ItTy S, ItTy E)
static size_t capacity_in_bytes(const DenseMap< KeyT, ValueT, KeyInfoT > &X)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool isSmall() const
Return true if this is a smallvector which has not had dynamic memory allocated for it...
void grow(size_t MinSize=0)
Double the size of the allocated memory, guaranteeing space for at least one more element or MinSize ...
std::reverse_iterator< const_iterator > const_reverse_iterator
iterator insert(iterator I, ItTy From, ItTy To)
SmallVectorTemplateCommon< T >::U InlineElts[N-1]
SmallVector(std::initializer_list< T > IL)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
A range adaptor for a pair of iterators.
void append(std::initializer_list< T > IL)
SmallVectorImpl & operator=(const SmallVectorImpl &RHS)
iterator insert(iterator I, T &&Elt)
SuperClass::size_type size_type
void insert(iterator I, std::initializer_list< T > IL)
static void destroy_range(T *S, T *E)
This is the part of SmallVectorTemplateBase which does not depend on whether the type T is a POD...
void set_size(size_type N)
Set the array size to N, which the current array must have enough capacity for.
void emplace_back(ArgTypes &&...Args)
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest, typename std::enable_if< std::is_same< typename std::remove_const< T1 >::type, T2 >::value >::type *=nullptr)
Copy the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
This is all the non-templated stuff common to all SmallVectors.
size_t size_in_bytes() const
This returns size()*sizeof(T).
SmallVectorTemplateCommon(size_t Size)
SmallVector(const SmallVector &RHS)
reverse_iterator rbegin()
LLVM Value Representation.
static void uninitialized_move(It1 I, It1 E, It2 Dest)
Move the range [I, E) onto the uninitialized memory starting with "Dest", constructing elements into ...
void grow_pod(size_t MinSizeInBytes, size_t TSize)
static void destroy_range(T *, T *)
void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize)
This is an implementation of the grow() method which only works on POD-like data types and is out of ...
Storage for the SmallVector elements which aren't contained in SmallVectorTemplateCommon.
SmallVector(const llvm::iterator_range< RangeTy > R)
size_type max_size() const
const SmallVector & operator=(std::initializer_list< T > IL)
void resetToSmall()
Put this vector in a state of being small.
const_pointer data() const
Return a pointer to the vector's buffer, even if empty().
SmallVector(size_t Size, const T &Value=T())
const_reverse_iterator rbegin() const