LLVM API Documentation
00001 //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the SmallVector class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_ADT_SMALLVECTOR_H 00015 #define LLVM_ADT_SMALLVECTOR_H 00016 00017 #include "llvm/ADT/iterator.h" 00018 #include "llvm/Support/type_traits.h" 00019 #include <algorithm> 00020 #include <cstring> 00021 #include <memory> 00022 #include <cassert> 00023 00024 #ifdef _MSC_VER 00025 namespace std { 00026 #if _MSC_VER <= 1310 00027 // Work around flawed VC++ implementation of std::uninitialized_copy. Define 00028 // additional overloads so that elements with pointer types are recognized as 00029 // scalars and not objects, causing bizarre type conversion errors. 00030 template<class T1, class T2> 00031 inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { 00032 _Scalar_ptr_iterator_tag _Cat; 00033 return _Cat; 00034 } 00035 00036 template<class T1, class T2> 00037 inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { 00038 _Scalar_ptr_iterator_tag _Cat; 00039 return _Cat; 00040 } 00041 #else 00042 // FIXME: It is not clear if the problem is fixed in VS 2005. What is clear 00043 // is that the above hack won't work if it wasn't fixed. 00044 #endif 00045 } 00046 #endif 00047 00048 namespace llvm { 00049 00050 /// SmallVectorImpl - This class consists of common code factored out of the 00051 /// SmallVector class to reduce code duplication based on the SmallVector 'N' 00052 /// template parameter. 00053 template <typename T> 00054 class SmallVectorImpl { 00055 protected: 00056 T *Begin, *End, *Capacity; 00057 00058 // Allocate raw space for N elements of type T. If T has a ctor or dtor, we 00059 // don't want it to be automatically run, so we need to represent the space as 00060 // something else. An array of char would work great, but might not be 00061 // aligned sufficiently. Instead, we either use GCC extensions, or some 00062 // number of union instances for the space, which guarantee maximal alignment. 00063 protected: 00064 #ifdef __GNUC__ 00065 typedef char U; 00066 U FirstEl __attribute__((aligned)); 00067 #else 00068 union U { 00069 double D; 00070 long double LD; 00071 long long L; 00072 void *P; 00073 } FirstEl; 00074 #endif 00075 // Space after 'FirstEl' is clobbered, do not add any instance vars after it. 00076 public: 00077 // Default ctor - Initialize to empty. 00078 SmallVectorImpl(unsigned N) 00079 : Begin(reinterpret_cast<T*>(&FirstEl)), 00080 End(reinterpret_cast<T*>(&FirstEl)), 00081 Capacity(reinterpret_cast<T*>(&FirstEl)+N) { 00082 } 00083 00084 ~SmallVectorImpl() { 00085 // Destroy the constructed elements in the vector. 00086 destroy_range(Begin, End); 00087 00088 // If this wasn't grown from the inline copy, deallocate the old space. 00089 if (!isSmall()) 00090 operator delete(Begin); 00091 } 00092 00093 typedef size_t size_type; 00094 typedef ptrdiff_t difference_type; 00095 typedef T value_type; 00096 typedef T* iterator; 00097 typedef const T* const_iterator; 00098 00099 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00100 typedef std::reverse_iterator<iterator> reverse_iterator; 00101 00102 typedef T& reference; 00103 typedef const T& const_reference; 00104 typedef T* pointer; 00105 typedef const T* const_pointer; 00106 00107 bool empty() const { return Begin == End; } 00108 size_type size() const { return End-Begin; } 00109 size_type max_size() const { return size_type(-1) / sizeof(T); } 00110 00111 // forward iterator creation methods. 00112 iterator begin() { return Begin; } 00113 const_iterator begin() const { return Begin; } 00114 iterator end() { return End; } 00115 const_iterator end() const { return End; } 00116 00117 // reverse iterator creation methods. 00118 reverse_iterator rbegin() { return reverse_iterator(end()); } 00119 const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } 00120 reverse_iterator rend() { return reverse_iterator(begin()); } 00121 const_reverse_iterator rend() const { return const_reverse_iterator(begin());} 00122 00123 00124 /* These asserts could be "Begin + idx < End", but there are lots of places 00125 in llvm where we use &v[v.size()] instead of v.end(). */ 00126 reference operator[](unsigned idx) { 00127 assert (Begin + idx <= End); 00128 return Begin[idx]; 00129 } 00130 const_reference operator[](unsigned idx) const { 00131 assert (Begin + idx <= End); 00132 return Begin[idx]; 00133 } 00134 00135 reference front() { 00136 return begin()[0]; 00137 } 00138 const_reference front() const { 00139 return begin()[0]; 00140 } 00141 00142 reference back() { 00143 return end()[-1]; 00144 } 00145 const_reference back() const { 00146 return end()[-1]; 00147 } 00148 00149 void push_back(const_reference Elt) { 00150 if (End < Capacity) { 00151 Retry: 00152 new (End) T(Elt); 00153 ++End; 00154 return; 00155 } 00156 grow(); 00157 goto Retry; 00158 } 00159 00160 void pop_back() { 00161 --End; 00162 End->~T(); 00163 } 00164 00165 T pop_back_val() { 00166 T Result = back(); 00167 pop_back(); 00168 return Result; 00169 } 00170 00171 void clear() { 00172 destroy_range(Begin, End); 00173 End = Begin; 00174 } 00175 00176 void resize(unsigned N) { 00177 if (N < size()) { 00178 destroy_range(Begin+N, End); 00179 End = Begin+N; 00180 } else if (N > size()) { 00181 if (unsigned(Capacity-Begin) < N) 00182 grow(N); 00183 construct_range(End, Begin+N, T()); 00184 End = Begin+N; 00185 } 00186 } 00187 00188 void resize(unsigned N, const T &NV) { 00189 if (N < size()) { 00190 destroy_range(Begin+N, End); 00191 End = Begin+N; 00192 } else if (N > size()) { 00193 if (unsigned(Capacity-Begin) < N) 00194 grow(N); 00195 construct_range(End, Begin+N, NV); 00196 End = Begin+N; 00197 } 00198 } 00199 00200 void reserve(unsigned N) { 00201 if (unsigned(Capacity-Begin) < N) 00202 grow(N); 00203 } 00204 00205 void swap(SmallVectorImpl &RHS); 00206 00207 /// append - Add the specified range to the end of the SmallVector. 00208 /// 00209 template<typename in_iter> 00210 void append(in_iter in_start, in_iter in_end) { 00211 size_type NumInputs = std::distance(in_start, in_end); 00212 // Grow allocated space if needed. 00213 if (End+NumInputs > Capacity) 00214 grow(size()+NumInputs); 00215 00216 // Copy the new elements over. 00217 std::uninitialized_copy(in_start, in_end, End); 00218 End += NumInputs; 00219 } 00220 00221 /// append - Add the specified range to the end of the SmallVector. 00222 /// 00223 void append(size_type NumInputs, const T &Elt) { 00224 // Grow allocated space if needed. 00225 if (End+NumInputs > Capacity) 00226 grow(size()+NumInputs); 00227 00228 // Copy the new elements over. 00229 std::uninitialized_fill_n(End, NumInputs, Elt); 00230 End += NumInputs; 00231 } 00232 00233 void assign(unsigned NumElts, const T &Elt) { 00234 clear(); 00235 if (unsigned(Capacity-Begin) < NumElts) 00236 grow(NumElts); 00237 End = Begin+NumElts; 00238 construct_range(Begin, End, Elt); 00239 } 00240 00241 iterator erase(iterator I) { 00242 iterator N = I; 00243 // Shift all elts down one. 00244 std::copy(I+1, End, I); 00245 // Drop the last elt. 00246 pop_back(); 00247 return(N); 00248 } 00249 00250 iterator erase(iterator S, iterator E) { 00251 iterator N = S; 00252 // Shift all elts down. 00253 iterator I = std::copy(E, End, S); 00254 // Drop the last elts. 00255 destroy_range(I, End); 00256 End = I; 00257 return(N); 00258 } 00259 00260 iterator insert(iterator I, const T &Elt) { 00261 if (I == End) { // Important special case for empty vector. 00262 push_back(Elt); 00263 return end()-1; 00264 } 00265 00266 if (End < Capacity) { 00267 Retry: 00268 new (End) T(back()); 00269 ++End; 00270 // Push everything else over. 00271 std::copy_backward(I, End-1, End); 00272 *I = Elt; 00273 return I; 00274 } 00275 size_t EltNo = I-Begin; 00276 grow(); 00277 I = Begin+EltNo; 00278 goto Retry; 00279 } 00280 00281 iterator insert(iterator I, size_type NumToInsert, const T &Elt) { 00282 if (I == End) { // Important special case for empty vector. 00283 append(NumToInsert, Elt); 00284 return end()-1; 00285 } 00286 00287 // Convert iterator to elt# to avoid invalidating iterator when we reserve() 00288 size_t InsertElt = I-begin(); 00289 00290 // Ensure there is enough space. 00291 reserve(static_cast<unsigned>(size() + NumToInsert)); 00292 00293 // Uninvalidate the iterator. 00294 I = begin()+InsertElt; 00295 00296 // If we already have this many elements in the collection, append the 00297 // dest elements at the end, then copy over the appropriate elements. Since 00298 // we already reserved space, we know that this won't reallocate the vector. 00299 if (size() >= NumToInsert) { 00300 T *OldEnd = End; 00301 append(End-NumToInsert, End); 00302 00303 // Copy the existing elements that get replaced. 00304 std::copy(I, OldEnd-NumToInsert, I+NumToInsert); 00305 00306 std::fill_n(I, NumToInsert, Elt); 00307 return I; 00308 } 00309 00310 // Otherwise, we're inserting more elements than exist already, and we're 00311 // not inserting at the end. 00312 00313 // Copy over the elements that we're about to overwrite. 00314 T *OldEnd = End; 00315 End += NumToInsert; 00316 size_t NumOverwritten = OldEnd-I; 00317 std::uninitialized_copy(I, OldEnd, End-NumOverwritten); 00318 00319 // Replace the overwritten part. 00320 std::fill_n(I, NumOverwritten, Elt); 00321 00322 // Insert the non-overwritten middle part. 00323 std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); 00324 return I; 00325 } 00326 00327 template<typename ItTy> 00328 iterator insert(iterator I, ItTy From, ItTy To) { 00329 if (I == End) { // Important special case for empty vector. 00330 append(From, To); 00331 return end()-1; 00332 } 00333 00334 size_t NumToInsert = std::distance(From, To); 00335 // Convert iterator to elt# to avoid invalidating iterator when we reserve() 00336 size_t InsertElt = I-begin(); 00337 00338 // Ensure there is enough space. 00339 reserve(static_cast<unsigned>(size() + NumToInsert)); 00340 00341 // Uninvalidate the iterator. 00342 I = begin()+InsertElt; 00343 00344 // If we already have this many elements in the collection, append the 00345 // dest elements at the end, then copy over the appropriate elements. Since 00346 // we already reserved space, we know that this won't reallocate the vector. 00347 if (size() >= NumToInsert) { 00348 T *OldEnd = End; 00349 append(End-NumToInsert, End); 00350 00351 // Copy the existing elements that get replaced. 00352 std::copy(I, OldEnd-NumToInsert, I+NumToInsert); 00353 00354 std::copy(From, To, I); 00355 return I; 00356 } 00357 00358 // Otherwise, we're inserting more elements than exist already, and we're 00359 // not inserting at the end. 00360 00361 // Copy over the elements that we're about to overwrite. 00362 T *OldEnd = End; 00363 End += NumToInsert; 00364 size_t NumOverwritten = OldEnd-I; 00365 std::uninitialized_copy(I, OldEnd, End-NumOverwritten); 00366 00367 // Replace the overwritten part. 00368 std::copy(From, From+NumOverwritten, I); 00369 00370 // Insert the non-overwritten middle part. 00371 std::uninitialized_copy(From+NumOverwritten, To, OldEnd); 00372 return I; 00373 } 00374 00375 const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); 00376 00377 bool operator==(const SmallVectorImpl &RHS) const { 00378 if (size() != RHS.size()) return false; 00379 for (T *This = Begin, *That = RHS.Begin, *E = Begin+size(); 00380 This != E; ++This, ++That) 00381 if (*This != *That) 00382 return false; 00383 return true; 00384 } 00385 bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } 00386 00387 bool operator<(const SmallVectorImpl &RHS) const { 00388 return std::lexicographical_compare(begin(), end(), 00389 RHS.begin(), RHS.end()); 00390 } 00391 00392 private: 00393 /// isSmall - Return true if this is a smallvector which has not had dynamic 00394 /// memory allocated for it. 00395 bool isSmall() const { 00396 return static_cast<const void*>(Begin) == 00397 static_cast<const void*>(&FirstEl); 00398 } 00399 00400 /// grow - double the size of the allocated memory, guaranteeing space for at 00401 /// least one more element or MinSize if specified. 00402 void grow(size_type MinSize = 0); 00403 00404 void construct_range(T *S, T *E, const T &Elt) { 00405 for (; S != E; ++S) 00406 new (S) T(Elt); 00407 } 00408 00409 void destroy_range(T *S, T *E) { 00410 while (S != E) { 00411 --E; 00412 E->~T(); 00413 } 00414 } 00415 }; 00416 00417 // Define this out-of-line to dissuade the C++ compiler from inlining it. 00418 template <typename T> 00419 void SmallVectorImpl<T>::grow(size_t MinSize) { 00420 size_t CurCapacity = Capacity-Begin; 00421 size_t CurSize = size(); 00422 size_t NewCapacity = 2*CurCapacity; 00423 if (NewCapacity < MinSize) 00424 NewCapacity = MinSize; 00425 T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T))); 00426 00427 // Copy the elements over. 00428 if (is_class<T>::value) 00429 std::uninitialized_copy(Begin, End, NewElts); 00430 else 00431 // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). 00432 memcpy(NewElts, Begin, CurSize * sizeof(T)); 00433 00434 // Destroy the original elements. 00435 destroy_range(Begin, End); 00436 00437 // If this wasn't grown from the inline copy, deallocate the old space. 00438 if (!isSmall()) 00439 operator delete(Begin); 00440 00441 Begin = NewElts; 00442 End = NewElts+CurSize; 00443 Capacity = Begin+NewCapacity; 00444 } 00445 00446 template <typename T> 00447 void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { 00448 if (this == &RHS) return; 00449 00450 // We can only avoid copying elements if neither vector is small. 00451 if (!isSmall() && !RHS.isSmall()) { 00452 std::swap(Begin, RHS.Begin); 00453 std::swap(End, RHS.End); 00454 std::swap(Capacity, RHS.Capacity); 00455 return; 00456 } 00457 if (Begin+RHS.size() > Capacity) 00458 grow(RHS.size()); 00459 if (RHS.begin()+size() > RHS.Capacity) 00460 RHS.grow(size()); 00461 00462 // Swap the shared elements. 00463 size_t NumShared = size(); 00464 if (NumShared > RHS.size()) NumShared = RHS.size(); 00465 for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i) 00466 std::swap(Begin[i], RHS[i]); 00467 00468 // Copy over the extra elts. 00469 if (size() > RHS.size()) { 00470 size_t EltDiff = size() - RHS.size(); 00471 std::uninitialized_copy(Begin+NumShared, End, RHS.End); 00472 RHS.End += EltDiff; 00473 destroy_range(Begin+NumShared, End); 00474 End = Begin+NumShared; 00475 } else if (RHS.size() > size()) { 00476 size_t EltDiff = RHS.size() - size(); 00477 std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End); 00478 End += EltDiff; 00479 destroy_range(RHS.Begin+NumShared, RHS.End); 00480 RHS.End = RHS.Begin+NumShared; 00481 } 00482 } 00483 00484 template <typename T> 00485 const SmallVectorImpl<T> & 00486 SmallVectorImpl<T>::operator=(const SmallVectorImpl<T> &RHS) { 00487 // Avoid self-assignment. 00488 if (this == &RHS) return *this; 00489 00490 // If we already have sufficient space, assign the common elements, then 00491 // destroy any excess. 00492 unsigned RHSSize = unsigned(RHS.size()); 00493 unsigned CurSize = unsigned(size()); 00494 if (CurSize >= RHSSize) { 00495 // Assign common elements. 00496 iterator NewEnd; 00497 if (RHSSize) 00498 NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); 00499 else 00500 NewEnd = Begin; 00501 00502 // Destroy excess elements. 00503 destroy_range(NewEnd, End); 00504 00505 // Trim. 00506 End = NewEnd; 00507 return *this; 00508 } 00509 00510 // If we have to grow to have enough elements, destroy the current elements. 00511 // This allows us to avoid copying them during the grow. 00512 if (unsigned(Capacity-Begin) < RHSSize) { 00513 // Destroy current elements. 00514 destroy_range(Begin, End); 00515 End = Begin; 00516 CurSize = 0; 00517 grow(RHSSize); 00518 } else if (CurSize) { 00519 // Otherwise, use assignment for the already-constructed elements. 00520 std::copy(RHS.Begin, RHS.Begin+CurSize, Begin); 00521 } 00522 00523 // Copy construct the new elements in place. 00524 std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize); 00525 00526 // Set end. 00527 End = Begin+RHSSize; 00528 return *this; 00529 } 00530 00531 /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized 00532 /// for the case when the array is small. It contains some number of elements 00533 /// in-place, which allows it to avoid heap allocation when the actual number of 00534 /// elements is below that threshold. This allows normal "small" cases to be 00535 /// fast without losing generality for large inputs. 00536 /// 00537 /// Note that this does not attempt to be exception safe. 00538 /// 00539 template <typename T, unsigned N> 00540 class SmallVector : public SmallVectorImpl<T> { 00541 /// InlineElts - These are 'N-1' elements that are stored inline in the body 00542 /// of the vector. The extra '1' element is stored in SmallVectorImpl. 00543 typedef typename SmallVectorImpl<T>::U U; 00544 enum { 00545 // MinUs - The number of U's require to cover N T's. 00546 MinUs = (static_cast<unsigned int>(sizeof(T))*N + 00547 static_cast<unsigned int>(sizeof(U)) - 1) / 00548 static_cast<unsigned int>(sizeof(U)), 00549 00550 // NumInlineEltsElts - The number of elements actually in this array. There 00551 // is already one in the parent class, and we have to round up to avoid 00552 // having a zero-element array. 00553 NumInlineEltsElts = MinUs > 1 ? (MinUs - 1) : 1, 00554 00555 // NumTsAvailable - The number of T's we actually have space for, which may 00556 // be more than N due to rounding. 00557 NumTsAvailable = (NumInlineEltsElts+1)*static_cast<unsigned int>(sizeof(U))/ 00558 static_cast<unsigned int>(sizeof(T)) 00559 }; 00560 U InlineElts[NumInlineEltsElts]; 00561 public: 00562 SmallVector() : SmallVectorImpl<T>(NumTsAvailable) { 00563 } 00564 00565 explicit SmallVector(unsigned Size, const T &Value = T()) 00566 : SmallVectorImpl<T>(NumTsAvailable) { 00567 this->reserve(Size); 00568 while (Size--) 00569 this->push_back(Value); 00570 } 00571 00572 template<typename ItTy> 00573 SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) { 00574 this->append(S, E); 00575 } 00576 00577 SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) { 00578 if (!RHS.empty()) 00579 SmallVectorImpl<T>::operator=(RHS); 00580 } 00581 00582 const SmallVector &operator=(const SmallVector &RHS) { 00583 SmallVectorImpl<T>::operator=(RHS); 00584 return *this; 00585 } 00586 00587 }; 00588 00589 } // End llvm namespace 00590 00591 namespace std { 00592 /// Implement std::swap in terms of SmallVector swap. 00593 template<typename T> 00594 inline void 00595 swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { 00596 LHS.swap(RHS); 00597 } 00598 00599 /// Implement std::swap in terms of SmallVector swap. 00600 template<typename T, unsigned N> 00601 inline void 00602 swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { 00603 LHS.swap(RHS); 00604 } 00605 } 00606 00607 #endif
This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.