9f2842a63890c960b716b2afebc41544f2e8824b
[oota-llvm.git] / include / llvm / ADT / SmallVector.h
1 //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the SmallVector class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_SMALLVECTOR_H
15 #define LLVM_ADT_SMALLVECTOR_H
16
17 #include <algorithm>
18 #include <iterator>
19 #include <memory>
20
21 #ifdef _MSC_VER
22 namespace std {
23   // Fix bug in VC++ implementation of std::uninitialized_copy.  Define
24   // additional overloads so that the copy is recognized as a scalar and
25   // not an object copy.
26   template<class T1, class T2>
27   inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
28           _Scalar_ptr_iterator_tag _Cat;
29           return _Cat;
30   }
31
32   template<class T1, class T2>
33   inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
34           _Scalar_ptr_iterator_tag _Cat;
35           return _Cat;
36   }
37 }
38 #endif
39
40 namespace llvm {
41
42 /// SmallVectorImpl - This class consists of common code factored out of the
43 /// SmallVector class to reduce code duplication based on the SmallVector 'N'
44 /// template parameter.
45 template <typename T>
46 class SmallVectorImpl {
47 protected:
48   T *Begin, *End, *Capacity;
49   
50   // Allocate raw space for N elements of type T.  If T has a ctor or dtor, we
51   // don't want it to be automatically run, so we need to represent the space as
52   // something else.  An array of char would work great, but might not be
53   // aligned sufficiently.  Instead, we either use GCC extensions, or some
54   // number of union instances for the space, which guarantee maximal alignment.
55 protected:
56 #ifdef __GNUC__
57   typedef char U;
58   U FirstEl __attribute__((aligned));
59 #else
60   union U {
61     double D;
62     long double LD;
63     long long L;
64     void *P;
65   } FirstEl;
66 #endif
67   // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
68 public:
69   // Default ctor - Initialize to empty.
70   SmallVectorImpl(unsigned N)
71     : Begin((T*)&FirstEl), End((T*)&FirstEl), Capacity((T*)&FirstEl+N) {
72   }
73   
74   ~SmallVectorImpl() {
75     // Destroy the constructed elements in the vector.
76     destroy_range(Begin, End);
77
78     // If this wasn't grown from the inline copy, deallocate the old space.
79     if (!isSmall())
80       delete[] (char*)Begin;
81   }
82   
83   typedef size_t size_type;
84   typedef T* iterator;
85   typedef const T* const_iterator;
86   typedef T& reference;
87   typedef const T& const_reference;
88
89   bool empty() const { return Begin == End; }
90   size_type size() const { return End-Begin; }
91   
92   iterator begin() { return Begin; }
93   const_iterator begin() const { return Begin; }
94
95   iterator end() { return End; }
96   const_iterator end() const { return End; }
97   
98   reference operator[](unsigned idx) {
99     return Begin[idx];
100   }
101   const_reference operator[](unsigned idx) const {
102     return Begin[idx];
103   }
104   
105   reference front() {
106     return begin()[0];
107   }
108   const_reference front() const {
109     return begin()[0];
110   }
111   
112   reference back() {
113     return end()[-1];
114   }
115   const_reference back() const {
116     return end()[-1];
117   }
118   
119   void push_back(const_reference Elt) {
120     if (End < Capacity) {
121   Retry:
122       new (End) T(Elt);
123       ++End;
124       return;
125     }
126     grow();
127     goto Retry;
128   }
129   
130   void pop_back() {
131     --End;
132     End->~T();
133   }
134   
135   void clear() {
136     destroy_range(Begin, End);
137     End = Begin;
138   }
139   
140   void resize(unsigned N) {
141     if (N < size()) {
142       destroy_range(Begin+N, End);
143       End = Begin+N;
144     } else if (N > size()) {
145       if (Begin+N > Capacity)
146         grow(N);
147       construct_range(End, Begin+N, T());
148       End = Begin+N;
149     }
150   }
151   
152   void resize(unsigned N, const T &NV) {
153     if (N < size()) {
154       destroy_range(Begin+N, End);
155       End = Begin+N;
156     } else if (N > size()) {
157       if (Begin+N > Capacity)
158         grow(N);
159       construct_range(End, Begin+N, NV);
160       End = Begin+N;
161     }
162   }
163   
164   void reserve(unsigned N) {
165     if (unsigned(Capacity-Begin) < N)
166       grow(N);
167   }
168   
169   void swap(SmallVectorImpl &RHS);
170   
171   /// append - Add the specified range to the end of the SmallVector.
172   ///
173   template<typename in_iter>
174   void append(in_iter in_start, in_iter in_end) {
175     unsigned NumInputs = std::distance(in_start, in_end);
176     // Grow allocated space if needed.
177     if (End+NumInputs > Capacity)
178       grow(size()+NumInputs);
179
180     // Copy the new elements over.
181     std::uninitialized_copy(in_start, in_end, End);
182     End += NumInputs;
183   }
184   
185   void assign(unsigned NumElts, const T &Elt) {
186     clear();
187     if (Begin+NumElts > Capacity)
188       grow(NumElts);
189     End = Begin+NumElts;
190     construct_range(Begin, End, Elt);
191   }
192   
193   void erase(iterator I) {
194     // Shift all elts down one.
195     std::copy(I+1, End, I);
196     // Drop the last elt.
197     pop_back();
198   }
199   
200   void erase(iterator S, iterator E) {
201     // Shift all elts down.
202     iterator I = std::copy(E, End, S);
203     // Drop the last elts.
204     destroy_range(I, End);
205     End = I;
206   }
207   
208   iterator insert(iterator I, const T &Elt) {
209     if (I == End) {  // Important special case for empty vector.
210       push_back(Elt);
211       return end()-1;
212     }
213     
214     if (End < Capacity) {
215   Retry:
216       new (End) T(back());
217       ++End;
218       // Push everything else over.
219       std::copy_backward(I, End-1, End);
220       *I = Elt;
221       return I;
222     }
223     unsigned EltNo = I-Begin;
224     grow();
225     I = Begin+EltNo;
226     goto Retry;
227   }
228   
229   template<typename ItTy>
230   iterator insert(iterator I, ItTy From, ItTy To) {
231     if (I == End) {  // Important special case for empty vector.
232       append(From, To);
233       return end()-1;
234     }
235     
236     unsigned NumToInsert = std::distance(From, To);
237     // Convert iterator to elt# to avoid invalidating iterator when we reserve()
238     unsigned InsertElt = I-begin();
239     
240     // Ensure there is enough space.
241     reserve(size() + NumToInsert);
242     
243     // Uninvalidate the iterator.
244     I = begin()+InsertElt;
245     
246     // If we already have this many elements in the collection, append the
247     // dest elements at the end, then copy over the appropriate elements.  Since
248     // we already reserved space, we know that this won't reallocate the vector.
249     if (size() >= NumToInsert) {
250       T *OldEnd = End;
251       append(End-NumToInsert, End);
252       
253       // Copy the existing elements that get replaced.
254       std::copy(I, OldEnd-NumToInsert, I+NumToInsert);
255       
256       std::copy(From, To, I);
257       return I;
258     }
259
260     // Otherwise, we're inserting more elements than exist already, and we're
261     // not inserting at the end.
262     
263     // Copy over the elements that we're about to overwrite.
264     T *OldEnd = End;
265     End += NumToInsert;
266     unsigned NumOverwritten = OldEnd-I;
267     std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
268     
269     // Replace the overwritten part.
270     std::copy(From, From+NumOverwritten, I);
271     
272     // Insert the non-overwritten middle part.
273     std::uninitialized_copy(From+NumOverwritten, To, OldEnd);
274     return I;
275   }
276   
277   const SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
278   
279 private:
280   /// isSmall - Return true if this is a smallvector which has not had dynamic
281   /// memory allocated for it.
282   bool isSmall() const {
283     return (void*)Begin == (void*)&FirstEl;
284   }
285
286   /// grow - double the size of the allocated memory, guaranteeing space for at
287   /// least one more element or MinSize if specified.
288   void grow(unsigned MinSize = 0);
289
290   void construct_range(T *S, T *E, const T &Elt) {
291     for (; S != E; ++S)
292       new (S) T(Elt);
293   }
294   
295   void destroy_range(T *S, T *E) {
296     while (S != E) {
297       --E;
298       E->~T();
299     }
300   }
301 };
302
303 // Define this out-of-line to dissuade the C++ compiler from inlining it.
304 template <typename T>
305 void SmallVectorImpl<T>::grow(unsigned MinSize) {
306   unsigned CurCapacity = Capacity-Begin;
307   unsigned CurSize = size();
308   unsigned NewCapacity = 2*CurCapacity;
309   if (NewCapacity < MinSize)
310     NewCapacity = MinSize;
311   T *NewElts = reinterpret_cast<T*>(new char[NewCapacity*sizeof(T)]);
312   
313   // Copy the elements over.
314   std::uninitialized_copy(Begin, End, NewElts);
315   
316   // Destroy the original elements.
317   destroy_range(Begin, End);
318   
319   // If this wasn't grown from the inline copy, deallocate the old space.
320   if (!isSmall())
321     delete[] (char*)Begin;
322   
323   Begin = NewElts;
324   End = NewElts+CurSize;
325   Capacity = Begin+NewCapacity;
326 }
327
328 template <typename T>
329 void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
330   if (this == &RHS) return;
331   
332   // We can only avoid copying elements if neither vector is small.
333   if (!isSmall() && !RHS.isSmall()) {
334     std::swap(Begin, RHS.Begin);
335     std::swap(End, RHS.End);
336     std::swap(Capacity, RHS.Capacity);
337     return;
338   }
339   if (Begin+RHS.size() > Capacity)
340     grow(RHS.size());
341   if (RHS.begin()+size() > RHS.Capacity)
342     RHS.grow(size());
343   
344   // Swap the shared elements.
345   unsigned NumShared = size();
346   if (NumShared > RHS.size()) NumShared = RHS.size();
347   for (unsigned i = 0; i != NumShared; ++i)
348     std::swap(Begin[i], RHS[i]);
349   
350   // Copy over the extra elts.
351   if (size() > RHS.size()) {
352     unsigned EltDiff = size() - RHS.size();
353     std::uninitialized_copy(Begin+NumShared, End, RHS.End);
354     RHS.End += EltDiff;
355     destroy_range(Begin+NumShared, End);
356     End = Begin+NumShared;
357   } else if (RHS.size() > size()) {
358     unsigned EltDiff = RHS.size() - size();
359     std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End);
360     End += EltDiff;
361     destroy_range(RHS.Begin+NumShared, RHS.End);
362     RHS.End = RHS.Begin+NumShared;
363   }
364 }
365   
366 template <typename T>
367 const SmallVectorImpl<T> &
368 SmallVectorImpl<T>::operator=(const SmallVectorImpl<T> &RHS) {
369   // Avoid self-assignment.
370   if (this == &RHS) return *this;
371   
372   // If we already have sufficient space, assign the common elements, then
373   // destroy any excess.
374   unsigned RHSSize = RHS.size();
375   unsigned CurSize = size();
376   if (CurSize >= RHSSize) {
377     // Assign common elements.
378     iterator NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin);
379     
380     // Destroy excess elements.
381     destroy_range(NewEnd, End);
382     
383     // Trim.
384     End = NewEnd;
385     return *this;
386   }
387   
388   // If we have to grow to have enough elements, destroy the current elements.
389   // This allows us to avoid copying them during the grow.
390   if (unsigned(Capacity-Begin) < RHSSize) {
391     // Destroy current elements.
392     destroy_range(Begin, End);
393     End = Begin;
394     CurSize = 0;
395     grow(RHSSize);
396   } else if (CurSize) {
397     // Otherwise, use assignment for the already-constructed elements.
398     std::copy(RHS.Begin, RHS.Begin+CurSize, Begin);
399   }
400   
401   // Copy construct the new elements in place.
402   std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize);
403   
404   // Set end.
405   End = Begin+RHSSize;
406   return *this;
407 }
408   
409 /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized
410 /// for the case when the array is small.  It contains some number of elements
411 /// in-place, which allows it to avoid heap allocation when the actual number of
412 /// elements is below that threshold.  This allows normal "small" cases to be
413 /// fast without losing generality for large inputs.
414 ///
415 /// Note that this does not attempt to be exception safe.
416 ///
417 template <typename T, unsigned N>
418 class SmallVector : public SmallVectorImpl<T> {
419   /// InlineElts - These are 'N-1' elements that are stored inline in the body
420   /// of the vector.  The extra '1' element is stored in SmallVectorImpl.
421   typedef typename SmallVectorImpl<T>::U U;
422   enum {
423     // MinUs - The number of U's require to cover N T's.
424     MinUs = (sizeof(T)*N+sizeof(U)-1)/sizeof(U),
425     
426     // NumInlineEltsElts - The number of elements actually in this array.  There
427     // is already one in the parent class, and we have to round up to avoid
428     // having a zero-element array.
429     NumInlineEltsElts = (MinUs - 1) > 0 ? (MinUs - 1) : 1,
430     
431     // NumTsAvailable - The number of T's we actually have space for, which may
432     // be more than N due to rounding.
433     NumTsAvailable = (NumInlineEltsElts+1)*sizeof(U) / sizeof(T)
434   };
435   U InlineElts[NumInlineEltsElts];
436 public:  
437   SmallVector() : SmallVectorImpl<T>(NumTsAvailable) {
438   }
439   
440   SmallVector(unsigned Size, const T &Value)
441     : SmallVectorImpl<T>(NumTsAvailable) {
442     this->reserve(Size);
443     while (Size--)
444       push_back(Value);
445   }
446   
447   template<typename ItTy>
448   SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) {
449     append(S, E);
450   }
451   
452   SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) {
453     operator=(RHS);
454   }
455   
456   const SmallVector &operator=(const SmallVector &RHS) {
457     SmallVectorImpl<T>::operator=(RHS);
458     return *this;
459   }
460 };
461
462 } // End llvm namespace
463
464 namespace std {
465   /// Implement std::swap in terms of SmallVector swap.
466   template<typename T>
467   inline void
468   swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
469     LHS.swap(RHS);
470   }
471   
472   /// Implement std::swap in terms of SmallVector swap.
473   template<typename T, unsigned N>
474   inline void
475   swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
476     LHS.swap(RHS);
477   }
478 }
479
480 #endif