//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the SmallVector class. /// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H #include "llvm/Support/Compiler.h" #include <algorithm> #include <cassert> #include <cstddef> #include <cstdint> #include <cstdlib> #include <cstring> #include <functional> #include <initializer_list> #include <iterator> #include <limits> #include <memory> #include <new> #include <type_traits> #include <utility> namespace llvm { template <typename T> class ArrayRef; template <typename IteratorT> class iterator_range; EnableIfConvertibleToInputIterator; /// This is all the stuff common to all SmallVectors. /// /// The template parameter specifies the type which should be used to hold the /// Size and Capacity of the SmallVector, so it can be adjusted. /// Using 32 bit size is desirable to shrink the size of the SmallVector. /// Using 64 bit size is desirable for cases like SmallVector<char>, where a /// 32 bit size would limit the vector to ~4GB. SmallVectors are used for /// buffering bitcode output - which can exceed 4GB. template <class Size_T> class SmallVectorBase { … }; SmallVectorSizeType; /// Figure out the offset of the first element. template <class T, typename = void> struct SmallVectorAlignmentAndSize { … }; /// This is the part of SmallVectorTemplateBase which does not depend on whether /// the type T is a POD. The extra dummy template argument is used by ArrayRef /// to avoid unnecessarily requiring T to be complete. template <typename T, typename = void> class SmallVectorTemplateCommon : public SmallVectorBase<SmallVectorSizeType<T>> { … }; /// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put /// method implementations that are designed to work with non-trivial T's. /// /// We approximate is_trivially_copyable with trivial move/copy construction and /// trivial destruction. While the standard doesn't specify that you're allowed /// copy these types with memcpy, there is no way for the type to observe this. /// This catches the important case of std::pair<POD, POD>, which is not /// trivially assignable. template <typename T, bool = (std::is_trivially_copy_constructible<T>::value) && (std::is_trivially_move_constructible<T>::value) && std::is_trivially_destructible<T>::value> class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { … }; // Define this out-of-line to dissuade the C++ compiler from inlining it. template <typename T, bool TriviallyCopyable> void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) { … } template <typename T, bool TriviallyCopyable> T *SmallVectorTemplateBase<T, TriviallyCopyable>::mallocForGrow( size_t MinSize, size_t &NewCapacity) { … } // Define this out-of-line to dissuade the C++ compiler from inlining it. template <typename T, bool TriviallyCopyable> void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow( T *NewElts) { … } // Define this out-of-line to dissuade the C++ compiler from inlining it. template <typename T, bool TriviallyCopyable> void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow( T *NewElts, size_t NewCapacity) { … } /// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put /// method implementations that are designed to work with trivially copyable /// T's. This allows using memcpy in place of copy/move construction and /// skipping destruction. SmallVectorTemplateBase<T, true>; /// This class consists of common code factored out of the SmallVector class to /// reduce code duplication based on the SmallVector 'N' template parameter. template <typename T> class SmallVectorImpl : public SmallVectorTemplateBase<T> { … }; template <typename T> void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { … } template <typename T> SmallVectorImpl<T> &SmallVectorImpl<T>:: operator=(const SmallVectorImpl<T> &RHS) { … } template <typename T> SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { … } /// Storage for the SmallVector elements. This is specialized for the N=0 case /// to avoid allocating unnecessary storage. template <typename T, unsigned N> struct SmallVectorStorage { … }; /// We need the storage to be properly aligned even for small-size of 0 so that /// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is /// well-defined. SmallVectorStorage<T, 0>; /// Forward declaration of SmallVector so that /// calculateSmallVectorDefaultInlinedElements can reference /// `sizeof(SmallVector<T, 0>)`. template <typename T, unsigned N> class LLVM_GSL_OWNER SmallVector; /// Helper class for calculating the default number of inline elements for /// `SmallVector<T>`. /// /// This should be migrated to a constexpr function when our minimum /// compiler support is enough for multi-statement constexpr functions. template <typename T> struct CalculateSmallVectorDefaultInlinedElements { … }; /// This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements /// in-place, which allows it to avoid heap allocation when the actual number of /// elements is below that threshold. This allows normal "small" cases to be /// fast without losing generality for large inputs. /// /// \note /// In the absence of a well-motivated choice for the number of inlined /// elements \p N, it is recommended to use \c SmallVector<T> (that is, /// omitting the \p N). This will choose a default number of inlined elements /// reasonable for allocation on the stack (for example, trying to keep \c /// sizeof(SmallVector<T>) around 64 bytes). /// /// \warning This does not attempt to be exception safe. /// /// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h template <typename T, unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value> class LLVM_GSL_OWNER SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> { … }; template <typename T, unsigned N> inline size_t capacity_in_bytes(const SmallVector<T, N> &X) { … } ValueTypeFromRangeType; /// Given a range of type R, iterate the entire range and return a /// SmallVector with elements of the vector. This is useful, for example, /// when you want to iterate a range and then sort the results. template <unsigned Size, typename R> SmallVector<ValueTypeFromRangeType<R>, Size> to_vector(R &&Range) { … } template <typename R> SmallVector<ValueTypeFromRangeType<R>> to_vector(R &&Range) { … } template <typename Out, unsigned Size, typename R> SmallVector<Out, Size> to_vector_of(R &&Range) { … } template <typename Out, typename R> SmallVector<Out> to_vector_of(R &&Range) { … } // Explicit instantiations extern template class llvm::SmallVectorBase<uint32_t>; #if SIZE_MAX > UINT32_MAX extern template class llvm::SmallVectorBase<uint64_t>; #endif } // end namespace llvm namespace std { /// Implement std::swap in terms of SmallVector swap. template<typename T> inline void swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { … } /// Implement std::swap in terms of SmallVector swap. template<typename T, unsigned N> inline void swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { … } } // end namespace std #endif // LLVM_ADT_SMALLVECTOR_H