PR debug/54693
[official-gcc.git] / gcc / vec.h
blob8858f6afea14b0a61f4cddb8a0c47f9a7555aa84
1 /* Vector API for GNU compiler.
2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
3 Free Software Foundation, Inc.
4 Contributed by Nathan Sidwell <nathan@codesourcery.com>
5 Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #ifndef GCC_VEC_H
24 #define GCC_VEC_H
26 #include "statistics.h" /* For MEM_STAT_DECL. */
28 /* Templated vector type and associated interfaces.
30 The interface functions are typesafe and use inline functions,
31 sometimes backed by out-of-line generic functions. The vectors are
32 designed to interoperate with the GTY machinery.
34 There are both 'index' and 'iterate' accessors. The index accessor
35 is implemented by operator[]. The iterator returns a boolean
36 iteration condition and updates the iteration variable passed by
37 reference. Because the iterator will be inlined, the address-of
38 can be optimized away.
40 The vectors are implemented using the trailing array idiom, thus
41 they are not resizeable without changing the address of the vector
42 object itself. This means you cannot have variables or fields of
43 vector type -- always use a pointer to a vector. The one exception
44 is the final field of a structure, which could be a vector type.
45 You will have to use the embedded_size & embedded_init calls to
46 create such objects, and they will probably not be resizeable (so
47 don't use the 'safe' allocation variants). The trailing array
48 idiom is used (rather than a pointer to an array of data), because,
49 if we allow NULL to also represent an empty vector, empty vectors
50 occupy minimal space in the structure containing them.
52 Each operation that increases the number of active elements is
53 available in 'quick' and 'safe' variants. The former presumes that
54 there is sufficient allocated space for the operation to succeed
55 (it dies if there is not). The latter will reallocate the
56 vector, if needed. Reallocation causes an exponential increase in
57 vector size. If you know you will be adding N elements, it would
58 be more efficient to use the reserve operation before adding the
59 elements with the 'quick' operation. This will ensure there are at
60 least as many elements as you ask for, it will exponentially
61 increase if there are too few spare slots. If you want reserve a
62 specific number of slots, but do not want the exponential increase
63 (for instance, you know this is the last allocation), use the
64 reserve_exact operation. You can also create a vector of a
65 specific size from the get go.
67 You should prefer the push and pop operations, as they append and
68 remove from the end of the vector. If you need to remove several
69 items in one go, use the truncate operation. The insert and remove
70 operations allow you to change elements in the middle of the
71 vector. There are two remove operations, one which preserves the
72 element ordering 'ordered_remove', and one which does not
73 'unordered_remove'. The latter function copies the end element
74 into the removed slot, rather than invoke a memmove operation. The
75 'lower_bound' function will determine where to place an item in the
76 array using insert that will maintain sorted order.
78 When a vector type is defined, first a non-memory managed version
79 is created. You can then define either or both garbage collected
80 and heap allocated versions. The allocation mechanism is specified
81 when the vector is allocated. This can occur via the VEC_alloc
82 call or one of the VEC_safe_* functions that add elements to a
83 vector. If the vector is NULL, it will be allocated using the
84 allocation strategy selected in the call. The valid allocations
85 are defined in enum vec_allocation_t.
87 If you need to directly manipulate a vector, then the 'address'
88 accessor will return the address of the start of the vector. Also
89 the 'space' predicate will tell you whether there is spare capacity
90 in the vector. You will not normally need to use these two functions.
92 Variables of vector type are of type vec_t<ETYPE> where ETYPE is
93 the type of the elements of the vector. Due to the way GTY works,
94 you must annotate any structures you wish to insert or reference
95 from a vector with a GTY(()) tag. You need to do this even if you
96 never use the GC allocated variants.
98 An example of their use would be,
100 struct my_struct {
101 vec_t<tree> *v; // A (pointer to) a vector of tree pointers.
104 struct my_struct *s;
106 if (VEC_length(tree,s->v)) { we have some contents }
107 VEC_safe_push(tree,gc,s->v,decl); // append some decl onto the end
108 for (ix = 0; VEC_iterate(tree,s->v,ix,elt); ix++)
109 { do something with elt }
112 #if ENABLE_CHECKING
113 #define ALONE_VEC_CHECK_INFO __FILE__, __LINE__, __FUNCTION__
114 #define VEC_CHECK_INFO , ALONE_VEC_CHECK_INFO
115 #define ALONE_VEC_CHECK_DECL const char *file_, unsigned line_, const char *function_
116 #define VEC_CHECK_DECL , ALONE_VEC_CHECK_DECL
117 #define ALONE_VEC_CHECK_PASS file_, line_, function_
118 #define VEC_CHECK_PASS , ALONE_VEC_CHECK_PASS
120 #define VEC_ASSERT(EXPR,OP,T,A) \
121 (void)((EXPR) ? 0 : (VEC_ASSERT_FAIL(OP,VEC(T,A)), 0))
123 extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
124 ATTRIBUTE_NORETURN;
125 #define VEC_ASSERT_FAIL(OP,VEC) vec_assert_fail (OP,#VEC VEC_CHECK_PASS)
126 #else
127 #define ALONE_VEC_CHECK_INFO
128 #define VEC_CHECK_INFO
129 #define ALONE_VEC_CHECK_DECL void
130 #define VEC_CHECK_DECL
131 #define ALONE_VEC_CHECK_PASS
132 #define VEC_CHECK_PASS
133 #define VEC_ASSERT(EXPR,OP,T,A) (void)(EXPR)
134 #endif
136 #define VEC(T,A) vec_t<T>
138 enum vec_allocation_t { heap, gc, stack };
140 struct vec_prefix
142 unsigned num_;
143 unsigned alloc_;
146 /* Vector type, user visible. */
147 template<typename T>
148 struct GTY(()) vec_t
150 unsigned length (void) const;
151 bool empty (void) const;
152 T *address (void);
153 T &last (ALONE_VEC_CHECK_DECL);
154 const T &operator[] (unsigned) const;
155 T &operator[] (unsigned);
156 void embedded_init (int, int = 0);
158 template<enum vec_allocation_t A>
159 vec_t<T> *copy (ALONE_MEM_STAT_DECL);
161 bool space (int VEC_CHECK_DECL);
162 void splice (vec_t<T> * VEC_CHECK_DECL);
163 T *quick_push (const T & VEC_CHECK_DECL);
164 T &pop (ALONE_VEC_CHECK_DECL);
165 void truncate (unsigned VEC_CHECK_DECL);
166 void replace (unsigned, const T & VEC_CHECK_DECL);
167 void quick_insert (unsigned, const T & VEC_CHECK_DECL);
168 void ordered_remove (unsigned VEC_CHECK_DECL);
169 void unordered_remove (unsigned VEC_CHECK_DECL);
170 void block_remove (unsigned, unsigned VEC_CHECK_DECL);
171 unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
173 /* Class-static member functions. Some of these will become member
174 functions of a future handler class wrapping vec_t. */
175 static size_t embedded_size (int);
177 template<enum vec_allocation_t A>
178 static vec_t<T> *alloc (int MEM_STAT_DECL);
180 static vec_t<T> *alloc (int, vec_t<T> *);
182 template<enum vec_allocation_t A>
183 static void free (vec_t<T> **);
185 template<enum vec_allocation_t A>
186 static vec_t<T> *reserve_exact (vec_t<T> *, int MEM_STAT_DECL);
188 template<enum vec_allocation_t A>
189 static bool reserve_exact (vec_t<T> **, int VEC_CHECK_DECL MEM_STAT_DECL);
191 template<enum vec_allocation_t A>
192 static vec_t<T> *reserve (vec_t<T> *, int MEM_STAT_DECL);
194 template<enum vec_allocation_t A>
195 static bool reserve (vec_t<T> **, int VEC_CHECK_DECL MEM_STAT_DECL);
197 template<enum vec_allocation_t A>
198 static void safe_splice (vec_t<T> **, vec_t<T> * VEC_CHECK_DECL
199 MEM_STAT_DECL);
201 template<enum vec_allocation_t A>
202 static T *safe_push (vec_t<T> **, const T & VEC_CHECK_DECL MEM_STAT_DECL);
204 template<enum vec_allocation_t A>
205 static void safe_grow (vec_t<T> **, int VEC_CHECK_DECL MEM_STAT_DECL);
207 template<enum vec_allocation_t A>
208 static void safe_grow_cleared (vec_t<T> **, int VEC_CHECK_DECL MEM_STAT_DECL);
210 template<enum vec_allocation_t A>
211 static void safe_insert (vec_t<T> **, unsigned, const T & VEC_CHECK_DECL
212 MEM_STAT_DECL);
214 static bool iterate (const vec_t<T> *, unsigned, T *);
215 static bool iterate (const vec_t<T> *, unsigned, T **);
217 vec_prefix prefix_;
218 T vec_[1];
222 /* Garbage collection support for vec_t. */
224 template<typename T>
225 void
226 gt_ggc_mx (vec_t<T> *v)
228 extern void gt_ggc_mx (T &);
229 for (unsigned i = 0; i < v->length (); i++)
230 gt_ggc_mx ((*v)[i]);
234 /* PCH support for vec_t. */
236 template<typename T>
237 void
238 gt_pch_nx (vec_t<T> *v)
240 extern void gt_pch_nx (T &);
241 for (unsigned i = 0; i < v->length (); i++)
242 gt_pch_nx ((*v)[i]);
245 template<typename T>
246 void
247 gt_pch_nx (vec_t<T *> *v, gt_pointer_operator op, void *cookie)
249 for (unsigned i = 0; i < v->length (); i++)
250 op (&((*v)[i]), cookie);
253 template<typename T>
254 void
255 gt_pch_nx (vec_t<T> *v, gt_pointer_operator op, void *cookie)
257 extern void gt_pch_nx (T *, gt_pointer_operator, void *);
258 for (unsigned i = 0; i < v->length (); i++)
259 gt_pch_nx (&((*v)[i]), op, cookie);
263 /* FIXME. Remove these definitions and update all calling sites after
264 the handler class for vec_t is implemented. */
266 /* Vector of integer-like object. */
267 #define DEF_VEC_I(T) struct vec_swallow_trailing_semi
268 #define DEF_VEC_ALLOC_I(T,A) struct vec_swallow_trailing_semi
270 /* Vector of pointer to object. */
271 #define DEF_VEC_P(T) struct vec_swallow_trailing_semi
272 #define DEF_VEC_ALLOC_P(T,A) struct vec_swallow_trailing_semi
274 /* Vector of object. */
275 #define DEF_VEC_O(T) struct vec_swallow_trailing_semi
276 #define DEF_VEC_ALLOC_O(T,A) struct vec_swallow_trailing_semi
278 /* Vectors on the stack. */
279 #define DEF_VEC_ALLOC_P_STACK(T) struct vec_swallow_trailing_semi
280 #define DEF_VEC_ALLOC_O_STACK(T) struct vec_swallow_trailing_semi
281 #define DEF_VEC_ALLOC_I_STACK(T) struct vec_swallow_trailing_semi
283 /* Vectors of atomic types. Atomic types do not need to have its
284 elements marked for GC and PCH. To avoid unnecessary traversals,
285 we provide template instantiations for the GC/PCH functions that
286 do not traverse the vector.
288 FIXME cxx-conversion - Once vec_t users are converted this can
289 be provided in some other way (e.g., adding an additional template
290 parameter to the vec_t class). */
291 #define DEF_VEC_A(TYPE) \
292 template<typename T> \
293 void \
294 gt_ggc_mx (vec_t<TYPE> *v ATTRIBUTE_UNUSED) \
298 template<typename T> \
299 void \
300 gt_pch_nx (vec_t<TYPE> *v ATTRIBUTE_UNUSED) \
304 template<typename T> \
305 void \
306 gt_pch_nx (vec_t<TYPE> *v ATTRIBUTE_UNUSED, \
307 gt_pointer_operator op ATTRIBUTE_UNUSED, \
308 void *cookie ATTRIBUTE_UNUSED) \
311 struct vec_swallow_trailing_semi
313 #define DEF_VEC_ALLOC_A(T,A) struct vec_swallow_trailing_semi
315 /* Support functions for stack vectors. */
316 extern void *vec_stack_p_reserve_exact_1 (int, void *);
317 extern void *vec_stack_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
318 extern void *vec_stack_o_reserve_exact (void *, int, size_t, size_t
319 MEM_STAT_DECL);
320 extern void vec_stack_free (void *);
322 extern void dump_vec_loc_statistics (void);
323 extern void ggc_free (void *);
324 extern void vec_heap_free (void *);
327 /* API compatibility macros (to be removed). */
328 #define VEC_length(T,V) \
329 ((V) ? (V)->length () : 0)
331 #define VEC_empty(T,V) \
332 ((V) ? (V)->empty () : true)
334 #define VEC_address(T,V) \
335 vec_address<T> (V)
337 /* FIXME. For now, we need to continue expanding VEC_address into a
338 function call. Otherwise, the warning machinery for -Wnonnull gets
339 confused thinking that VEC_address may return null in calls to
340 memcpy and qsort. This will disappear once vec_address becomes
341 a member function for a handler class wrapping vec_t. */
343 template<typename T>
344 static inline T *
345 vec_address (vec_t<T> *vec)
347 return vec ? vec->address() : NULL;
350 #define VEC_last(T,V) \
351 ((V)->last (ALONE_VEC_CHECK_INFO))
353 #define VEC_index(T,V,I) \
354 ((*(V))[I])
356 #define VEC_iterate(T,V,I,P) \
357 (vec_t<T>::iterate(V, I, &(P)))
359 #define VEC_embedded_size(T,N) \
360 (vec_t<T>::embedded_size (N))
362 #define VEC_embedded_init(T,V,N) \
363 ((V)->embedded_init (N))
365 #define VEC_free(T,A,V) \
366 (vec_t<T>::free<A> (&(V)))
368 #define VEC_copy(T,A,V) \
369 ((V)->copy<A> (ALONE_MEM_STAT_INFO))
371 #define VEC_space(T,V,R) \
372 ((V) ? (V)->space (R VEC_CHECK_INFO) : (R) == 0)
374 #define VEC_reserve(T,A,V,R) \
375 (vec_t<T>::reserve<A> (&(V), (int)(R) VEC_CHECK_INFO MEM_STAT_INFO))
377 #define VEC_reserve_exact(T,A,V,R) \
378 (vec_t<T>::reserve_exact<A> (&(V), R VEC_CHECK_INFO MEM_STAT_INFO))
380 #define VEC_splice(T,DST,SRC) \
381 (DST)->splice (SRC VEC_CHECK_INFO)
383 #define VEC_safe_splice(T,A,DST,SRC) \
384 vec_t<T>::safe_splice<A> (&(DST), SRC VEC_CHECK_INFO MEM_STAT_INFO)
386 #define VEC_quick_push(T,V,O) \
387 ((V)->quick_push (O VEC_CHECK_INFO))
389 #define VEC_safe_push(T,A,V,O) \
390 (vec_t<T>::safe_push<A> (&(V), O VEC_CHECK_INFO MEM_STAT_INFO))
392 #define VEC_pop(T,V) \
393 ((V)->pop (ALONE_VEC_CHECK_INFO))
395 #define VEC_truncate(T,V,I) \
396 (V \
397 ? (V)->truncate ((unsigned)(I) VEC_CHECK_INFO) \
398 : gcc_assert ((I) == 0))
400 #define VEC_safe_grow(T,A,V,I) \
401 (vec_t<T>::safe_grow<A> (&(V), (int)(I) VEC_CHECK_INFO MEM_STAT_INFO))
403 #define VEC_safe_grow_cleared(T,A,V,I) \
404 (vec_t<T>::safe_grow_cleared<A> (&(V), (int)(I) \
405 VEC_CHECK_INFO MEM_STAT_INFO))
407 #define VEC_replace(T,V,I,O) \
408 ((V)->replace ((unsigned)(I), O VEC_CHECK_INFO))
410 #define VEC_quick_insert(T,V,I,O) \
411 ((V)->quick_insert (I,O VEC_CHECK_INFO))
413 #define VEC_safe_insert(T,A,V,I,O) \
414 (vec_t<T>::safe_insert<A> (&(V), I, O VEC_CHECK_INFO MEM_STAT_INFO))
416 #define VEC_ordered_remove(T,V,I) \
417 ((V)->ordered_remove (I VEC_CHECK_INFO))
419 #define VEC_unordered_remove(T,V,I) \
420 ((V)->unordered_remove (I VEC_CHECK_INFO))
422 #define VEC_block_remove(T,V,I,L) \
423 ((V)->block_remove (I, L VEC_CHECK_INFO))
425 #define VEC_lower_bound(T,V,O,LT) \
426 ((V)->lower_bound (O, LT))
429 /* Return the number of active elements in this vector. */
431 template<typename T>
432 inline unsigned
433 vec_t<T>::length (void) const
435 return prefix_.num_;
439 /* Return true if this vector has no active elements. */
441 template<typename T>
442 inline bool
443 vec_t<T>::empty (void) const
445 return length () == 0;
449 /* Return the address of the array of elements. If you need to
450 directly manipulate the array (for instance, you want to feed it
451 to qsort), use this accessor. */
453 template<typename T>
454 inline T *
455 vec_t<T>::address (void)
457 return vec_;
461 /* Get the final element of the vector, which must not be empty. */
463 template<typename T>
465 vec_t<T>::last (ALONE_VEC_CHECK_DECL)
467 VEC_ASSERT (prefix_.num_, "last", T, base);
468 return (*this)[prefix_.num_ - 1];
472 /* Index into vector. Return the IX'th element. IX must be in the
473 domain of the vector. */
475 template<typename T>
476 const T &
477 vec_t<T>::operator[] (unsigned ix) const
479 gcc_assert (ix < prefix_.num_);
480 return vec_[ix];
483 template<typename T>
485 vec_t<T>::operator[] (unsigned ix)
487 gcc_assert (ix < prefix_.num_);
488 return vec_[ix];
492 /* Return iteration condition and update PTR to point to the IX'th
493 element of VEC. Use this to iterate over the elements of a vector
494 as follows,
496 for (ix = 0; vec_t<T>::iterate(v, ix, &ptr); ix++)
497 continue;
499 FIXME. This is a static member function because if VEC is NULL,
500 PTR should be initialized to NULL. This will become a regular
501 member function of the handler class. */
503 template<typename T>
504 bool
505 vec_t<T>::iterate (const vec_t<T> *vec, unsigned ix, T *ptr)
507 if (vec && ix < vec->prefix_.num_)
509 *ptr = vec->vec_[ix];
510 return true;
512 else
514 *ptr = 0;
515 return false;
520 /* Return iteration condition and update *PTR to point to the
521 IX'th element of VEC. Use this to iterate over the elements of a
522 vector as follows,
524 for (ix = 0; v->iterate(ix, &ptr); ix++)
525 continue;
527 This variant is for vectors of objects. FIXME, to be removed
528 once the distinction between vec_t<T> and vec_t<T *> disappears. */
530 template<typename T>
531 bool
532 vec_t<T>::iterate (const vec_t<T> *vec, unsigned ix, T **ptr)
534 if (vec && ix < vec->prefix_.num_)
536 *ptr = CONST_CAST (T *, &vec->vec_[ix]);
537 return true;
539 else
541 *ptr = 0;
542 return false;
547 /* Convenience macro for forward iteration. */
549 #define FOR_EACH_VEC_ELT(T, V, I, P) \
550 for (I = 0; VEC_iterate (T, (V), (I), (P)); ++(I))
552 /* Likewise, but start from FROM rather than 0. */
554 #define FOR_EACH_VEC_ELT_FROM(T, V, I, P, FROM) \
555 for (I = (FROM); VEC_iterate (T, (V), (I), (P)); ++(I))
557 /* Convenience macro for reverse iteration. */
559 #define FOR_EACH_VEC_ELT_REVERSE(T, V, I, P) \
560 for (I = VEC_length (T, (V)) - 1; \
561 VEC_iterate (T, (V), (I), (P)); \
562 (I)--)
565 /* Return the number of bytes needed to embed an instance of vec_t inside
566 another data structure.
568 Use these methods to determine the required size and initialization
569 of a vector V of type T embedded within another structure (as the
570 final member):
572 size_t vec_t<T>::embedded_size<T> (int reserve);
573 void v->embedded_init(int reserve, int active);
575 These allow the caller to perform the memory allocation. */
577 template<typename T>
578 size_t
579 vec_t<T>::embedded_size (int nelems)
581 return offsetof (vec_t<T>, vec_) + nelems * sizeof (T);
585 /* Initialize the vector to contain room for NELEMS elements and
586 ACTIVE active elements. */
588 template<typename T>
589 void
590 vec_t<T>::embedded_init (int nelems, int active)
592 prefix_.num_ = active;
593 prefix_.alloc_ = nelems;
597 /* Allocate a new vector with space for RESERVE objects. If RESERVE
598 is zero, NO vector is created.
600 Note that this allocator must always be a macro:
602 We support a vector which starts out with space on the stack and
603 switches to heap space when forced to reallocate. This works a
604 little differently. In the case of stack vectors, vec_alloc will
605 expand to a call to vec_alloc_1 that calls XALLOCAVAR to request the
606 initial allocation. This uses alloca to get the initial space.
607 Since alloca can not be usefully called in an inline function,
608 vec_alloc must always be a macro.
610 Important limitations of stack vectors:
612 - Only the initial allocation will be made using alloca, so pass a
613 reasonable estimate that doesn't use too much stack space; don't
614 pass zero.
616 - Don't return a stack-allocated vector from the function which
617 allocated it. */
619 #define VEC_alloc(T,A,N) \
620 ((A == stack) \
621 ? vec_t<T>::alloc (N, XALLOCAVAR (vec_t<T>, vec_t<T>::embedded_size (N)))\
622 : vec_t<T>::alloc<A> (N MEM_STAT_INFO))
624 template<typename T>
625 template<enum vec_allocation_t A>
626 vec_t<T> *
627 vec_t<T>::alloc (int nelems MEM_STAT_DECL)
629 return reserve_exact<A> ((vec_t<T> *) NULL, nelems PASS_MEM_STAT);
632 template<typename T>
633 vec_t<T> *
634 vec_t<T>::alloc (int nelems, vec_t<T> *space)
636 return static_cast <vec_t<T> *> (vec_stack_p_reserve_exact_1 (nelems, space));
640 /* Free vector *V and set it to NULL. */
642 template<typename T>
643 template<enum vec_allocation_t A>
644 void
645 vec_t<T>::free (vec_t<T> **v)
647 if (*v)
649 if (A == heap)
650 vec_heap_free (*v);
651 else if (A == gc)
652 ggc_free (*v);
653 else if (A == stack)
654 vec_stack_free (*v);
656 *v = NULL;
660 /* Return a copy of this vector. The new and old vectors need not be
661 allocated by the same mechanism. */
663 template<typename T>
664 template<enum vec_allocation_t A>
665 vec_t<T> *
666 vec_t<T>::copy (ALONE_MEM_STAT_DECL)
668 unsigned len = VEC_length (T, this);
669 vec_t<T> *new_vec = NULL;
671 if (len)
673 new_vec = reserve_exact<A> (static_cast<vec_t<T> *> (NULL),
674 len PASS_MEM_STAT);
675 new_vec->embedded_init (len, len);
676 memcpy (new_vec->address (), vec_, sizeof (T) * len);
679 return new_vec;
683 /* If this vector has space for RESERVE additional entries, return
684 true. You usually only need to use this if you are doing your
685 own vector reallocation, for instance on an embedded vector. This
686 returns true in exactly the same circumstances that vec_reserve
687 will. */
689 template<typename T>
690 bool
691 vec_t<T>::space (int nelems VEC_CHECK_DECL)
693 VEC_ASSERT (nelems >= 0, "space", T, base);
694 return prefix_.alloc_ - prefix_.num_ >= static_cast <unsigned> (nelems);
698 /* Ensure that the vector **VEC has at least RESERVE slots available. This
699 will create additional headroom. Note this can cause **VEC to
700 be reallocated. Returns true iff reallocation actually occurred. */
702 template<typename T>
703 template<enum vec_allocation_t A>
704 bool
705 vec_t<T>::reserve (vec_t<T> **vec, int nelems VEC_CHECK_DECL MEM_STAT_DECL)
707 bool extend = (*vec) ? !(*vec)->space (nelems VEC_CHECK_PASS) : nelems != 0;
709 if (extend)
710 *vec = reserve<A> (*vec, nelems PASS_MEM_STAT);
712 return extend;
716 /* Ensure that **VEC has at least NELEMS slots available. This will not
717 create additional headroom. Note this can cause VEC to be
718 reallocated. Returns true iff reallocation actually occurred. */
720 template<typename T>
721 template<enum vec_allocation_t A>
722 bool
723 vec_t<T>::reserve_exact (vec_t<T> **vec, int nelems VEC_CHECK_DECL
724 MEM_STAT_DECL)
726 bool extend = (*vec) ? !(*vec)->space (nelems VEC_CHECK_PASS) : nelems != 0;
728 if (extend)
729 *vec = reserve_exact<A> (*vec, nelems PASS_MEM_STAT);
731 return extend;
735 /* Copy the elements from SRC to the end of this vector as if by memcpy.
736 SRC and this vector need not be allocated with the same mechanism,
737 although they most often will be. This vector is assumed to have
738 sufficient headroom available. */
740 template<typename T>
741 void
742 vec_t<T>::splice (vec_t<T> *src VEC_CHECK_DECL)
744 if (src)
746 unsigned len = VEC_length (T, src);
747 VEC_ASSERT (VEC_length (T, this) + len <= prefix_.alloc_, "splice", T,
748 base);
749 memcpy (address () + VEC_length (T, this),
750 src->address (),
751 len * sizeof (T));
752 prefix_.num_ += len;
757 /* Copy the elements in SRC to the end of DST as if by memcpy. DST and
758 SRC need not be allocated with the same mechanism, although they most
759 often will be. DST need not have sufficient headroom and will be
760 reallocated if needed. */
762 template<typename T>
763 template<enum vec_allocation_t A>
764 void
765 vec_t<T>::safe_splice (vec_t<T> **dst, vec_t<T> *src VEC_CHECK_DECL
766 MEM_STAT_DECL)
768 if (src)
770 reserve_exact<A> (dst, VEC_length (T, src) VEC_CHECK_PASS MEM_STAT_INFO);
771 (*dst)->splice (src VEC_CHECK_PASS);
776 /* Push OBJ (a new element) onto the end of the vector. There must be
777 sufficient space in the vector. Return a pointer to the slot
778 where OBJ was inserted. */
781 template<typename T>
783 vec_t<T>::quick_push (const T &obj VEC_CHECK_DECL)
785 VEC_ASSERT (prefix_.num_ < prefix_.alloc_, "push", T, base);
786 T *slot = &vec_[prefix_.num_++];
787 *slot = obj;
788 return slot;
792 /* Push a new element OBJ onto the end of VEC. Reallocates VEC, if
793 needed. Return a pointer to the slot where OBJ was inserted. */
795 template<typename T>
796 template<enum vec_allocation_t A>
798 vec_t<T>::safe_push (vec_t<T> **vec, const T &obj VEC_CHECK_DECL MEM_STAT_DECL)
800 reserve<A> (vec, 1 VEC_CHECK_PASS PASS_MEM_STAT);
801 return (*vec)->quick_push (obj VEC_CHECK_PASS);
805 /* Pop and return the last element off the end of the vector. */
808 template<typename T>
810 vec_t<T>::pop (ALONE_VEC_CHECK_DECL)
812 VEC_ASSERT (prefix_.num_, "pop", T, base);
813 return vec_[--prefix_.num_];
817 /* Set the length of the vector to LEN. The new length must be less
818 than or equal to the current length. This is an O(1) operation. */
820 template<typename T>
821 void
822 vec_t<T>::truncate (unsigned size VEC_CHECK_DECL)
824 VEC_ASSERT (prefix_.num_ >= size, "truncate", T, base);
825 prefix_.num_ = size;
829 /* Grow the vector VEC to a specific length. The LEN must be as
830 long or longer than the current length. The new elements are
831 uninitialized. */
833 template<typename T>
834 template<enum vec_allocation_t A>
835 void
836 vec_t<T>::safe_grow (vec_t<T> **vec, int size VEC_CHECK_DECL MEM_STAT_DECL)
838 VEC_ASSERT (size >= 0 && VEC_length (T, *vec) <= (unsigned)size,
839 "grow", T, A);
840 reserve_exact<A> (vec, size - (int)VEC_length (T, *vec)
841 VEC_CHECK_PASS PASS_MEM_STAT);
842 (*vec)->prefix_.num_ = size;
846 /* Grow the vector *VEC to a specific length. The LEN must be as
847 long or longer than the current length. The new elements are
848 initialized to zero. */
850 template<typename T>
851 template<enum vec_allocation_t A>
852 void
853 vec_t<T>::safe_grow_cleared (vec_t<T> **vec, int size VEC_CHECK_DECL
854 MEM_STAT_DECL)
856 int oldsize = VEC_length (T, *vec);
857 safe_grow<A> (vec, size VEC_CHECK_PASS PASS_MEM_STAT);
858 memset (&((*vec)->address ()[oldsize]), 0, sizeof (T) * (size - oldsize));
862 /* Replace the IXth element of this vector with a new value, VAL. */
864 template<typename T>
865 void
866 vec_t<T>::replace (unsigned ix, const T &obj VEC_CHECK_DECL)
868 VEC_ASSERT (ix < prefix_.num_, "replace", T, base);
869 vec_[ix] = obj;
873 /* Insert an element, OBJ, at the IXth position of VEC. There must be
874 sufficient space. */
876 template<typename T>
877 void
878 vec_t<T>::quick_insert (unsigned ix, const T &obj VEC_CHECK_DECL)
880 VEC_ASSERT (prefix_.num_ < prefix_.alloc_, "insert", T, base);
881 VEC_ASSERT (ix <= prefix_.num_, "insert", T, base);
882 T *slot = &vec_[ix];
883 memmove (slot + 1, slot, (prefix_.num_++ - ix) * sizeof (T));
884 *slot = obj;
888 /* Insert an element, OBJ, at the IXth position of VEC. Reallocate
889 VEC, if necessary. */
891 template<typename T>
892 template<enum vec_allocation_t A>
893 void
894 vec_t<T>::safe_insert (vec_t<T> **vec, unsigned ix, const T &obj VEC_CHECK_DECL
895 MEM_STAT_DECL)
897 reserve<A> (vec, 1 VEC_CHECK_PASS PASS_MEM_STAT);
898 (*vec)->quick_insert (ix, obj VEC_CHECK_PASS);
902 /* Remove an element from the IXth position of this vector. Ordering of
903 remaining elements is preserved. This is an O(N) operation due to
904 a memmove. */
906 template<typename T>
907 void
908 vec_t<T>::ordered_remove (unsigned ix VEC_CHECK_DECL)
910 VEC_ASSERT (ix < prefix_.num_, "remove", T, base);
911 T *slot = &vec_[ix];
912 memmove (slot, slot + 1, (--prefix_.num_ - ix) * sizeof (T));
916 /* Remove an element from the IXth position of VEC. Ordering of
917 remaining elements is destroyed. This is an O(1) operation. */
919 template<typename T>
920 void
921 vec_t<T>::unordered_remove (unsigned ix VEC_CHECK_DECL)
923 VEC_ASSERT (ix < prefix_.num_, "remove", T, base);
924 vec_[ix] = vec_[--prefix_.num_];
928 /* Remove LEN elements starting at the IXth. Ordering is retained.
929 This is an O(N) operation due to memmove. */
931 template<typename T>
932 void
933 vec_t<T>::block_remove (unsigned ix, unsigned len VEC_CHECK_DECL)
935 VEC_ASSERT (ix + len <= prefix_.num_, "block_remove", T, base);
936 T *slot = &vec_[ix];
937 prefix_.num_ -= len;
938 memmove (slot, slot + len, (prefix_.num_ - ix) * sizeof (T));
941 /* Sort the contents of V with qsort. Use CMP as the comparison function. */
942 #define VEC_qsort(T,V,CMP) \
943 qsort (VEC_address (T, V), VEC_length (T, V), sizeof (T), CMP)
946 /* Find and return the first position in which OBJ could be inserted
947 without changing the ordering of this vector. LESSTHAN is a
948 function that returns true if the first argument is strictly less
949 than the second. */
951 template<typename T>
952 unsigned
953 vec_t<T>::lower_bound (T obj, bool (*lessthan)(const T &, const T &)) const
955 unsigned int len = VEC_length (T, this);
956 unsigned int half, middle;
957 unsigned int first = 0;
958 while (len > 0)
960 half = len / 2;
961 middle = first;
962 middle += half;
963 T middle_elem = (*this)[middle];
964 if (lessthan (middle_elem, obj))
966 first = middle;
967 ++first;
968 len = len - half - 1;
970 else
971 len = half;
973 return first;
977 void *vec_heap_o_reserve_1 (void *, int, size_t, size_t, bool MEM_STAT_DECL);
978 void *vec_gc_o_reserve_1 (void *, int, size_t, size_t, bool MEM_STAT_DECL);
980 /* Ensure there are at least RESERVE free slots in VEC_, growing
981 exponentially. If RESERVE < 0 grow exactly, else grow
982 exponentially. As a special case, if VEC_ is NULL, and RESERVE is
983 0, no vector will be created. */
985 template<typename T>
986 template<enum vec_allocation_t A>
987 vec_t<T> *
988 vec_t<T>::reserve (vec_t<T> *vec, int reserve MEM_STAT_DECL)
990 void *res = NULL;
991 size_t off = offsetof (vec_t<T>, vec_);
992 size_t sz = sizeof (T);
994 switch (A)
996 case gc:
997 res = vec_gc_o_reserve_1 (vec, reserve, off, sz, false PASS_MEM_STAT);
998 break;
999 case heap:
1000 res = vec_heap_o_reserve_1 (vec, reserve, off, sz, false PASS_MEM_STAT);
1001 break;
1002 case stack:
1003 res = vec_stack_o_reserve (vec, reserve, off, sz PASS_MEM_STAT);
1004 break;
1007 return static_cast <vec_t<T> *> (res);
1011 /* Ensure there are at least RESERVE free slots in VEC, growing
1012 exactly. If RESERVE < 0 grow exactly, else grow exponentially. As
1013 a special case, if VEC is NULL, and RESERVE is 0, no vector will be
1014 created. */
1016 template<typename T>
1017 template<enum vec_allocation_t A>
1018 vec_t<T> *
1019 vec_t<T>::reserve_exact (vec_t<T> *vec, int reserve MEM_STAT_DECL)
1021 void *res = NULL;
1022 size_t off = sizeof (struct vec_prefix);
1023 size_t sz = sizeof (T);
1025 gcc_assert (offsetof (vec_t<T>, vec_) == sizeof (struct vec_prefix));
1027 switch (A)
1029 case gc:
1030 res = vec_gc_o_reserve_1 (vec, reserve, off, sz, true PASS_MEM_STAT);
1031 break;
1032 case heap:
1033 res = vec_heap_o_reserve_1 (vec, reserve, off, sz, true PASS_MEM_STAT);
1034 break;
1035 case stack:
1036 res = vec_stack_o_reserve_exact (vec, reserve, off, sz PASS_MEM_STAT);
1037 break;
1040 return static_cast <vec_t<T> *> (res);
1043 #endif /* GCC_VEC_H */