xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/vec.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Vector API for GNU compiler.
2*8feb0f0bSmrg    Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Nathan Sidwell <nathan@codesourcery.com>
41debfc3dSmrg    Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
51debfc3dSmrg 
61debfc3dSmrg This file is part of GCC.
71debfc3dSmrg 
81debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
91debfc3dSmrg the terms of the GNU General Public License as published by the Free
101debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
111debfc3dSmrg version.
121debfc3dSmrg 
131debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
141debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
151debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
161debfc3dSmrg for more details.
171debfc3dSmrg 
181debfc3dSmrg You should have received a copy of the GNU General Public License
191debfc3dSmrg along with GCC; see the file COPYING3.  If not see
201debfc3dSmrg <http://www.gnu.org/licenses/>.  */
211debfc3dSmrg 
221debfc3dSmrg #ifndef GCC_VEC_H
231debfc3dSmrg #define GCC_VEC_H
241debfc3dSmrg 
251debfc3dSmrg /* Some gen* file have no ggc support as the header file gtype-desc.h is
261debfc3dSmrg    missing.  Provide these definitions in case ggc.h has not been included.
271debfc3dSmrg    This is not a problem because any code that runs before gengtype is built
281debfc3dSmrg    will never need to use GC vectors.*/
291debfc3dSmrg 
301debfc3dSmrg extern void ggc_free (void *);
311debfc3dSmrg extern size_t ggc_round_alloc_size (size_t requested_size);
321debfc3dSmrg extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
331debfc3dSmrg 
341debfc3dSmrg /* Templated vector type and associated interfaces.
351debfc3dSmrg 
361debfc3dSmrg    The interface functions are typesafe and use inline functions,
371debfc3dSmrg    sometimes backed by out-of-line generic functions.  The vectors are
381debfc3dSmrg    designed to interoperate with the GTY machinery.
391debfc3dSmrg 
401debfc3dSmrg    There are both 'index' and 'iterate' accessors.  The index accessor
411debfc3dSmrg    is implemented by operator[].  The iterator returns a boolean
421debfc3dSmrg    iteration condition and updates the iteration variable passed by
431debfc3dSmrg    reference.  Because the iterator will be inlined, the address-of
441debfc3dSmrg    can be optimized away.
451debfc3dSmrg 
461debfc3dSmrg    Each operation that increases the number of active elements is
471debfc3dSmrg    available in 'quick' and 'safe' variants.  The former presumes that
481debfc3dSmrg    there is sufficient allocated space for the operation to succeed
491debfc3dSmrg    (it dies if there is not).  The latter will reallocate the
501debfc3dSmrg    vector, if needed.  Reallocation causes an exponential increase in
511debfc3dSmrg    vector size.  If you know you will be adding N elements, it would
521debfc3dSmrg    be more efficient to use the reserve operation before adding the
531debfc3dSmrg    elements with the 'quick' operation.  This will ensure there are at
541debfc3dSmrg    least as many elements as you ask for, it will exponentially
551debfc3dSmrg    increase if there are too few spare slots.  If you want reserve a
561debfc3dSmrg    specific number of slots, but do not want the exponential increase
571debfc3dSmrg    (for instance, you know this is the last allocation), use the
581debfc3dSmrg    reserve_exact operation.  You can also create a vector of a
591debfc3dSmrg    specific size from the get go.
601debfc3dSmrg 
611debfc3dSmrg    You should prefer the push and pop operations, as they append and
621debfc3dSmrg    remove from the end of the vector. If you need to remove several
631debfc3dSmrg    items in one go, use the truncate operation.  The insert and remove
641debfc3dSmrg    operations allow you to change elements in the middle of the
651debfc3dSmrg    vector.  There are two remove operations, one which preserves the
661debfc3dSmrg    element ordering 'ordered_remove', and one which does not
671debfc3dSmrg    'unordered_remove'.  The latter function copies the end element
681debfc3dSmrg    into the removed slot, rather than invoke a memmove operation.  The
691debfc3dSmrg    'lower_bound' function will determine where to place an item in the
701debfc3dSmrg    array using insert that will maintain sorted order.
711debfc3dSmrg 
721debfc3dSmrg    Vectors are template types with three arguments: the type of the
731debfc3dSmrg    elements in the vector, the allocation strategy, and the physical
741debfc3dSmrg    layout to use
751debfc3dSmrg 
761debfc3dSmrg    Four allocation strategies are supported:
771debfc3dSmrg 
781debfc3dSmrg 	- Heap: allocation is done using malloc/free.  This is the
791debfc3dSmrg 	  default allocation strategy.
801debfc3dSmrg 
811debfc3dSmrg   	- GC: allocation is done using ggc_alloc/ggc_free.
821debfc3dSmrg 
831debfc3dSmrg   	- GC atomic: same as GC with the exception that the elements
841debfc3dSmrg 	  themselves are assumed to be of an atomic type that does
851debfc3dSmrg 	  not need to be garbage collected.  This means that marking
861debfc3dSmrg 	  routines do not need to traverse the array marking the
871debfc3dSmrg 	  individual elements.  This increases the performance of
881debfc3dSmrg 	  GC activities.
891debfc3dSmrg 
901debfc3dSmrg    Two physical layouts are supported:
911debfc3dSmrg 
921debfc3dSmrg 	- Embedded: The vector is structured using the trailing array
931debfc3dSmrg 	  idiom.  The last member of the structure is an array of size
941debfc3dSmrg 	  1.  When the vector is initially allocated, a single memory
951debfc3dSmrg 	  block is created to hold the vector's control data and the
961debfc3dSmrg 	  array of elements.  These vectors cannot grow without
971debfc3dSmrg 	  reallocation (see discussion on embeddable vectors below).
981debfc3dSmrg 
991debfc3dSmrg 	- Space efficient: The vector is structured as a pointer to an
1001debfc3dSmrg 	  embedded vector.  This is the default layout.  It means that
1011debfc3dSmrg 	  vectors occupy a single word of storage before initial
1021debfc3dSmrg 	  allocation.  Vectors are allowed to grow (the internal
1031debfc3dSmrg 	  pointer is reallocated but the main vector instance does not
1041debfc3dSmrg 	  need to relocate).
1051debfc3dSmrg 
1061debfc3dSmrg    The type, allocation and layout are specified when the vector is
1071debfc3dSmrg    declared.
1081debfc3dSmrg 
1091debfc3dSmrg    If you need to directly manipulate a vector, then the 'address'
1101debfc3dSmrg    accessor will return the address of the start of the vector.  Also
1111debfc3dSmrg    the 'space' predicate will tell you whether there is spare capacity
1121debfc3dSmrg    in the vector.  You will not normally need to use these two functions.
1131debfc3dSmrg 
1141debfc3dSmrg    Notes on the different layout strategies
1151debfc3dSmrg 
1161debfc3dSmrg    * Embeddable vectors (vec<T, A, vl_embed>)
1171debfc3dSmrg 
1181debfc3dSmrg      These vectors are suitable to be embedded in other data
1191debfc3dSmrg      structures so that they can be pre-allocated in a contiguous
1201debfc3dSmrg      memory block.
1211debfc3dSmrg 
1221debfc3dSmrg      Embeddable vectors are implemented using the trailing array
1231debfc3dSmrg      idiom, thus they are not resizeable without changing the address
1241debfc3dSmrg      of the vector object itself.  This means you cannot have
1251debfc3dSmrg      variables or fields of embeddable vector type -- always use a
1261debfc3dSmrg      pointer to a vector.  The one exception is the final field of a
1271debfc3dSmrg      structure, which could be a vector type.
1281debfc3dSmrg 
1291debfc3dSmrg      You will have to use the embedded_size & embedded_init calls to
1301debfc3dSmrg      create such objects, and they will not be resizeable (so the
1311debfc3dSmrg      'safe' allocation variants are not available).
1321debfc3dSmrg 
1331debfc3dSmrg      Properties of embeddable vectors:
1341debfc3dSmrg 
1351debfc3dSmrg 	  - The whole vector and control data are allocated in a single
1361debfc3dSmrg 	    contiguous block.  It uses the trailing-vector idiom, so
1371debfc3dSmrg 	    allocation must reserve enough space for all the elements
1381debfc3dSmrg 	    in the vector plus its control data.
1391debfc3dSmrg 	  - The vector cannot be re-allocated.
1401debfc3dSmrg 	  - The vector cannot grow nor shrink.
1411debfc3dSmrg 	  - No indirections needed for access/manipulation.
1421debfc3dSmrg 	  - It requires 2 words of storage (prior to vector allocation).
1431debfc3dSmrg 
1441debfc3dSmrg 
1451debfc3dSmrg    * Space efficient vector (vec<T, A, vl_ptr>)
1461debfc3dSmrg 
1471debfc3dSmrg      These vectors can grow dynamically and are allocated together
1481debfc3dSmrg      with their control data.  They are suited to be included in data
1491debfc3dSmrg      structures.  Prior to initial allocation, they only take a single
1501debfc3dSmrg      word of storage.
1511debfc3dSmrg 
1521debfc3dSmrg      These vectors are implemented as a pointer to embeddable vectors.
1531debfc3dSmrg      The semantics allow for this pointer to be NULL to represent
1541debfc3dSmrg      empty vectors.  This way, empty vectors occupy minimal space in
1551debfc3dSmrg      the structure containing them.
1561debfc3dSmrg 
1571debfc3dSmrg      Properties:
1581debfc3dSmrg 
1591debfc3dSmrg 	- The whole vector and control data are allocated in a single
1601debfc3dSmrg 	  contiguous block.
1611debfc3dSmrg   	- The whole vector may be re-allocated.
1621debfc3dSmrg   	- Vector data may grow and shrink.
1631debfc3dSmrg   	- Access and manipulation requires a pointer test and
1641debfc3dSmrg 	  indirection.
1651debfc3dSmrg   	- It requires 1 word of storage (prior to vector allocation).
1661debfc3dSmrg 
1671debfc3dSmrg    An example of their use would be,
1681debfc3dSmrg 
1691debfc3dSmrg    struct my_struct {
1701debfc3dSmrg      // A space-efficient vector of tree pointers in GC memory.
1711debfc3dSmrg      vec<tree, va_gc, vl_ptr> v;
1721debfc3dSmrg    };
1731debfc3dSmrg 
1741debfc3dSmrg    struct my_struct *s;
1751debfc3dSmrg 
1761debfc3dSmrg    if (s->v.length ()) { we have some contents }
1771debfc3dSmrg    s->v.safe_push (decl); // append some decl onto the end
1781debfc3dSmrg    for (ix = 0; s->v.iterate (ix, &elt); ix++)
1791debfc3dSmrg      { do something with elt }
1801debfc3dSmrg */
1811debfc3dSmrg 
1821debfc3dSmrg /* Support function for statistics.  */
1831debfc3dSmrg extern void dump_vec_loc_statistics (void);
1841debfc3dSmrg 
1851debfc3dSmrg /* Hashtable mapping vec addresses to descriptors.  */
1861debfc3dSmrg extern htab_t vec_mem_usage_hash;
1871debfc3dSmrg 
1881debfc3dSmrg /* Control data for vectors.  This contains the number of allocated
1891debfc3dSmrg    and used slots inside a vector.  */
1901debfc3dSmrg 
1911debfc3dSmrg struct vec_prefix
1921debfc3dSmrg {
1931debfc3dSmrg   /* FIXME - These fields should be private, but we need to cater to
1941debfc3dSmrg 	     compilers that have stricter notions of PODness for types.  */
1951debfc3dSmrg 
1961debfc3dSmrg   /* Memory allocation support routines in vec.c.  */
1971debfc3dSmrg   void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
198c0a68be4Smrg   void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO);
1991debfc3dSmrg   static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
2001debfc3dSmrg   static unsigned calculate_allocation_1 (unsigned, unsigned);
2011debfc3dSmrg 
2021debfc3dSmrg   /* Note that vec_prefix should be a base class for vec, but we use
2031debfc3dSmrg      offsetof() on vector fields of tree structures (e.g.,
2041debfc3dSmrg      tree_binfo::base_binfos), and offsetof only supports base types.
2051debfc3dSmrg 
2061debfc3dSmrg      To compensate, we make vec_prefix a field inside vec and make
2071debfc3dSmrg      vec a friend class of vec_prefix so it can access its fields.  */
2081debfc3dSmrg   template <typename, typename, typename> friend struct vec;
2091debfc3dSmrg 
2101debfc3dSmrg   /* The allocator types also need access to our internals.  */
2111debfc3dSmrg   friend struct va_gc;
2121debfc3dSmrg   friend struct va_gc_atomic;
2131debfc3dSmrg   friend struct va_heap;
2141debfc3dSmrg 
2151debfc3dSmrg   unsigned m_alloc : 31;
2161debfc3dSmrg   unsigned m_using_auto_storage : 1;
2171debfc3dSmrg   unsigned m_num;
2181debfc3dSmrg };
2191debfc3dSmrg 
2201debfc3dSmrg /* Calculate the number of slots to reserve a vector, making sure that
2211debfc3dSmrg    RESERVE slots are free.  If EXACT grow exactly, otherwise grow
2221debfc3dSmrg    exponentially.  PFX is the control data for the vector.  */
2231debfc3dSmrg 
2241debfc3dSmrg inline unsigned
calculate_allocation(vec_prefix * pfx,unsigned reserve,bool exact)2251debfc3dSmrg vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
2261debfc3dSmrg 				  bool exact)
2271debfc3dSmrg {
2281debfc3dSmrg   if (exact)
2291debfc3dSmrg     return (pfx ? pfx->m_num : 0) + reserve;
2301debfc3dSmrg   else if (!pfx)
2311debfc3dSmrg     return MAX (4, reserve);
2321debfc3dSmrg   return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
2331debfc3dSmrg }
2341debfc3dSmrg 
2351debfc3dSmrg template<typename, typename, typename> struct vec;
2361debfc3dSmrg 
2371debfc3dSmrg /* Valid vector layouts
2381debfc3dSmrg 
2391debfc3dSmrg    vl_embed	- Embeddable vector that uses the trailing array idiom.
2401debfc3dSmrg    vl_ptr	- Space efficient vector that uses a pointer to an
2411debfc3dSmrg 		  embeddable vector.  */
2421debfc3dSmrg struct vl_embed { };
2431debfc3dSmrg struct vl_ptr { };
2441debfc3dSmrg 
2451debfc3dSmrg 
2461debfc3dSmrg /* Types of supported allocations
2471debfc3dSmrg 
2481debfc3dSmrg    va_heap	- Allocation uses malloc/free.
2491debfc3dSmrg    va_gc	- Allocation uses ggc_alloc.
2501debfc3dSmrg    va_gc_atomic	- Same as GC, but individual elements of the array
2511debfc3dSmrg 		  do not need to be marked during collection.  */
2521debfc3dSmrg 
2531debfc3dSmrg /* Allocator type for heap vectors.  */
2541debfc3dSmrg struct va_heap
2551debfc3dSmrg {
2561debfc3dSmrg   /* Heap vectors are frequently regular instances, so use the vl_ptr
2571debfc3dSmrg      layout for them.  */
2581debfc3dSmrg   typedef vl_ptr default_layout;
2591debfc3dSmrg 
2601debfc3dSmrg   template<typename T>
2611debfc3dSmrg   static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
2621debfc3dSmrg 		       CXX_MEM_STAT_INFO);
2631debfc3dSmrg 
2641debfc3dSmrg   template<typename T>
2651debfc3dSmrg   static void release (vec<T, va_heap, vl_embed> *&);
2661debfc3dSmrg };
2671debfc3dSmrg 
2681debfc3dSmrg 
2691debfc3dSmrg /* Allocator for heap memory.  Ensure there are at least RESERVE free
2701debfc3dSmrg    slots in V.  If EXACT is true, grow exactly, else grow
2711debfc3dSmrg    exponentially.  As a special case, if the vector had not been
2721debfc3dSmrg    allocated and RESERVE is 0, no vector will be created.  */
2731debfc3dSmrg 
2741debfc3dSmrg template<typename T>
2751debfc3dSmrg inline void
reserve(vec<T,va_heap,vl_embed> * & v,unsigned reserve,bool exact MEM_STAT_DECL)2761debfc3dSmrg va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
2771debfc3dSmrg 		  MEM_STAT_DECL)
2781debfc3dSmrg {
279c0a68be4Smrg   size_t elt_size = sizeof (T);
2801debfc3dSmrg   unsigned alloc
2811debfc3dSmrg     = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
2821debfc3dSmrg   gcc_checking_assert (alloc);
2831debfc3dSmrg 
2841debfc3dSmrg   if (GATHER_STATISTICS && v)
285c0a68be4Smrg     v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
286c0a68be4Smrg 				  v->allocated (), false);
2871debfc3dSmrg 
2881debfc3dSmrg   size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
2891debfc3dSmrg   unsigned nelem = v ? v->length () : 0;
2901debfc3dSmrg   v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
2911debfc3dSmrg   v->embedded_init (alloc, nelem);
2921debfc3dSmrg 
2931debfc3dSmrg   if (GATHER_STATISTICS)
294c0a68be4Smrg     v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT);
2951debfc3dSmrg }
2961debfc3dSmrg 
2971debfc3dSmrg 
298*8feb0f0bSmrg #if GCC_VERSION >= 4007
299*8feb0f0bSmrg #pragma GCC diagnostic push
300*8feb0f0bSmrg #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
301*8feb0f0bSmrg #endif
302*8feb0f0bSmrg 
3031debfc3dSmrg /* Free the heap space allocated for vector V.  */
3041debfc3dSmrg 
3051debfc3dSmrg template<typename T>
3061debfc3dSmrg void
release(vec<T,va_heap,vl_embed> * & v)3071debfc3dSmrg va_heap::release (vec<T, va_heap, vl_embed> *&v)
3081debfc3dSmrg {
309c0a68be4Smrg   size_t elt_size = sizeof (T);
3101debfc3dSmrg   if (v == NULL)
3111debfc3dSmrg     return;
3121debfc3dSmrg 
3131debfc3dSmrg   if (GATHER_STATISTICS)
314c0a68be4Smrg     v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
315c0a68be4Smrg 				  v->allocated (), true);
3161debfc3dSmrg   ::free (v);
3171debfc3dSmrg   v = NULL;
3181debfc3dSmrg }
3191debfc3dSmrg 
320*8feb0f0bSmrg #if GCC_VERSION >= 4007
321*8feb0f0bSmrg #pragma GCC diagnostic pop
322*8feb0f0bSmrg #endif
3231debfc3dSmrg 
3241debfc3dSmrg /* Allocator type for GC vectors.  Notice that we need the structure
3251debfc3dSmrg    declaration even if GC is not enabled.  */
3261debfc3dSmrg 
3271debfc3dSmrg struct va_gc
3281debfc3dSmrg {
3291debfc3dSmrg   /* Use vl_embed as the default layout for GC vectors.  Due to GTY
3301debfc3dSmrg      limitations, GC vectors must always be pointers, so it is more
3311debfc3dSmrg      efficient to use a pointer to the vl_embed layout, rather than
3321debfc3dSmrg      using a pointer to a pointer as would be the case with vl_ptr.  */
3331debfc3dSmrg   typedef vl_embed default_layout;
3341debfc3dSmrg 
3351debfc3dSmrg   template<typename T, typename A>
3361debfc3dSmrg   static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
3371debfc3dSmrg 		       CXX_MEM_STAT_INFO);
3381debfc3dSmrg 
3391debfc3dSmrg   template<typename T, typename A>
3401debfc3dSmrg   static void release (vec<T, A, vl_embed> *&v);
3411debfc3dSmrg };
3421debfc3dSmrg 
3431debfc3dSmrg 
3441debfc3dSmrg /* Free GC memory used by V and reset V to NULL.  */
3451debfc3dSmrg 
3461debfc3dSmrg template<typename T, typename A>
3471debfc3dSmrg inline void
release(vec<T,A,vl_embed> * & v)3481debfc3dSmrg va_gc::release (vec<T, A, vl_embed> *&v)
3491debfc3dSmrg {
3501debfc3dSmrg   if (v)
3511debfc3dSmrg     ::ggc_free (v);
3521debfc3dSmrg   v = NULL;
3531debfc3dSmrg }
3541debfc3dSmrg 
3551debfc3dSmrg 
3561debfc3dSmrg /* Allocator for GC memory.  Ensure there are at least RESERVE free
3571debfc3dSmrg    slots in V.  If EXACT is true, grow exactly, else grow
3581debfc3dSmrg    exponentially.  As a special case, if the vector had not been
3591debfc3dSmrg    allocated and RESERVE is 0, no vector will be created.  */
3601debfc3dSmrg 
3611debfc3dSmrg template<typename T, typename A>
3621debfc3dSmrg void
reserve(vec<T,A,vl_embed> * & v,unsigned reserve,bool exact MEM_STAT_DECL)3631debfc3dSmrg va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
3641debfc3dSmrg 		MEM_STAT_DECL)
3651debfc3dSmrg {
3661debfc3dSmrg   unsigned alloc
3671debfc3dSmrg     = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
3681debfc3dSmrg   if (!alloc)
3691debfc3dSmrg     {
3701debfc3dSmrg       ::ggc_free (v);
3711debfc3dSmrg       v = NULL;
3721debfc3dSmrg       return;
3731debfc3dSmrg     }
3741debfc3dSmrg 
3751debfc3dSmrg   /* Calculate the amount of space we want.  */
3761debfc3dSmrg   size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
3771debfc3dSmrg 
3781debfc3dSmrg   /* Ask the allocator how much space it will really give us.  */
3791debfc3dSmrg   size = ::ggc_round_alloc_size (size);
3801debfc3dSmrg 
3811debfc3dSmrg   /* Adjust the number of slots accordingly.  */
3821debfc3dSmrg   size_t vec_offset = sizeof (vec_prefix);
3831debfc3dSmrg   size_t elt_size = sizeof (T);
3841debfc3dSmrg   alloc = (size - vec_offset) / elt_size;
3851debfc3dSmrg 
3861debfc3dSmrg   /* And finally, recalculate the amount of space we ask for.  */
3871debfc3dSmrg   size = vec_offset + alloc * elt_size;
3881debfc3dSmrg 
3891debfc3dSmrg   unsigned nelem = v ? v->length () : 0;
3901debfc3dSmrg   v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
3911debfc3dSmrg 							       PASS_MEM_STAT));
3921debfc3dSmrg   v->embedded_init (alloc, nelem);
3931debfc3dSmrg }
3941debfc3dSmrg 
3951debfc3dSmrg 
3961debfc3dSmrg /* Allocator type for GC vectors.  This is for vectors of types
3971debfc3dSmrg    atomics w.r.t. collection, so allocation and deallocation is
3981debfc3dSmrg    completely inherited from va_gc.  */
3991debfc3dSmrg struct va_gc_atomic : va_gc
4001debfc3dSmrg {
4011debfc3dSmrg };
4021debfc3dSmrg 
4031debfc3dSmrg 
4041debfc3dSmrg /* Generic vector template.  Default values for A and L indicate the
4051debfc3dSmrg    most commonly used strategies.
4061debfc3dSmrg 
4071debfc3dSmrg    FIXME - Ideally, they would all be vl_ptr to encourage using regular
4081debfc3dSmrg            instances for vectors, but the existing GTY machinery is limited
4091debfc3dSmrg 	   in that it can only deal with GC objects that are pointers
4101debfc3dSmrg 	   themselves.
4111debfc3dSmrg 
4121debfc3dSmrg 	   This means that vector operations that need to deal with
4131debfc3dSmrg 	   potentially NULL pointers, must be provided as free
4141debfc3dSmrg 	   functions (see the vec_safe_* functions above).  */
4151debfc3dSmrg template<typename T,
4161debfc3dSmrg          typename A = va_heap,
4171debfc3dSmrg          typename L = typename A::default_layout>
4181debfc3dSmrg struct GTY((user)) vec
4191debfc3dSmrg {
4201debfc3dSmrg };
4211debfc3dSmrg 
422a2dc1f3fSmrg /* Generic vec<> debug helpers.
423a2dc1f3fSmrg 
424a2dc1f3fSmrg    These need to be instantiated for each vec<TYPE> used throughout
425a2dc1f3fSmrg    the compiler like this:
426a2dc1f3fSmrg 
427a2dc1f3fSmrg     DEFINE_DEBUG_VEC (TYPE)
428a2dc1f3fSmrg 
429a2dc1f3fSmrg    The reason we have a debug_helper() is because GDB can't
430a2dc1f3fSmrg    disambiguate a plain call to debug(some_vec), and it must be called
431a2dc1f3fSmrg    like debug<TYPE>(some_vec).  */
432a2dc1f3fSmrg 
433a2dc1f3fSmrg template<typename T>
434a2dc1f3fSmrg void
debug_helper(vec<T> & ref)435a2dc1f3fSmrg debug_helper (vec<T> &ref)
436a2dc1f3fSmrg {
437a2dc1f3fSmrg   unsigned i;
438a2dc1f3fSmrg   for (i = 0; i < ref.length (); ++i)
439a2dc1f3fSmrg     {
440a2dc1f3fSmrg       fprintf (stderr, "[%d] = ", i);
441a2dc1f3fSmrg       debug_slim (ref[i]);
442a2dc1f3fSmrg       fputc ('\n', stderr);
443a2dc1f3fSmrg     }
444a2dc1f3fSmrg }
445a2dc1f3fSmrg 
446a2dc1f3fSmrg /* We need a separate va_gc variant here because default template
447a2dc1f3fSmrg    argument for functions cannot be used in c++-98.  Once this
448a2dc1f3fSmrg    restriction is removed, those variant should be folded with the
449a2dc1f3fSmrg    above debug_helper.  */
450a2dc1f3fSmrg 
451a2dc1f3fSmrg template<typename T>
452a2dc1f3fSmrg void
debug_helper(vec<T,va_gc> & ref)453a2dc1f3fSmrg debug_helper (vec<T, va_gc> &ref)
454a2dc1f3fSmrg {
455a2dc1f3fSmrg   unsigned i;
456a2dc1f3fSmrg   for (i = 0; i < ref.length (); ++i)
457a2dc1f3fSmrg     {
458a2dc1f3fSmrg       fprintf (stderr, "[%d] = ", i);
459a2dc1f3fSmrg       debug_slim (ref[i]);
460a2dc1f3fSmrg       fputc ('\n', stderr);
461a2dc1f3fSmrg     }
462a2dc1f3fSmrg }
463a2dc1f3fSmrg 
464a2dc1f3fSmrg /* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper
465a2dc1f3fSmrg    functions for a type T.  */
466a2dc1f3fSmrg 
467a2dc1f3fSmrg #define DEFINE_DEBUG_VEC(T) \
468a2dc1f3fSmrg   template void debug_helper (vec<T> &);		\
469a2dc1f3fSmrg   template void debug_helper (vec<T, va_gc> &);		\
470a2dc1f3fSmrg   /* Define the vec<T> debug functions.  */		\
471a2dc1f3fSmrg   DEBUG_FUNCTION void					\
472a2dc1f3fSmrg   debug (vec<T> &ref)					\
473a2dc1f3fSmrg   {							\
474a2dc1f3fSmrg     debug_helper <T> (ref);				\
475a2dc1f3fSmrg   }							\
476a2dc1f3fSmrg   DEBUG_FUNCTION void					\
477a2dc1f3fSmrg   debug (vec<T> *ptr)					\
478a2dc1f3fSmrg   {							\
479a2dc1f3fSmrg     if (ptr)						\
480a2dc1f3fSmrg       debug (*ptr);					\
481a2dc1f3fSmrg     else						\
482a2dc1f3fSmrg       fprintf (stderr, "<nil>\n");			\
483a2dc1f3fSmrg   }							\
484a2dc1f3fSmrg   /* Define the vec<T, va_gc> debug functions.  */	\
485a2dc1f3fSmrg   DEBUG_FUNCTION void					\
486a2dc1f3fSmrg   debug (vec<T, va_gc> &ref)				\
487a2dc1f3fSmrg   {							\
488a2dc1f3fSmrg     debug_helper <T> (ref);				\
489a2dc1f3fSmrg   }							\
490a2dc1f3fSmrg   DEBUG_FUNCTION void					\
491a2dc1f3fSmrg   debug (vec<T, va_gc> *ptr)				\
492a2dc1f3fSmrg   {							\
493a2dc1f3fSmrg     if (ptr)						\
494a2dc1f3fSmrg       debug (*ptr);					\
495a2dc1f3fSmrg     else						\
496a2dc1f3fSmrg       fprintf (stderr, "<nil>\n");			\
497a2dc1f3fSmrg   }
498a2dc1f3fSmrg 
499a2dc1f3fSmrg /* Default-construct N elements in DST.  */
500a2dc1f3fSmrg 
501a2dc1f3fSmrg template <typename T>
502a2dc1f3fSmrg inline void
vec_default_construct(T * dst,unsigned n)503a2dc1f3fSmrg vec_default_construct (T *dst, unsigned n)
504a2dc1f3fSmrg {
505a2dc1f3fSmrg #ifdef BROKEN_VALUE_INITIALIZATION
506a2dc1f3fSmrg   /* Versions of GCC before 4.4 sometimes leave certain objects
507a2dc1f3fSmrg      uninitialized when value initialized, though if the type has
508a2dc1f3fSmrg      user defined default ctor, that ctor is invoked.  As a workaround
509a2dc1f3fSmrg      perform clearing first and then the value initialization, which
510a2dc1f3fSmrg      fixes the case when value initialization doesn't initialize due to
511a2dc1f3fSmrg      the bugs and should initialize to all zeros, but still allows
512a2dc1f3fSmrg      vectors for types with user defined default ctor that initializes
513a2dc1f3fSmrg      some or all elements to non-zero.  If T has no user defined
514a2dc1f3fSmrg      default ctor and some non-static data members have user defined
515a2dc1f3fSmrg      default ctors that initialize to non-zero the workaround will
516a2dc1f3fSmrg      still not work properly; in that case we just need to provide
517a2dc1f3fSmrg      user defined default ctor.  */
518a2dc1f3fSmrg   memset (dst, '\0', sizeof (T) * n);
519a2dc1f3fSmrg #endif
520a2dc1f3fSmrg   for ( ; n; ++dst, --n)
521a2dc1f3fSmrg     ::new (static_cast<void*>(dst)) T ();
522a2dc1f3fSmrg }
523a2dc1f3fSmrg 
524a2dc1f3fSmrg /* Copy-construct N elements in DST from *SRC.  */
525a2dc1f3fSmrg 
526a2dc1f3fSmrg template <typename T>
527a2dc1f3fSmrg inline void
vec_copy_construct(T * dst,const T * src,unsigned n)528a2dc1f3fSmrg vec_copy_construct (T *dst, const T *src, unsigned n)
529a2dc1f3fSmrg {
530a2dc1f3fSmrg   for ( ; n; ++dst, ++src, --n)
531a2dc1f3fSmrg     ::new (static_cast<void*>(dst)) T (*src);
532a2dc1f3fSmrg }
533a2dc1f3fSmrg 
5341debfc3dSmrg /* Type to provide NULL values for vec<T, A, L>.  This is used to
5351debfc3dSmrg    provide nil initializers for vec instances.  Since vec must be
5361debfc3dSmrg    a POD, we cannot have proper ctor/dtor for it.  To initialize
5371debfc3dSmrg    a vec instance, you can assign it the value vNULL.  This isn't
5381debfc3dSmrg    needed for file-scope and function-local static vectors, which
5391debfc3dSmrg    are zero-initialized by default.  */
5401debfc3dSmrg struct vnull
5411debfc3dSmrg {
5421debfc3dSmrg   template <typename T, typename A, typename L>
543a2dc1f3fSmrg   CONSTEXPR operator vec<T, A, L> () { return vec<T, A, L>(); }
5441debfc3dSmrg };
5451debfc3dSmrg extern vnull vNULL;
5461debfc3dSmrg 
5471debfc3dSmrg 
5481debfc3dSmrg /* Embeddable vector.  These vectors are suitable to be embedded
5491debfc3dSmrg    in other data structures so that they can be pre-allocated in a
5501debfc3dSmrg    contiguous memory block.
5511debfc3dSmrg 
5521debfc3dSmrg    Embeddable vectors are implemented using the trailing array idiom,
5531debfc3dSmrg    thus they are not resizeable without changing the address of the
5541debfc3dSmrg    vector object itself.  This means you cannot have variables or
5551debfc3dSmrg    fields of embeddable vector type -- always use a pointer to a
5561debfc3dSmrg    vector.  The one exception is the final field of a structure, which
5571debfc3dSmrg    could be a vector type.
5581debfc3dSmrg 
5591debfc3dSmrg    You will have to use the embedded_size & embedded_init calls to
5601debfc3dSmrg    create such objects, and they will not be resizeable (so the 'safe'
5611debfc3dSmrg    allocation variants are not available).
5621debfc3dSmrg 
5631debfc3dSmrg    Properties:
5641debfc3dSmrg 
5651debfc3dSmrg 	- The whole vector and control data are allocated in a single
5661debfc3dSmrg 	  contiguous block.  It uses the trailing-vector idiom, so
5671debfc3dSmrg 	  allocation must reserve enough space for all the elements
5681debfc3dSmrg   	  in the vector plus its control data.
5691debfc3dSmrg   	- The vector cannot be re-allocated.
5701debfc3dSmrg   	- The vector cannot grow nor shrink.
5711debfc3dSmrg   	- No indirections needed for access/manipulation.
5721debfc3dSmrg   	- It requires 2 words of storage (prior to vector allocation).  */
5731debfc3dSmrg 
5741debfc3dSmrg template<typename T, typename A>
5751debfc3dSmrg struct GTY((user)) vec<T, A, vl_embed>
5761debfc3dSmrg {
5771debfc3dSmrg public:
5781debfc3dSmrg   unsigned allocated (void) const { return m_vecpfx.m_alloc; }
5791debfc3dSmrg   unsigned length (void) const { return m_vecpfx.m_num; }
5801debfc3dSmrg   bool is_empty (void) const { return m_vecpfx.m_num == 0; }
5811debfc3dSmrg   T *address (void) { return m_vecdata; }
5821debfc3dSmrg   const T *address (void) const { return m_vecdata; }
5831debfc3dSmrg   T *begin () { return address (); }
5841debfc3dSmrg   const T *begin () const { return address (); }
5851debfc3dSmrg   T *end () { return address () + length (); }
5861debfc3dSmrg   const T *end () const { return address () + length (); }
5871debfc3dSmrg   const T &operator[] (unsigned) const;
5881debfc3dSmrg   T &operator[] (unsigned);
5891debfc3dSmrg   T &last (void);
5901debfc3dSmrg   bool space (unsigned) const;
5911debfc3dSmrg   bool iterate (unsigned, T *) const;
5921debfc3dSmrg   bool iterate (unsigned, T **) const;
5931debfc3dSmrg   vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
5941debfc3dSmrg   void splice (const vec &);
5951debfc3dSmrg   void splice (const vec *src);
5961debfc3dSmrg   T *quick_push (const T &);
5971debfc3dSmrg   T &pop (void);
5981debfc3dSmrg   void truncate (unsigned);
5991debfc3dSmrg   void quick_insert (unsigned, const T &);
6001debfc3dSmrg   void ordered_remove (unsigned);
6011debfc3dSmrg   void unordered_remove (unsigned);
6021debfc3dSmrg   void block_remove (unsigned, unsigned);
6031debfc3dSmrg   void qsort (int (*) (const void *, const void *));
604*8feb0f0bSmrg   void sort (int (*) (const void *, const void *, void *), void *);
6051debfc3dSmrg   T *bsearch (const void *key, int (*compar)(const void *, const void *));
606*8feb0f0bSmrg   T *bsearch (const void *key,
607*8feb0f0bSmrg 	      int (*compar)(const void *, const void *, void *), void *);
6081debfc3dSmrg   unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
6091debfc3dSmrg   bool contains (const T &search) const;
6101debfc3dSmrg   static size_t embedded_size (unsigned);
6111debfc3dSmrg   void embedded_init (unsigned, unsigned = 0, unsigned = 0);
6121debfc3dSmrg   void quick_grow (unsigned len);
6131debfc3dSmrg   void quick_grow_cleared (unsigned len);
6141debfc3dSmrg 
6151debfc3dSmrg   /* vec class can access our internal data and functions.  */
6161debfc3dSmrg   template <typename, typename, typename> friend struct vec;
6171debfc3dSmrg 
6181debfc3dSmrg   /* The allocator types also need access to our internals.  */
6191debfc3dSmrg   friend struct va_gc;
6201debfc3dSmrg   friend struct va_gc_atomic;
6211debfc3dSmrg   friend struct va_heap;
6221debfc3dSmrg 
6231debfc3dSmrg   /* FIXME - These fields should be private, but we need to cater to
6241debfc3dSmrg 	     compilers that have stricter notions of PODness for types.  */
6251debfc3dSmrg   vec_prefix m_vecpfx;
6261debfc3dSmrg   T m_vecdata[1];
6271debfc3dSmrg };
6281debfc3dSmrg 
6291debfc3dSmrg 
6301debfc3dSmrg /* Convenience wrapper functions to use when dealing with pointers to
6311debfc3dSmrg    embedded vectors.  Some functionality for these vectors must be
6321debfc3dSmrg    provided via free functions for these reasons:
6331debfc3dSmrg 
6341debfc3dSmrg 	1- The pointer may be NULL (e.g., before initial allocation).
6351debfc3dSmrg 
6361debfc3dSmrg   	2- When the vector needs to grow, it must be reallocated, so
6371debfc3dSmrg   	   the pointer will change its value.
6381debfc3dSmrg 
6391debfc3dSmrg    Because of limitations with the current GC machinery, all vectors
6401debfc3dSmrg    in GC memory *must* be pointers.  */
6411debfc3dSmrg 
6421debfc3dSmrg 
6431debfc3dSmrg /* If V contains no room for NELEMS elements, return false. Otherwise,
6441debfc3dSmrg    return true.  */
6451debfc3dSmrg template<typename T, typename A>
6461debfc3dSmrg inline bool
6471debfc3dSmrg vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
6481debfc3dSmrg {
6491debfc3dSmrg   return v ? v->space (nelems) : nelems == 0;
6501debfc3dSmrg }
6511debfc3dSmrg 
6521debfc3dSmrg 
6531debfc3dSmrg /* If V is NULL, return 0.  Otherwise, return V->length().  */
6541debfc3dSmrg template<typename T, typename A>
6551debfc3dSmrg inline unsigned
6561debfc3dSmrg vec_safe_length (const vec<T, A, vl_embed> *v)
6571debfc3dSmrg {
6581debfc3dSmrg   return v ? v->length () : 0;
6591debfc3dSmrg }
6601debfc3dSmrg 
6611debfc3dSmrg 
6621debfc3dSmrg /* If V is NULL, return NULL.  Otherwise, return V->address().  */
6631debfc3dSmrg template<typename T, typename A>
6641debfc3dSmrg inline T *
6651debfc3dSmrg vec_safe_address (vec<T, A, vl_embed> *v)
6661debfc3dSmrg {
6671debfc3dSmrg   return v ? v->address () : NULL;
6681debfc3dSmrg }
6691debfc3dSmrg 
6701debfc3dSmrg 
6711debfc3dSmrg /* If V is NULL, return true.  Otherwise, return V->is_empty().  */
6721debfc3dSmrg template<typename T, typename A>
6731debfc3dSmrg inline bool
6741debfc3dSmrg vec_safe_is_empty (vec<T, A, vl_embed> *v)
6751debfc3dSmrg {
6761debfc3dSmrg   return v ? v->is_empty () : true;
6771debfc3dSmrg }
6781debfc3dSmrg 
6791debfc3dSmrg /* If V does not have space for NELEMS elements, call
6801debfc3dSmrg    V->reserve(NELEMS, EXACT).  */
6811debfc3dSmrg template<typename T, typename A>
6821debfc3dSmrg inline bool
6831debfc3dSmrg vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
6841debfc3dSmrg 		  CXX_MEM_STAT_INFO)
6851debfc3dSmrg {
6861debfc3dSmrg   bool extend = nelems ? !vec_safe_space (v, nelems) : false;
6871debfc3dSmrg   if (extend)
6881debfc3dSmrg     A::reserve (v, nelems, exact PASS_MEM_STAT);
6891debfc3dSmrg   return extend;
6901debfc3dSmrg }
6911debfc3dSmrg 
6921debfc3dSmrg template<typename T, typename A>
6931debfc3dSmrg inline bool
6941debfc3dSmrg vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
6951debfc3dSmrg 			CXX_MEM_STAT_INFO)
6961debfc3dSmrg {
6971debfc3dSmrg   return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
6981debfc3dSmrg }
6991debfc3dSmrg 
7001debfc3dSmrg 
7011debfc3dSmrg /* Allocate GC memory for V with space for NELEMS slots.  If NELEMS
7021debfc3dSmrg    is 0, V is initialized to NULL.  */
7031debfc3dSmrg 
7041debfc3dSmrg template<typename T, typename A>
7051debfc3dSmrg inline void
7061debfc3dSmrg vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
7071debfc3dSmrg {
7081debfc3dSmrg   v = NULL;
7091debfc3dSmrg   vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
7101debfc3dSmrg }
7111debfc3dSmrg 
7121debfc3dSmrg 
7131debfc3dSmrg /* Free the GC memory allocated by vector V and set it to NULL.  */
7141debfc3dSmrg 
7151debfc3dSmrg template<typename T, typename A>
7161debfc3dSmrg inline void
7171debfc3dSmrg vec_free (vec<T, A, vl_embed> *&v)
7181debfc3dSmrg {
7191debfc3dSmrg   A::release (v);
7201debfc3dSmrg }
7211debfc3dSmrg 
7221debfc3dSmrg 
7231debfc3dSmrg /* Grow V to length LEN.  Allocate it, if necessary.  */
7241debfc3dSmrg template<typename T, typename A>
7251debfc3dSmrg inline void
7261debfc3dSmrg vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
7271debfc3dSmrg {
7281debfc3dSmrg   unsigned oldlen = vec_safe_length (v);
7291debfc3dSmrg   gcc_checking_assert (len >= oldlen);
7301debfc3dSmrg   vec_safe_reserve_exact (v, len - oldlen PASS_MEM_STAT);
7311debfc3dSmrg   v->quick_grow (len);
7321debfc3dSmrg }
7331debfc3dSmrg 
7341debfc3dSmrg 
7351debfc3dSmrg /* If V is NULL, allocate it.  Call V->safe_grow_cleared(LEN).  */
7361debfc3dSmrg template<typename T, typename A>
7371debfc3dSmrg inline void
7381debfc3dSmrg vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len CXX_MEM_STAT_INFO)
7391debfc3dSmrg {
7401debfc3dSmrg   unsigned oldlen = vec_safe_length (v);
7411debfc3dSmrg   vec_safe_grow (v, len PASS_MEM_STAT);
742a2dc1f3fSmrg   vec_default_construct (v->address () + oldlen, len - oldlen);
7431debfc3dSmrg }
7441debfc3dSmrg 
7451debfc3dSmrg 
746c0a68be4Smrg /* Assume V is not NULL.  */
747c0a68be4Smrg 
748c0a68be4Smrg template<typename T>
749c0a68be4Smrg inline void
750c0a68be4Smrg vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
751c0a68be4Smrg 		       unsigned len CXX_MEM_STAT_INFO)
752c0a68be4Smrg {
753c0a68be4Smrg   v->safe_grow_cleared (len PASS_MEM_STAT);
754c0a68be4Smrg }
755c0a68be4Smrg 
756*8feb0f0bSmrg /* If V does not have space for NELEMS elements, call
757*8feb0f0bSmrg    V->reserve(NELEMS, EXACT).  */
758*8feb0f0bSmrg 
759*8feb0f0bSmrg template<typename T>
760*8feb0f0bSmrg inline bool
761*8feb0f0bSmrg vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
762*8feb0f0bSmrg 		  CXX_MEM_STAT_INFO)
763*8feb0f0bSmrg {
764*8feb0f0bSmrg   return v->reserve (nelems, exact);
765*8feb0f0bSmrg }
766*8feb0f0bSmrg 
767c0a68be4Smrg 
7681debfc3dSmrg /* If V is NULL return false, otherwise return V->iterate(IX, PTR).  */
7691debfc3dSmrg template<typename T, typename A>
7701debfc3dSmrg inline bool
7711debfc3dSmrg vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
7721debfc3dSmrg {
7731debfc3dSmrg   if (v)
7741debfc3dSmrg     return v->iterate (ix, ptr);
7751debfc3dSmrg   else
7761debfc3dSmrg     {
7771debfc3dSmrg       *ptr = 0;
7781debfc3dSmrg       return false;
7791debfc3dSmrg     }
7801debfc3dSmrg }
7811debfc3dSmrg 
7821debfc3dSmrg template<typename T, typename A>
7831debfc3dSmrg inline bool
7841debfc3dSmrg vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
7851debfc3dSmrg {
7861debfc3dSmrg   if (v)
7871debfc3dSmrg     return v->iterate (ix, ptr);
7881debfc3dSmrg   else
7891debfc3dSmrg     {
7901debfc3dSmrg       *ptr = 0;
7911debfc3dSmrg       return false;
7921debfc3dSmrg     }
7931debfc3dSmrg }
7941debfc3dSmrg 
7951debfc3dSmrg 
7961debfc3dSmrg /* If V has no room for one more element, reallocate it.  Then call
7971debfc3dSmrg    V->quick_push(OBJ).  */
7981debfc3dSmrg template<typename T, typename A>
7991debfc3dSmrg inline T *
8001debfc3dSmrg vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
8011debfc3dSmrg {
8021debfc3dSmrg   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
8031debfc3dSmrg   return v->quick_push (obj);
8041debfc3dSmrg }
8051debfc3dSmrg 
8061debfc3dSmrg 
8071debfc3dSmrg /* if V has no room for one more element, reallocate it.  Then call
8081debfc3dSmrg    V->quick_insert(IX, OBJ).  */
8091debfc3dSmrg template<typename T, typename A>
8101debfc3dSmrg inline void
8111debfc3dSmrg vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
8121debfc3dSmrg 		 CXX_MEM_STAT_INFO)
8131debfc3dSmrg {
8141debfc3dSmrg   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
8151debfc3dSmrg   v->quick_insert (ix, obj);
8161debfc3dSmrg }
8171debfc3dSmrg 
8181debfc3dSmrg 
8191debfc3dSmrg /* If V is NULL, do nothing.  Otherwise, call V->truncate(SIZE).  */
8201debfc3dSmrg template<typename T, typename A>
8211debfc3dSmrg inline void
8221debfc3dSmrg vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
8231debfc3dSmrg {
8241debfc3dSmrg   if (v)
8251debfc3dSmrg     v->truncate (size);
8261debfc3dSmrg }
8271debfc3dSmrg 
8281debfc3dSmrg 
8291debfc3dSmrg /* If SRC is not NULL, return a pointer to a copy of it.  */
8301debfc3dSmrg template<typename T, typename A>
8311debfc3dSmrg inline vec<T, A, vl_embed> *
8321debfc3dSmrg vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
8331debfc3dSmrg {
8341debfc3dSmrg   return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL;
8351debfc3dSmrg }
8361debfc3dSmrg 
8371debfc3dSmrg /* Copy the elements from SRC to the end of DST as if by memcpy.
8381debfc3dSmrg    Reallocate DST, if necessary.  */
8391debfc3dSmrg template<typename T, typename A>
8401debfc3dSmrg inline void
8411debfc3dSmrg vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
8421debfc3dSmrg 		 CXX_MEM_STAT_INFO)
8431debfc3dSmrg {
8441debfc3dSmrg   unsigned src_len = vec_safe_length (src);
8451debfc3dSmrg   if (src_len)
8461debfc3dSmrg     {
8471debfc3dSmrg       vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
8481debfc3dSmrg 			      PASS_MEM_STAT);
8491debfc3dSmrg       dst->splice (*src);
8501debfc3dSmrg     }
8511debfc3dSmrg }
8521debfc3dSmrg 
8531debfc3dSmrg /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
8541debfc3dSmrg    size of the vector and so should be used with care.  */
8551debfc3dSmrg 
8561debfc3dSmrg template<typename T, typename A>
8571debfc3dSmrg inline bool
8581debfc3dSmrg vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
8591debfc3dSmrg {
8601debfc3dSmrg   return v ? v->contains (search) : false;
8611debfc3dSmrg }
8621debfc3dSmrg 
8631debfc3dSmrg /* Index into vector.  Return the IX'th element.  IX must be in the
8641debfc3dSmrg    domain of the vector.  */
8651debfc3dSmrg 
8661debfc3dSmrg template<typename T, typename A>
8671debfc3dSmrg inline const T &
8681debfc3dSmrg vec<T, A, vl_embed>::operator[] (unsigned ix) const
8691debfc3dSmrg {
8701debfc3dSmrg   gcc_checking_assert (ix < m_vecpfx.m_num);
8711debfc3dSmrg   return m_vecdata[ix];
8721debfc3dSmrg }
8731debfc3dSmrg 
8741debfc3dSmrg template<typename T, typename A>
8751debfc3dSmrg inline T &
8761debfc3dSmrg vec<T, A, vl_embed>::operator[] (unsigned ix)
8771debfc3dSmrg {
8781debfc3dSmrg   gcc_checking_assert (ix < m_vecpfx.m_num);
8791debfc3dSmrg   return m_vecdata[ix];
8801debfc3dSmrg }
8811debfc3dSmrg 
8821debfc3dSmrg 
8831debfc3dSmrg /* Get the final element of the vector, which must not be empty.  */
8841debfc3dSmrg 
8851debfc3dSmrg template<typename T, typename A>
8861debfc3dSmrg inline T &
8871debfc3dSmrg vec<T, A, vl_embed>::last (void)
8881debfc3dSmrg {
8891debfc3dSmrg   gcc_checking_assert (m_vecpfx.m_num > 0);
8901debfc3dSmrg   return (*this)[m_vecpfx.m_num - 1];
8911debfc3dSmrg }
8921debfc3dSmrg 
8931debfc3dSmrg 
8941debfc3dSmrg /* If this vector has space for NELEMS additional entries, return
8951debfc3dSmrg    true.  You usually only need to use this if you are doing your
8961debfc3dSmrg    own vector reallocation, for instance on an embedded vector.  This
8971debfc3dSmrg    returns true in exactly the same circumstances that vec::reserve
8981debfc3dSmrg    will.  */
8991debfc3dSmrg 
9001debfc3dSmrg template<typename T, typename A>
9011debfc3dSmrg inline bool
9021debfc3dSmrg vec<T, A, vl_embed>::space (unsigned nelems) const
9031debfc3dSmrg {
9041debfc3dSmrg   return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
9051debfc3dSmrg }
9061debfc3dSmrg 
9071debfc3dSmrg 
9081debfc3dSmrg /* Return iteration condition and update PTR to point to the IX'th
9091debfc3dSmrg    element of this vector.  Use this to iterate over the elements of a
9101debfc3dSmrg    vector as follows,
9111debfc3dSmrg 
9121debfc3dSmrg      for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++)
9131debfc3dSmrg        continue;  */
9141debfc3dSmrg 
9151debfc3dSmrg template<typename T, typename A>
9161debfc3dSmrg inline bool
9171debfc3dSmrg vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
9181debfc3dSmrg {
9191debfc3dSmrg   if (ix < m_vecpfx.m_num)
9201debfc3dSmrg     {
9211debfc3dSmrg       *ptr = m_vecdata[ix];
9221debfc3dSmrg       return true;
9231debfc3dSmrg     }
9241debfc3dSmrg   else
9251debfc3dSmrg     {
9261debfc3dSmrg       *ptr = 0;
9271debfc3dSmrg       return false;
9281debfc3dSmrg     }
9291debfc3dSmrg }
9301debfc3dSmrg 
9311debfc3dSmrg 
9321debfc3dSmrg /* Return iteration condition and update *PTR to point to the
9331debfc3dSmrg    IX'th element of this vector.  Use this to iterate over the
9341debfc3dSmrg    elements of a vector as follows,
9351debfc3dSmrg 
9361debfc3dSmrg      for (ix = 0; v->iterate (ix, &ptr); ix++)
9371debfc3dSmrg        continue;
9381debfc3dSmrg 
9391debfc3dSmrg    This variant is for vectors of objects.  */
9401debfc3dSmrg 
9411debfc3dSmrg template<typename T, typename A>
9421debfc3dSmrg inline bool
9431debfc3dSmrg vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
9441debfc3dSmrg {
9451debfc3dSmrg   if (ix < m_vecpfx.m_num)
9461debfc3dSmrg     {
9471debfc3dSmrg       *ptr = CONST_CAST (T *, &m_vecdata[ix]);
9481debfc3dSmrg       return true;
9491debfc3dSmrg     }
9501debfc3dSmrg   else
9511debfc3dSmrg     {
9521debfc3dSmrg       *ptr = 0;
9531debfc3dSmrg       return false;
9541debfc3dSmrg     }
9551debfc3dSmrg }
9561debfc3dSmrg 
9571debfc3dSmrg 
9581debfc3dSmrg /* Return a pointer to a copy of this vector.  */
9591debfc3dSmrg 
9601debfc3dSmrg template<typename T, typename A>
9611debfc3dSmrg inline vec<T, A, vl_embed> *
9621debfc3dSmrg vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
9631debfc3dSmrg {
9641debfc3dSmrg   vec<T, A, vl_embed> *new_vec = NULL;
9651debfc3dSmrg   unsigned len = length ();
9661debfc3dSmrg   if (len)
9671debfc3dSmrg     {
9681debfc3dSmrg       vec_alloc (new_vec, len PASS_MEM_STAT);
9691debfc3dSmrg       new_vec->embedded_init (len, len);
970a2dc1f3fSmrg       vec_copy_construct (new_vec->address (), m_vecdata, len);
9711debfc3dSmrg     }
9721debfc3dSmrg   return new_vec;
9731debfc3dSmrg }
9741debfc3dSmrg 
9751debfc3dSmrg 
9761debfc3dSmrg /* Copy the elements from SRC to the end of this vector as if by memcpy.
9771debfc3dSmrg    The vector must have sufficient headroom available.  */
9781debfc3dSmrg 
9791debfc3dSmrg template<typename T, typename A>
9801debfc3dSmrg inline void
9811debfc3dSmrg vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
9821debfc3dSmrg {
9831debfc3dSmrg   unsigned len = src.length ();
9841debfc3dSmrg   if (len)
9851debfc3dSmrg     {
9861debfc3dSmrg       gcc_checking_assert (space (len));
987a2dc1f3fSmrg       vec_copy_construct (end (), src.address (), len);
9881debfc3dSmrg       m_vecpfx.m_num += len;
9891debfc3dSmrg     }
9901debfc3dSmrg }
9911debfc3dSmrg 
9921debfc3dSmrg template<typename T, typename A>
9931debfc3dSmrg inline void
9941debfc3dSmrg vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
9951debfc3dSmrg {
9961debfc3dSmrg   if (src)
9971debfc3dSmrg     splice (*src);
9981debfc3dSmrg }
9991debfc3dSmrg 
10001debfc3dSmrg 
10011debfc3dSmrg /* Push OBJ (a new element) onto the end of the vector.  There must be
10021debfc3dSmrg    sufficient space in the vector.  Return a pointer to the slot
10031debfc3dSmrg    where OBJ was inserted.  */
10041debfc3dSmrg 
10051debfc3dSmrg template<typename T, typename A>
10061debfc3dSmrg inline T *
10071debfc3dSmrg vec<T, A, vl_embed>::quick_push (const T &obj)
10081debfc3dSmrg {
10091debfc3dSmrg   gcc_checking_assert (space (1));
10101debfc3dSmrg   T *slot = &m_vecdata[m_vecpfx.m_num++];
10111debfc3dSmrg   *slot = obj;
10121debfc3dSmrg   return slot;
10131debfc3dSmrg }
10141debfc3dSmrg 
10151debfc3dSmrg 
10161debfc3dSmrg /* Pop and return the last element off the end of the vector.  */
10171debfc3dSmrg 
10181debfc3dSmrg template<typename T, typename A>
10191debfc3dSmrg inline T &
10201debfc3dSmrg vec<T, A, vl_embed>::pop (void)
10211debfc3dSmrg {
10221debfc3dSmrg   gcc_checking_assert (length () > 0);
10231debfc3dSmrg   return m_vecdata[--m_vecpfx.m_num];
10241debfc3dSmrg }
10251debfc3dSmrg 
10261debfc3dSmrg 
10271debfc3dSmrg /* Set the length of the vector to SIZE.  The new length must be less
10281debfc3dSmrg    than or equal to the current length.  This is an O(1) operation.  */
10291debfc3dSmrg 
10301debfc3dSmrg template<typename T, typename A>
10311debfc3dSmrg inline void
10321debfc3dSmrg vec<T, A, vl_embed>::truncate (unsigned size)
10331debfc3dSmrg {
10341debfc3dSmrg   gcc_checking_assert (length () >= size);
10351debfc3dSmrg   m_vecpfx.m_num = size;
10361debfc3dSmrg }
10371debfc3dSmrg 
10381debfc3dSmrg 
10391debfc3dSmrg /* Insert an element, OBJ, at the IXth position of this vector.  There
10401debfc3dSmrg    must be sufficient space.  */
10411debfc3dSmrg 
10421debfc3dSmrg template<typename T, typename A>
10431debfc3dSmrg inline void
10441debfc3dSmrg vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
10451debfc3dSmrg {
10461debfc3dSmrg   gcc_checking_assert (length () < allocated ());
10471debfc3dSmrg   gcc_checking_assert (ix <= length ());
10481debfc3dSmrg   T *slot = &m_vecdata[ix];
10491debfc3dSmrg   memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
10501debfc3dSmrg   *slot = obj;
10511debfc3dSmrg }
10521debfc3dSmrg 
10531debfc3dSmrg 
10541debfc3dSmrg /* Remove an element from the IXth position of this vector.  Ordering of
10551debfc3dSmrg    remaining elements is preserved.  This is an O(N) operation due to
10561debfc3dSmrg    memmove.  */
10571debfc3dSmrg 
10581debfc3dSmrg template<typename T, typename A>
10591debfc3dSmrg inline void
10601debfc3dSmrg vec<T, A, vl_embed>::ordered_remove (unsigned ix)
10611debfc3dSmrg {
10621debfc3dSmrg   gcc_checking_assert (ix < length ());
10631debfc3dSmrg   T *slot = &m_vecdata[ix];
10641debfc3dSmrg   memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
10651debfc3dSmrg }
10661debfc3dSmrg 
10671debfc3dSmrg 
1068c0a68be4Smrg /* Remove elements in [START, END) from VEC for which COND holds.  Ordering of
1069c0a68be4Smrg    remaining elements is preserved.  This is an O(N) operation.  */
1070c0a68be4Smrg 
1071c0a68be4Smrg #define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index,	\
1072c0a68be4Smrg 				      elem_ptr, start, end, cond)	\
1073c0a68be4Smrg   {									\
1074c0a68be4Smrg     gcc_assert ((end) <= (vec).length ());				\
1075c0a68be4Smrg     for (read_index = write_index = (start); read_index < (end);	\
1076c0a68be4Smrg 	 ++read_index)							\
1077c0a68be4Smrg       {									\
1078c0a68be4Smrg 	elem_ptr = &(vec)[read_index];					\
1079c0a68be4Smrg 	bool remove_p = (cond);						\
1080c0a68be4Smrg 	if (remove_p)							\
1081c0a68be4Smrg 	  continue;							\
1082c0a68be4Smrg 									\
1083c0a68be4Smrg 	if (read_index != write_index)					\
1084c0a68be4Smrg 	  (vec)[write_index] = (vec)[read_index];			\
1085c0a68be4Smrg 									\
1086c0a68be4Smrg 	write_index++;							\
1087c0a68be4Smrg       }									\
1088c0a68be4Smrg 									\
1089c0a68be4Smrg     if (read_index - write_index > 0)					\
1090c0a68be4Smrg       (vec).block_remove (write_index, read_index - write_index);	\
1091c0a68be4Smrg   }
1092c0a68be4Smrg 
1093c0a68be4Smrg 
1094c0a68be4Smrg /* Remove elements from VEC for which COND holds.  Ordering of remaining
1095c0a68be4Smrg    elements is preserved.  This is an O(N) operation.  */
1096c0a68be4Smrg 
1097c0a68be4Smrg #define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr,	\
1098c0a68be4Smrg 			      cond)					\
1099c0a68be4Smrg   VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index,	\
1100c0a68be4Smrg 				 elem_ptr, 0, (vec).length (), (cond))
1101c0a68be4Smrg 
11021debfc3dSmrg /* Remove an element from the IXth position of this vector.  Ordering of
11031debfc3dSmrg    remaining elements is destroyed.  This is an O(1) operation.  */
11041debfc3dSmrg 
11051debfc3dSmrg template<typename T, typename A>
11061debfc3dSmrg inline void
11071debfc3dSmrg vec<T, A, vl_embed>::unordered_remove (unsigned ix)
11081debfc3dSmrg {
11091debfc3dSmrg   gcc_checking_assert (ix < length ());
11101debfc3dSmrg   m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
11111debfc3dSmrg }
11121debfc3dSmrg 
11131debfc3dSmrg 
11141debfc3dSmrg /* Remove LEN elements starting at the IXth.  Ordering is retained.
11151debfc3dSmrg    This is an O(N) operation due to memmove.  */
11161debfc3dSmrg 
11171debfc3dSmrg template<typename T, typename A>
11181debfc3dSmrg inline void
11191debfc3dSmrg vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
11201debfc3dSmrg {
11211debfc3dSmrg   gcc_checking_assert (ix + len <= length ());
11221debfc3dSmrg   T *slot = &m_vecdata[ix];
11231debfc3dSmrg   m_vecpfx.m_num -= len;
11241debfc3dSmrg   memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
11251debfc3dSmrg }
11261debfc3dSmrg 
11271debfc3dSmrg 
11281debfc3dSmrg /* Sort the contents of this vector with qsort.  CMP is the comparison
11291debfc3dSmrg    function to pass to qsort.  */
11301debfc3dSmrg 
11311debfc3dSmrg template<typename T, typename A>
11321debfc3dSmrg inline void
11331debfc3dSmrg vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
11341debfc3dSmrg {
11351debfc3dSmrg   if (length () > 1)
1136*8feb0f0bSmrg     gcc_qsort (address (), length (), sizeof (T), cmp);
1137*8feb0f0bSmrg }
1138*8feb0f0bSmrg 
1139*8feb0f0bSmrg /* Sort the contents of this vector with qsort.  CMP is the comparison
1140*8feb0f0bSmrg    function to pass to qsort.  */
1141*8feb0f0bSmrg 
1142*8feb0f0bSmrg template<typename T, typename A>
1143*8feb0f0bSmrg inline void
1144*8feb0f0bSmrg vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
1145*8feb0f0bSmrg 			   void *data)
1146*8feb0f0bSmrg {
1147*8feb0f0bSmrg   if (length () > 1)
1148*8feb0f0bSmrg     gcc_sort_r (address (), length (), sizeof (T), cmp, data);
11491debfc3dSmrg }
11501debfc3dSmrg 
11511debfc3dSmrg 
11521debfc3dSmrg /* Search the contents of the sorted vector with a binary search.
11531debfc3dSmrg    CMP is the comparison function to pass to bsearch.  */
11541debfc3dSmrg 
11551debfc3dSmrg template<typename T, typename A>
11561debfc3dSmrg inline T *
11571debfc3dSmrg vec<T, A, vl_embed>::bsearch (const void *key,
11581debfc3dSmrg 			      int (*compar) (const void *, const void *))
11591debfc3dSmrg {
11601debfc3dSmrg   const void *base = this->address ();
11611debfc3dSmrg   size_t nmemb = this->length ();
11621debfc3dSmrg   size_t size = sizeof (T);
11631debfc3dSmrg   /* The following is a copy of glibc stdlib-bsearch.h.  */
11641debfc3dSmrg   size_t l, u, idx;
11651debfc3dSmrg   const void *p;
11661debfc3dSmrg   int comparison;
11671debfc3dSmrg 
11681debfc3dSmrg   l = 0;
11691debfc3dSmrg   u = nmemb;
11701debfc3dSmrg   while (l < u)
11711debfc3dSmrg     {
11721debfc3dSmrg       idx = (l + u) / 2;
11731debfc3dSmrg       p = (const void *) (((const char *) base) + (idx * size));
11741debfc3dSmrg       comparison = (*compar) (key, p);
11751debfc3dSmrg       if (comparison < 0)
11761debfc3dSmrg 	u = idx;
11771debfc3dSmrg       else if (comparison > 0)
11781debfc3dSmrg 	l = idx + 1;
11791debfc3dSmrg       else
11801debfc3dSmrg 	return (T *)const_cast<void *>(p);
11811debfc3dSmrg     }
11821debfc3dSmrg 
11831debfc3dSmrg   return NULL;
11841debfc3dSmrg }
11851debfc3dSmrg 
1186*8feb0f0bSmrg /* Search the contents of the sorted vector with a binary search.
1187*8feb0f0bSmrg    CMP is the comparison function to pass to bsearch.  */
1188*8feb0f0bSmrg 
1189*8feb0f0bSmrg template<typename T, typename A>
1190*8feb0f0bSmrg inline T *
1191*8feb0f0bSmrg vec<T, A, vl_embed>::bsearch (const void *key,
1192*8feb0f0bSmrg 			      int (*compar) (const void *, const void *,
1193*8feb0f0bSmrg 					     void *), void *data)
1194*8feb0f0bSmrg {
1195*8feb0f0bSmrg   const void *base = this->address ();
1196*8feb0f0bSmrg   size_t nmemb = this->length ();
1197*8feb0f0bSmrg   size_t size = sizeof (T);
1198*8feb0f0bSmrg   /* The following is a copy of glibc stdlib-bsearch.h.  */
1199*8feb0f0bSmrg   size_t l, u, idx;
1200*8feb0f0bSmrg   const void *p;
1201*8feb0f0bSmrg   int comparison;
1202*8feb0f0bSmrg 
1203*8feb0f0bSmrg   l = 0;
1204*8feb0f0bSmrg   u = nmemb;
1205*8feb0f0bSmrg   while (l < u)
1206*8feb0f0bSmrg     {
1207*8feb0f0bSmrg       idx = (l + u) / 2;
1208*8feb0f0bSmrg       p = (const void *) (((const char *) base) + (idx * size));
1209*8feb0f0bSmrg       comparison = (*compar) (key, p, data);
1210*8feb0f0bSmrg       if (comparison < 0)
1211*8feb0f0bSmrg 	u = idx;
1212*8feb0f0bSmrg       else if (comparison > 0)
1213*8feb0f0bSmrg 	l = idx + 1;
1214*8feb0f0bSmrg       else
1215*8feb0f0bSmrg 	return (T *)const_cast<void *>(p);
1216*8feb0f0bSmrg     }
1217*8feb0f0bSmrg 
1218*8feb0f0bSmrg   return NULL;
1219*8feb0f0bSmrg }
1220*8feb0f0bSmrg 
12211debfc3dSmrg /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
12221debfc3dSmrg    size of the vector and so should be used with care.  */
12231debfc3dSmrg 
12241debfc3dSmrg template<typename T, typename A>
12251debfc3dSmrg inline bool
12261debfc3dSmrg vec<T, A, vl_embed>::contains (const T &search) const
12271debfc3dSmrg {
12281debfc3dSmrg   unsigned int len = length ();
12291debfc3dSmrg   for (unsigned int i = 0; i < len; i++)
12301debfc3dSmrg     if ((*this)[i] == search)
12311debfc3dSmrg       return true;
12321debfc3dSmrg 
12331debfc3dSmrg   return false;
12341debfc3dSmrg }
12351debfc3dSmrg 
12361debfc3dSmrg /* Find and return the first position in which OBJ could be inserted
12371debfc3dSmrg    without changing the ordering of this vector.  LESSTHAN is a
12381debfc3dSmrg    function that returns true if the first argument is strictly less
12391debfc3dSmrg    than the second.  */
12401debfc3dSmrg 
12411debfc3dSmrg template<typename T, typename A>
12421debfc3dSmrg unsigned
12431debfc3dSmrg vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
12441debfc3dSmrg   const
12451debfc3dSmrg {
12461debfc3dSmrg   unsigned int len = length ();
12471debfc3dSmrg   unsigned int half, middle;
12481debfc3dSmrg   unsigned int first = 0;
12491debfc3dSmrg   while (len > 0)
12501debfc3dSmrg     {
12511debfc3dSmrg       half = len / 2;
12521debfc3dSmrg       middle = first;
12531debfc3dSmrg       middle += half;
12541debfc3dSmrg       T middle_elem = (*this)[middle];
12551debfc3dSmrg       if (lessthan (middle_elem, obj))
12561debfc3dSmrg 	{
12571debfc3dSmrg 	  first = middle;
12581debfc3dSmrg 	  ++first;
12591debfc3dSmrg 	  len = len - half - 1;
12601debfc3dSmrg 	}
12611debfc3dSmrg       else
12621debfc3dSmrg 	len = half;
12631debfc3dSmrg     }
12641debfc3dSmrg   return first;
12651debfc3dSmrg }
12661debfc3dSmrg 
12671debfc3dSmrg 
12681debfc3dSmrg /* Return the number of bytes needed to embed an instance of an
12691debfc3dSmrg    embeddable vec inside another data structure.
12701debfc3dSmrg 
12711debfc3dSmrg    Use these methods to determine the required size and initialization
12721debfc3dSmrg    of a vector V of type T embedded within another structure (as the
12731debfc3dSmrg    final member):
12741debfc3dSmrg 
12751debfc3dSmrg    size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
12761debfc3dSmrg    void v->embedded_init (unsigned alloc, unsigned num);
12771debfc3dSmrg 
12781debfc3dSmrg    These allow the caller to perform the memory allocation.  */
12791debfc3dSmrg 
12801debfc3dSmrg template<typename T, typename A>
12811debfc3dSmrg inline size_t
12821debfc3dSmrg vec<T, A, vl_embed>::embedded_size (unsigned alloc)
12831debfc3dSmrg {
12841debfc3dSmrg   typedef vec<T, A, vl_embed> vec_embedded;
12851debfc3dSmrg   return offsetof (vec_embedded, m_vecdata) + alloc * sizeof (T);
12861debfc3dSmrg }
12871debfc3dSmrg 
12881debfc3dSmrg 
12891debfc3dSmrg /* Initialize the vector to contain room for ALLOC elements and
12901debfc3dSmrg    NUM active elements.  */
12911debfc3dSmrg 
12921debfc3dSmrg template<typename T, typename A>
12931debfc3dSmrg inline void
12941debfc3dSmrg vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
12951debfc3dSmrg {
12961debfc3dSmrg   m_vecpfx.m_alloc = alloc;
12971debfc3dSmrg   m_vecpfx.m_using_auto_storage = aut;
12981debfc3dSmrg   m_vecpfx.m_num = num;
12991debfc3dSmrg }
13001debfc3dSmrg 
13011debfc3dSmrg 
13021debfc3dSmrg /* Grow the vector to a specific length.  LEN must be as long or longer than
13031debfc3dSmrg    the current length.  The new elements are uninitialized.  */
13041debfc3dSmrg 
13051debfc3dSmrg template<typename T, typename A>
13061debfc3dSmrg inline void
13071debfc3dSmrg vec<T, A, vl_embed>::quick_grow (unsigned len)
13081debfc3dSmrg {
13091debfc3dSmrg   gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
13101debfc3dSmrg   m_vecpfx.m_num = len;
13111debfc3dSmrg }
13121debfc3dSmrg 
13131debfc3dSmrg 
13141debfc3dSmrg /* Grow the vector to a specific length.  LEN must be as long or longer than
13151debfc3dSmrg    the current length.  The new elements are initialized to zero.  */
13161debfc3dSmrg 
13171debfc3dSmrg template<typename T, typename A>
13181debfc3dSmrg inline void
13191debfc3dSmrg vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
13201debfc3dSmrg {
13211debfc3dSmrg   unsigned oldlen = length ();
1322a2dc1f3fSmrg   size_t growby = len - oldlen;
13231debfc3dSmrg   quick_grow (len);
1324a2dc1f3fSmrg   if (growby != 0)
1325a2dc1f3fSmrg     vec_default_construct (address () + oldlen, growby);
13261debfc3dSmrg }
13271debfc3dSmrg 
13281debfc3dSmrg /* Garbage collection support for vec<T, A, vl_embed>.  */
13291debfc3dSmrg 
13301debfc3dSmrg template<typename T>
13311debfc3dSmrg void
13321debfc3dSmrg gt_ggc_mx (vec<T, va_gc> *v)
13331debfc3dSmrg {
13341debfc3dSmrg   extern void gt_ggc_mx (T &);
13351debfc3dSmrg   for (unsigned i = 0; i < v->length (); i++)
13361debfc3dSmrg     gt_ggc_mx ((*v)[i]);
13371debfc3dSmrg }
13381debfc3dSmrg 
13391debfc3dSmrg template<typename T>
13401debfc3dSmrg void
13411debfc3dSmrg gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED)
13421debfc3dSmrg {
13431debfc3dSmrg   /* Nothing to do.  Vectors of atomic types wrt GC do not need to
13441debfc3dSmrg      be traversed.  */
13451debfc3dSmrg }
13461debfc3dSmrg 
13471debfc3dSmrg 
13481debfc3dSmrg /* PCH support for vec<T, A, vl_embed>.  */
13491debfc3dSmrg 
13501debfc3dSmrg template<typename T, typename A>
13511debfc3dSmrg void
13521debfc3dSmrg gt_pch_nx (vec<T, A, vl_embed> *v)
13531debfc3dSmrg {
13541debfc3dSmrg   extern void gt_pch_nx (T &);
13551debfc3dSmrg   for (unsigned i = 0; i < v->length (); i++)
13561debfc3dSmrg     gt_pch_nx ((*v)[i]);
13571debfc3dSmrg }
13581debfc3dSmrg 
13591debfc3dSmrg template<typename T, typename A>
13601debfc3dSmrg void
13611debfc3dSmrg gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
13621debfc3dSmrg {
13631debfc3dSmrg   for (unsigned i = 0; i < v->length (); i++)
13641debfc3dSmrg     op (&((*v)[i]), cookie);
13651debfc3dSmrg }
13661debfc3dSmrg 
13671debfc3dSmrg template<typename T, typename A>
13681debfc3dSmrg void
13691debfc3dSmrg gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
13701debfc3dSmrg {
13711debfc3dSmrg   extern void gt_pch_nx (T *, gt_pointer_operator, void *);
13721debfc3dSmrg   for (unsigned i = 0; i < v->length (); i++)
13731debfc3dSmrg     gt_pch_nx (&((*v)[i]), op, cookie);
13741debfc3dSmrg }
13751debfc3dSmrg 
13761debfc3dSmrg 
13771debfc3dSmrg /* Space efficient vector.  These vectors can grow dynamically and are
13781debfc3dSmrg    allocated together with their control data.  They are suited to be
13791debfc3dSmrg    included in data structures.  Prior to initial allocation, they
13801debfc3dSmrg    only take a single word of storage.
13811debfc3dSmrg 
13821debfc3dSmrg    These vectors are implemented as a pointer to an embeddable vector.
13831debfc3dSmrg    The semantics allow for this pointer to be NULL to represent empty
13841debfc3dSmrg    vectors.  This way, empty vectors occupy minimal space in the
13851debfc3dSmrg    structure containing them.
13861debfc3dSmrg 
13871debfc3dSmrg    Properties:
13881debfc3dSmrg 
13891debfc3dSmrg 	- The whole vector and control data are allocated in a single
13901debfc3dSmrg 	  contiguous block.
13911debfc3dSmrg   	- The whole vector may be re-allocated.
13921debfc3dSmrg   	- Vector data may grow and shrink.
13931debfc3dSmrg   	- Access and manipulation requires a pointer test and
13941debfc3dSmrg 	  indirection.
13951debfc3dSmrg 	- It requires 1 word of storage (prior to vector allocation).
13961debfc3dSmrg 
13971debfc3dSmrg 
13981debfc3dSmrg    Limitations:
13991debfc3dSmrg 
14001debfc3dSmrg    These vectors must be PODs because they are stored in unions.
14011debfc3dSmrg    (http://en.wikipedia.org/wiki/Plain_old_data_structures).
14021debfc3dSmrg    As long as we use C++03, we cannot have constructors nor
14031debfc3dSmrg    destructors in classes that are stored in unions.  */
14041debfc3dSmrg 
14051debfc3dSmrg template<typename T>
14061debfc3dSmrg struct vec<T, va_heap, vl_ptr>
14071debfc3dSmrg {
14081debfc3dSmrg public:
14091debfc3dSmrg   /* Memory allocation and deallocation for the embedded vector.
14101debfc3dSmrg      Needed because we cannot have proper ctors/dtors defined.  */
14111debfc3dSmrg   void create (unsigned nelems CXX_MEM_STAT_INFO);
14121debfc3dSmrg   void release (void);
14131debfc3dSmrg 
14141debfc3dSmrg   /* Vector operations.  */
14151debfc3dSmrg   bool exists (void) const
14161debfc3dSmrg   { return m_vec != NULL; }
14171debfc3dSmrg 
14181debfc3dSmrg   bool is_empty (void) const
14191debfc3dSmrg   { return m_vec ? m_vec->is_empty () : true; }
14201debfc3dSmrg 
14211debfc3dSmrg   unsigned length (void) const
14221debfc3dSmrg   { return m_vec ? m_vec->length () : 0; }
14231debfc3dSmrg 
14241debfc3dSmrg   T *address (void)
14251debfc3dSmrg   { return m_vec ? m_vec->m_vecdata : NULL; }
14261debfc3dSmrg 
14271debfc3dSmrg   const T *address (void) const
14281debfc3dSmrg   { return m_vec ? m_vec->m_vecdata : NULL; }
14291debfc3dSmrg 
14301debfc3dSmrg   T *begin () { return address (); }
14311debfc3dSmrg   const T *begin () const { return address (); }
14321debfc3dSmrg   T *end () { return begin () + length (); }
14331debfc3dSmrg   const T *end () const { return begin () + length (); }
14341debfc3dSmrg   const T &operator[] (unsigned ix) const
14351debfc3dSmrg   { return (*m_vec)[ix]; }
14361debfc3dSmrg 
14371debfc3dSmrg   bool operator!=(const vec &other) const
14381debfc3dSmrg   { return !(*this == other); }
14391debfc3dSmrg 
14401debfc3dSmrg   bool operator==(const vec &other) const
14411debfc3dSmrg   { return address () == other.address (); }
14421debfc3dSmrg 
14431debfc3dSmrg   T &operator[] (unsigned ix)
14441debfc3dSmrg   { return (*m_vec)[ix]; }
14451debfc3dSmrg 
14461debfc3dSmrg   T &last (void)
14471debfc3dSmrg   { return m_vec->last (); }
14481debfc3dSmrg 
14491debfc3dSmrg   bool space (int nelems) const
14501debfc3dSmrg   { return m_vec ? m_vec->space (nelems) : nelems == 0; }
14511debfc3dSmrg 
14521debfc3dSmrg   bool iterate (unsigned ix, T *p) const;
14531debfc3dSmrg   bool iterate (unsigned ix, T **p) const;
14541debfc3dSmrg   vec copy (ALONE_CXX_MEM_STAT_INFO) const;
14551debfc3dSmrg   bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
14561debfc3dSmrg   bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
14571debfc3dSmrg   void splice (const vec &);
14581debfc3dSmrg   void safe_splice (const vec & CXX_MEM_STAT_INFO);
14591debfc3dSmrg   T *quick_push (const T &);
14601debfc3dSmrg   T *safe_push (const T &CXX_MEM_STAT_INFO);
14611debfc3dSmrg   T &pop (void);
14621debfc3dSmrg   void truncate (unsigned);
14631debfc3dSmrg   void safe_grow (unsigned CXX_MEM_STAT_INFO);
14641debfc3dSmrg   void safe_grow_cleared (unsigned CXX_MEM_STAT_INFO);
14651debfc3dSmrg   void quick_grow (unsigned);
14661debfc3dSmrg   void quick_grow_cleared (unsigned);
14671debfc3dSmrg   void quick_insert (unsigned, const T &);
14681debfc3dSmrg   void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
14691debfc3dSmrg   void ordered_remove (unsigned);
14701debfc3dSmrg   void unordered_remove (unsigned);
14711debfc3dSmrg   void block_remove (unsigned, unsigned);
14721debfc3dSmrg   void qsort (int (*) (const void *, const void *));
1473*8feb0f0bSmrg   void sort (int (*) (const void *, const void *, void *), void *);
14741debfc3dSmrg   T *bsearch (const void *key, int (*compar)(const void *, const void *));
1475*8feb0f0bSmrg   T *bsearch (const void *key,
1476*8feb0f0bSmrg 	      int (*compar)(const void *, const void *, void *), void *);
14771debfc3dSmrg   unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
14781debfc3dSmrg   bool contains (const T &search) const;
1479c0a68be4Smrg   void reverse (void);
14801debfc3dSmrg 
14811debfc3dSmrg   bool using_auto_storage () const;
14821debfc3dSmrg 
14831debfc3dSmrg   /* FIXME - This field should be private, but we need to cater to
14841debfc3dSmrg 	     compilers that have stricter notions of PODness for types.  */
14851debfc3dSmrg   vec<T, va_heap, vl_embed> *m_vec;
14861debfc3dSmrg };
14871debfc3dSmrg 
14881debfc3dSmrg 
14891debfc3dSmrg /* auto_vec is a subclass of vec that automatically manages creating and
14901debfc3dSmrg    releasing the internal vector. If N is non zero then it has N elements of
14911debfc3dSmrg    internal storage.  The default is no internal storage, and you probably only
14921debfc3dSmrg    want to ask for internal storage for vectors on the stack because if the
14931debfc3dSmrg    size of the vector is larger than the internal storage that space is wasted.
14941debfc3dSmrg    */
14951debfc3dSmrg template<typename T, size_t N = 0>
14961debfc3dSmrg class auto_vec : public vec<T, va_heap>
14971debfc3dSmrg {
14981debfc3dSmrg public:
14991debfc3dSmrg   auto_vec ()
15001debfc3dSmrg   {
15011debfc3dSmrg     m_auto.embedded_init (MAX (N, 2), 0, 1);
15021debfc3dSmrg     this->m_vec = &m_auto;
15031debfc3dSmrg   }
15041debfc3dSmrg 
1505a2dc1f3fSmrg   auto_vec (size_t s)
1506a2dc1f3fSmrg   {
1507a2dc1f3fSmrg     if (s > N)
1508a2dc1f3fSmrg       {
1509a2dc1f3fSmrg 	this->create (s);
1510a2dc1f3fSmrg 	return;
1511a2dc1f3fSmrg       }
1512a2dc1f3fSmrg 
1513a2dc1f3fSmrg     m_auto.embedded_init (MAX (N, 2), 0, 1);
1514a2dc1f3fSmrg     this->m_vec = &m_auto;
1515a2dc1f3fSmrg   }
1516a2dc1f3fSmrg 
15171debfc3dSmrg   ~auto_vec ()
15181debfc3dSmrg   {
15191debfc3dSmrg     this->release ();
15201debfc3dSmrg   }
15211debfc3dSmrg 
15221debfc3dSmrg private:
15231debfc3dSmrg   vec<T, va_heap, vl_embed> m_auto;
15241debfc3dSmrg   T m_data[MAX (N - 1, 1)];
15251debfc3dSmrg };
15261debfc3dSmrg 
15271debfc3dSmrg /* auto_vec is a sub class of vec whose storage is released when it is
15281debfc3dSmrg   destroyed. */
15291debfc3dSmrg template<typename T>
15301debfc3dSmrg class auto_vec<T, 0> : public vec<T, va_heap>
15311debfc3dSmrg {
15321debfc3dSmrg public:
15331debfc3dSmrg   auto_vec () { this->m_vec = NULL; }
15341debfc3dSmrg   auto_vec (size_t n) { this->create (n); }
15351debfc3dSmrg   ~auto_vec () { this->release (); }
15361debfc3dSmrg };
15371debfc3dSmrg 
15381debfc3dSmrg 
15391debfc3dSmrg /* Allocate heap memory for pointer V and create the internal vector
15401debfc3dSmrg    with space for NELEMS elements.  If NELEMS is 0, the internal
15411debfc3dSmrg    vector is initialized to empty.  */
15421debfc3dSmrg 
15431debfc3dSmrg template<typename T>
15441debfc3dSmrg inline void
15451debfc3dSmrg vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
15461debfc3dSmrg {
15471debfc3dSmrg   v = new vec<T>;
15481debfc3dSmrg   v->create (nelems PASS_MEM_STAT);
15491debfc3dSmrg }
15501debfc3dSmrg 
15511debfc3dSmrg 
1552c0a68be4Smrg /* A subclass of auto_vec <char *> that frees all of its elements on
1553c0a68be4Smrg    deletion.  */
1554c0a68be4Smrg 
1555c0a68be4Smrg class auto_string_vec : public auto_vec <char *>
1556c0a68be4Smrg {
1557c0a68be4Smrg  public:
1558c0a68be4Smrg   ~auto_string_vec ();
1559c0a68be4Smrg };
1560c0a68be4Smrg 
1561*8feb0f0bSmrg /* A subclass of auto_vec <T *> that deletes all of its elements on
1562*8feb0f0bSmrg    destruction.
1563*8feb0f0bSmrg 
1564*8feb0f0bSmrg    This is a crude way for a vec to "own" the objects it points to
1565*8feb0f0bSmrg    and clean up automatically.
1566*8feb0f0bSmrg 
1567*8feb0f0bSmrg    For example, no attempt is made to delete elements when an item
1568*8feb0f0bSmrg    within the vec is overwritten.
1569*8feb0f0bSmrg 
1570*8feb0f0bSmrg    We can't rely on gnu::unique_ptr within a container,
1571*8feb0f0bSmrg    since we can't rely on move semantics in C++98.  */
1572*8feb0f0bSmrg 
1573*8feb0f0bSmrg template <typename T>
1574*8feb0f0bSmrg class auto_delete_vec : public auto_vec <T *>
1575*8feb0f0bSmrg {
1576*8feb0f0bSmrg  public:
1577*8feb0f0bSmrg   auto_delete_vec () {}
1578*8feb0f0bSmrg   auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
1579*8feb0f0bSmrg 
1580*8feb0f0bSmrg   ~auto_delete_vec ();
1581*8feb0f0bSmrg 
1582*8feb0f0bSmrg private:
1583*8feb0f0bSmrg   DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
1584*8feb0f0bSmrg };
1585*8feb0f0bSmrg 
15861debfc3dSmrg /* Conditionally allocate heap memory for VEC and its internal vector.  */
15871debfc3dSmrg 
15881debfc3dSmrg template<typename T>
15891debfc3dSmrg inline void
15901debfc3dSmrg vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
15911debfc3dSmrg {
15921debfc3dSmrg   if (!vec)
15931debfc3dSmrg     vec_alloc (vec, nelems PASS_MEM_STAT);
15941debfc3dSmrg }
15951debfc3dSmrg 
15961debfc3dSmrg 
15971debfc3dSmrg /* Free the heap memory allocated by vector V and set it to NULL.  */
15981debfc3dSmrg 
15991debfc3dSmrg template<typename T>
16001debfc3dSmrg inline void
16011debfc3dSmrg vec_free (vec<T> *&v)
16021debfc3dSmrg {
16031debfc3dSmrg   if (v == NULL)
16041debfc3dSmrg     return;
16051debfc3dSmrg 
16061debfc3dSmrg   v->release ();
16071debfc3dSmrg   delete v;
16081debfc3dSmrg   v = NULL;
16091debfc3dSmrg }
16101debfc3dSmrg 
16111debfc3dSmrg 
16121debfc3dSmrg /* Return iteration condition and update PTR to point to the IX'th
16131debfc3dSmrg    element of this vector.  Use this to iterate over the elements of a
16141debfc3dSmrg    vector as follows,
16151debfc3dSmrg 
16161debfc3dSmrg      for (ix = 0; v.iterate (ix, &ptr); ix++)
16171debfc3dSmrg        continue;  */
16181debfc3dSmrg 
16191debfc3dSmrg template<typename T>
16201debfc3dSmrg inline bool
16211debfc3dSmrg vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
16221debfc3dSmrg {
16231debfc3dSmrg   if (m_vec)
16241debfc3dSmrg     return m_vec->iterate (ix, ptr);
16251debfc3dSmrg   else
16261debfc3dSmrg     {
16271debfc3dSmrg       *ptr = 0;
16281debfc3dSmrg       return false;
16291debfc3dSmrg     }
16301debfc3dSmrg }
16311debfc3dSmrg 
16321debfc3dSmrg 
16331debfc3dSmrg /* Return iteration condition and update *PTR to point to the
16341debfc3dSmrg    IX'th element of this vector.  Use this to iterate over the
16351debfc3dSmrg    elements of a vector as follows,
16361debfc3dSmrg 
16371debfc3dSmrg      for (ix = 0; v->iterate (ix, &ptr); ix++)
16381debfc3dSmrg        continue;
16391debfc3dSmrg 
16401debfc3dSmrg    This variant is for vectors of objects.  */
16411debfc3dSmrg 
16421debfc3dSmrg template<typename T>
16431debfc3dSmrg inline bool
16441debfc3dSmrg vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
16451debfc3dSmrg {
16461debfc3dSmrg   if (m_vec)
16471debfc3dSmrg     return m_vec->iterate (ix, ptr);
16481debfc3dSmrg   else
16491debfc3dSmrg     {
16501debfc3dSmrg       *ptr = 0;
16511debfc3dSmrg       return false;
16521debfc3dSmrg     }
16531debfc3dSmrg }
16541debfc3dSmrg 
16551debfc3dSmrg 
16561debfc3dSmrg /* Convenience macro for forward iteration.  */
16571debfc3dSmrg #define FOR_EACH_VEC_ELT(V, I, P)			\
16581debfc3dSmrg   for (I = 0; (V).iterate ((I), &(P)); ++(I))
16591debfc3dSmrg 
16601debfc3dSmrg #define FOR_EACH_VEC_SAFE_ELT(V, I, P)			\
16611debfc3dSmrg   for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
16621debfc3dSmrg 
16631debfc3dSmrg /* Likewise, but start from FROM rather than 0.  */
16641debfc3dSmrg #define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)		\
16651debfc3dSmrg   for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
16661debfc3dSmrg 
16671debfc3dSmrg /* Convenience macro for reverse iteration.  */
16681debfc3dSmrg #define FOR_EACH_VEC_ELT_REVERSE(V, I, P)		\
16691debfc3dSmrg   for (I = (V).length () - 1;				\
16701debfc3dSmrg        (V).iterate ((I), &(P));				\
16711debfc3dSmrg        (I)--)
16721debfc3dSmrg 
16731debfc3dSmrg #define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)		\
16741debfc3dSmrg   for (I = vec_safe_length (V) - 1;			\
16751debfc3dSmrg        vec_safe_iterate ((V), (I), &(P));	\
16761debfc3dSmrg        (I)--)
16771debfc3dSmrg 
1678c0a68be4Smrg /* auto_string_vec's dtor, freeing all contained strings, automatically
1679c0a68be4Smrg    chaining up to ~auto_vec <char *>, which frees the internal buffer.  */
1680c0a68be4Smrg 
1681c0a68be4Smrg inline
1682c0a68be4Smrg auto_string_vec::~auto_string_vec ()
1683c0a68be4Smrg {
1684c0a68be4Smrg   int i;
1685c0a68be4Smrg   char *str;
1686c0a68be4Smrg   FOR_EACH_VEC_ELT (*this, i, str)
1687c0a68be4Smrg     free (str);
1688c0a68be4Smrg }
1689c0a68be4Smrg 
1690*8feb0f0bSmrg /* auto_delete_vec's dtor, deleting all contained items, automatically
1691*8feb0f0bSmrg    chaining up to ~auto_vec <T*>, which frees the internal buffer.  */
1692*8feb0f0bSmrg 
1693*8feb0f0bSmrg template <typename T>
1694*8feb0f0bSmrg inline
1695*8feb0f0bSmrg auto_delete_vec<T>::~auto_delete_vec ()
1696*8feb0f0bSmrg {
1697*8feb0f0bSmrg   int i;
1698*8feb0f0bSmrg   T *item;
1699*8feb0f0bSmrg   FOR_EACH_VEC_ELT (*this, i, item)
1700*8feb0f0bSmrg     delete item;
1701*8feb0f0bSmrg }
1702*8feb0f0bSmrg 
17031debfc3dSmrg 
17041debfc3dSmrg /* Return a copy of this vector.  */
17051debfc3dSmrg 
17061debfc3dSmrg template<typename T>
17071debfc3dSmrg inline vec<T, va_heap, vl_ptr>
17081debfc3dSmrg vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
17091debfc3dSmrg {
17101debfc3dSmrg   vec<T, va_heap, vl_ptr> new_vec = vNULL;
17111debfc3dSmrg   if (length ())
17121debfc3dSmrg     new_vec.m_vec = m_vec->copy ();
17131debfc3dSmrg   return new_vec;
17141debfc3dSmrg }
17151debfc3dSmrg 
17161debfc3dSmrg 
17171debfc3dSmrg /* Ensure that the vector has at least RESERVE slots available (if
17181debfc3dSmrg    EXACT is false), or exactly RESERVE slots available (if EXACT is
17191debfc3dSmrg    true).
17201debfc3dSmrg 
17211debfc3dSmrg    This may create additional headroom if EXACT is false.
17221debfc3dSmrg 
17231debfc3dSmrg    Note that this can cause the embedded vector to be reallocated.
17241debfc3dSmrg    Returns true iff reallocation actually occurred.  */
17251debfc3dSmrg 
17261debfc3dSmrg template<typename T>
17271debfc3dSmrg inline bool
17281debfc3dSmrg vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
17291debfc3dSmrg {
17301debfc3dSmrg   if (space (nelems))
17311debfc3dSmrg     return false;
17321debfc3dSmrg 
17331debfc3dSmrg   /* For now play a game with va_heap::reserve to hide our auto storage if any,
17341debfc3dSmrg      this is necessary because it doesn't have enough information to know the
17351debfc3dSmrg      embedded vector is in auto storage, and so should not be freed.  */
17361debfc3dSmrg   vec<T, va_heap, vl_embed> *oldvec = m_vec;
17371debfc3dSmrg   unsigned int oldsize = 0;
17381debfc3dSmrg   bool handle_auto_vec = m_vec && using_auto_storage ();
17391debfc3dSmrg   if (handle_auto_vec)
17401debfc3dSmrg     {
17411debfc3dSmrg       m_vec = NULL;
17421debfc3dSmrg       oldsize = oldvec->length ();
17431debfc3dSmrg       nelems += oldsize;
17441debfc3dSmrg     }
17451debfc3dSmrg 
17461debfc3dSmrg   va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
17471debfc3dSmrg   if (handle_auto_vec)
17481debfc3dSmrg     {
1749a2dc1f3fSmrg       vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
17501debfc3dSmrg       m_vec->m_vecpfx.m_num = oldsize;
17511debfc3dSmrg     }
17521debfc3dSmrg 
17531debfc3dSmrg   return true;
17541debfc3dSmrg }
17551debfc3dSmrg 
17561debfc3dSmrg 
17571debfc3dSmrg /* Ensure that this vector has exactly NELEMS slots available.  This
17581debfc3dSmrg    will not create additional headroom.  Note this can cause the
17591debfc3dSmrg    embedded vector to be reallocated.  Returns true iff reallocation
17601debfc3dSmrg    actually occurred.  */
17611debfc3dSmrg 
17621debfc3dSmrg template<typename T>
17631debfc3dSmrg inline bool
17641debfc3dSmrg vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
17651debfc3dSmrg {
17661debfc3dSmrg   return reserve (nelems, true PASS_MEM_STAT);
17671debfc3dSmrg }
17681debfc3dSmrg 
17691debfc3dSmrg 
17701debfc3dSmrg /* Create the internal vector and reserve NELEMS for it.  This is
17711debfc3dSmrg    exactly like vec::reserve, but the internal vector is
17721debfc3dSmrg    unconditionally allocated from scratch.  The old one, if it
17731debfc3dSmrg    existed, is lost.  */
17741debfc3dSmrg 
17751debfc3dSmrg template<typename T>
17761debfc3dSmrg inline void
17771debfc3dSmrg vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
17781debfc3dSmrg {
17791debfc3dSmrg   m_vec = NULL;
17801debfc3dSmrg   if (nelems > 0)
17811debfc3dSmrg     reserve_exact (nelems PASS_MEM_STAT);
17821debfc3dSmrg }
17831debfc3dSmrg 
17841debfc3dSmrg 
17851debfc3dSmrg /* Free the memory occupied by the embedded vector.  */
17861debfc3dSmrg 
17871debfc3dSmrg template<typename T>
17881debfc3dSmrg inline void
17891debfc3dSmrg vec<T, va_heap, vl_ptr>::release (void)
17901debfc3dSmrg {
17911debfc3dSmrg   if (!m_vec)
17921debfc3dSmrg     return;
17931debfc3dSmrg 
17941debfc3dSmrg   if (using_auto_storage ())
17951debfc3dSmrg     {
17961debfc3dSmrg       m_vec->m_vecpfx.m_num = 0;
17971debfc3dSmrg       return;
17981debfc3dSmrg     }
17991debfc3dSmrg 
18001debfc3dSmrg   va_heap::release (m_vec);
18011debfc3dSmrg }
18021debfc3dSmrg 
18031debfc3dSmrg /* Copy the elements from SRC to the end of this vector as if by memcpy.
18041debfc3dSmrg    SRC and this vector must be allocated with the same memory
18051debfc3dSmrg    allocation mechanism. This vector is assumed to have sufficient
18061debfc3dSmrg    headroom available.  */
18071debfc3dSmrg 
18081debfc3dSmrg template<typename T>
18091debfc3dSmrg inline void
18101debfc3dSmrg vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
18111debfc3dSmrg {
1812c0a68be4Smrg   if (src.length ())
18131debfc3dSmrg     m_vec->splice (*(src.m_vec));
18141debfc3dSmrg }
18151debfc3dSmrg 
18161debfc3dSmrg 
18171debfc3dSmrg /* Copy the elements in SRC to the end of this vector as if by memcpy.
18181debfc3dSmrg    SRC and this vector must be allocated with the same mechanism.
18191debfc3dSmrg    If there is not enough headroom in this vector, it will be reallocated
18201debfc3dSmrg    as needed.  */
18211debfc3dSmrg 
18221debfc3dSmrg template<typename T>
18231debfc3dSmrg inline void
18241debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
18251debfc3dSmrg 				      MEM_STAT_DECL)
18261debfc3dSmrg {
18271debfc3dSmrg   if (src.length ())
18281debfc3dSmrg     {
18291debfc3dSmrg       reserve_exact (src.length ());
18301debfc3dSmrg       splice (src);
18311debfc3dSmrg     }
18321debfc3dSmrg }
18331debfc3dSmrg 
18341debfc3dSmrg 
18351debfc3dSmrg /* Push OBJ (a new element) onto the end of the vector.  There must be
18361debfc3dSmrg    sufficient space in the vector.  Return a pointer to the slot
18371debfc3dSmrg    where OBJ was inserted.  */
18381debfc3dSmrg 
18391debfc3dSmrg template<typename T>
18401debfc3dSmrg inline T *
18411debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
18421debfc3dSmrg {
18431debfc3dSmrg   return m_vec->quick_push (obj);
18441debfc3dSmrg }
18451debfc3dSmrg 
18461debfc3dSmrg 
18471debfc3dSmrg /* Push a new element OBJ onto the end of this vector.  Reallocates
18481debfc3dSmrg    the embedded vector, if needed.  Return a pointer to the slot where
18491debfc3dSmrg    OBJ was inserted.  */
18501debfc3dSmrg 
18511debfc3dSmrg template<typename T>
18521debfc3dSmrg inline T *
18531debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
18541debfc3dSmrg {
18551debfc3dSmrg   reserve (1, false PASS_MEM_STAT);
18561debfc3dSmrg   return quick_push (obj);
18571debfc3dSmrg }
18581debfc3dSmrg 
18591debfc3dSmrg 
18601debfc3dSmrg /* Pop and return the last element off the end of the vector.  */
18611debfc3dSmrg 
18621debfc3dSmrg template<typename T>
18631debfc3dSmrg inline T &
18641debfc3dSmrg vec<T, va_heap, vl_ptr>::pop (void)
18651debfc3dSmrg {
18661debfc3dSmrg   return m_vec->pop ();
18671debfc3dSmrg }
18681debfc3dSmrg 
18691debfc3dSmrg 
18701debfc3dSmrg /* Set the length of the vector to LEN.  The new length must be less
18711debfc3dSmrg    than or equal to the current length.  This is an O(1) operation.  */
18721debfc3dSmrg 
18731debfc3dSmrg template<typename T>
18741debfc3dSmrg inline void
18751debfc3dSmrg vec<T, va_heap, vl_ptr>::truncate (unsigned size)
18761debfc3dSmrg {
18771debfc3dSmrg   if (m_vec)
18781debfc3dSmrg     m_vec->truncate (size);
18791debfc3dSmrg   else
18801debfc3dSmrg     gcc_checking_assert (size == 0);
18811debfc3dSmrg }
18821debfc3dSmrg 
18831debfc3dSmrg 
18841debfc3dSmrg /* Grow the vector to a specific length.  LEN must be as long or
18851debfc3dSmrg    longer than the current length.  The new elements are
18861debfc3dSmrg    uninitialized.  Reallocate the internal vector, if needed.  */
18871debfc3dSmrg 
18881debfc3dSmrg template<typename T>
18891debfc3dSmrg inline void
18901debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL)
18911debfc3dSmrg {
18921debfc3dSmrg   unsigned oldlen = length ();
18931debfc3dSmrg   gcc_checking_assert (oldlen <= len);
18941debfc3dSmrg   reserve_exact (len - oldlen PASS_MEM_STAT);
18951debfc3dSmrg   if (m_vec)
18961debfc3dSmrg     m_vec->quick_grow (len);
18971debfc3dSmrg   else
18981debfc3dSmrg     gcc_checking_assert (len == 0);
18991debfc3dSmrg }
19001debfc3dSmrg 
19011debfc3dSmrg 
19021debfc3dSmrg /* Grow the embedded vector to a specific length.  LEN must be as
19031debfc3dSmrg    long or longer than the current length.  The new elements are
19041debfc3dSmrg    initialized to zero.  Reallocate the internal vector, if needed.  */
19051debfc3dSmrg 
19061debfc3dSmrg template<typename T>
19071debfc3dSmrg inline void
19081debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL)
19091debfc3dSmrg {
19101debfc3dSmrg   unsigned oldlen = length ();
1911a2dc1f3fSmrg   size_t growby = len - oldlen;
19121debfc3dSmrg   safe_grow (len PASS_MEM_STAT);
1913a2dc1f3fSmrg   if (growby != 0)
1914a2dc1f3fSmrg     vec_default_construct (address () + oldlen, growby);
19151debfc3dSmrg }
19161debfc3dSmrg 
19171debfc3dSmrg 
19181debfc3dSmrg /* Same as vec::safe_grow but without reallocation of the internal vector.
19191debfc3dSmrg    If the vector cannot be extended, a runtime assertion will be triggered.  */
19201debfc3dSmrg 
19211debfc3dSmrg template<typename T>
19221debfc3dSmrg inline void
19231debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
19241debfc3dSmrg {
19251debfc3dSmrg   gcc_checking_assert (m_vec);
19261debfc3dSmrg   m_vec->quick_grow (len);
19271debfc3dSmrg }
19281debfc3dSmrg 
19291debfc3dSmrg 
19301debfc3dSmrg /* Same as vec::quick_grow_cleared but without reallocation of the
19311debfc3dSmrg    internal vector. If the vector cannot be extended, a runtime
19321debfc3dSmrg    assertion will be triggered.  */
19331debfc3dSmrg 
19341debfc3dSmrg template<typename T>
19351debfc3dSmrg inline void
19361debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
19371debfc3dSmrg {
19381debfc3dSmrg   gcc_checking_assert (m_vec);
19391debfc3dSmrg   m_vec->quick_grow_cleared (len);
19401debfc3dSmrg }
19411debfc3dSmrg 
19421debfc3dSmrg 
19431debfc3dSmrg /* Insert an element, OBJ, at the IXth position of this vector.  There
19441debfc3dSmrg    must be sufficient space.  */
19451debfc3dSmrg 
19461debfc3dSmrg template<typename T>
19471debfc3dSmrg inline void
19481debfc3dSmrg vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
19491debfc3dSmrg {
19501debfc3dSmrg   m_vec->quick_insert (ix, obj);
19511debfc3dSmrg }
19521debfc3dSmrg 
19531debfc3dSmrg 
19541debfc3dSmrg /* Insert an element, OBJ, at the IXth position of the vector.
19551debfc3dSmrg    Reallocate the embedded vector, if necessary.  */
19561debfc3dSmrg 
19571debfc3dSmrg template<typename T>
19581debfc3dSmrg inline void
19591debfc3dSmrg vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
19601debfc3dSmrg {
19611debfc3dSmrg   reserve (1, false PASS_MEM_STAT);
19621debfc3dSmrg   quick_insert (ix, obj);
19631debfc3dSmrg }
19641debfc3dSmrg 
19651debfc3dSmrg 
19661debfc3dSmrg /* Remove an element from the IXth position of this vector.  Ordering of
19671debfc3dSmrg    remaining elements is preserved.  This is an O(N) operation due to
19681debfc3dSmrg    a memmove.  */
19691debfc3dSmrg 
19701debfc3dSmrg template<typename T>
19711debfc3dSmrg inline void
19721debfc3dSmrg vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
19731debfc3dSmrg {
19741debfc3dSmrg   m_vec->ordered_remove (ix);
19751debfc3dSmrg }
19761debfc3dSmrg 
19771debfc3dSmrg 
19781debfc3dSmrg /* Remove an element from the IXth position of this vector.  Ordering
19791debfc3dSmrg    of remaining elements is destroyed.  This is an O(1) operation.  */
19801debfc3dSmrg 
19811debfc3dSmrg template<typename T>
19821debfc3dSmrg inline void
19831debfc3dSmrg vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
19841debfc3dSmrg {
19851debfc3dSmrg   m_vec->unordered_remove (ix);
19861debfc3dSmrg }
19871debfc3dSmrg 
19881debfc3dSmrg 
19891debfc3dSmrg /* Remove LEN elements starting at the IXth.  Ordering is retained.
19901debfc3dSmrg    This is an O(N) operation due to memmove.  */
19911debfc3dSmrg 
19921debfc3dSmrg template<typename T>
19931debfc3dSmrg inline void
19941debfc3dSmrg vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
19951debfc3dSmrg {
19961debfc3dSmrg   m_vec->block_remove (ix, len);
19971debfc3dSmrg }
19981debfc3dSmrg 
19991debfc3dSmrg 
20001debfc3dSmrg /* Sort the contents of this vector with qsort.  CMP is the comparison
20011debfc3dSmrg    function to pass to qsort.  */
20021debfc3dSmrg 
20031debfc3dSmrg template<typename T>
20041debfc3dSmrg inline void
20051debfc3dSmrg vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
20061debfc3dSmrg {
20071debfc3dSmrg   if (m_vec)
20081debfc3dSmrg     m_vec->qsort (cmp);
20091debfc3dSmrg }
20101debfc3dSmrg 
2011*8feb0f0bSmrg /* Sort the contents of this vector with qsort.  CMP is the comparison
2012*8feb0f0bSmrg    function to pass to qsort.  */
2013*8feb0f0bSmrg 
2014*8feb0f0bSmrg template<typename T>
2015*8feb0f0bSmrg inline void
2016*8feb0f0bSmrg vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
2017*8feb0f0bSmrg 					   void *), void *data)
2018*8feb0f0bSmrg {
2019*8feb0f0bSmrg   if (m_vec)
2020*8feb0f0bSmrg     m_vec->sort (cmp, data);
2021*8feb0f0bSmrg }
2022*8feb0f0bSmrg 
20231debfc3dSmrg 
20241debfc3dSmrg /* Search the contents of the sorted vector with a binary search.
20251debfc3dSmrg    CMP is the comparison function to pass to bsearch.  */
20261debfc3dSmrg 
20271debfc3dSmrg template<typename T>
20281debfc3dSmrg inline T *
20291debfc3dSmrg vec<T, va_heap, vl_ptr>::bsearch (const void *key,
20301debfc3dSmrg 				  int (*cmp) (const void *, const void *))
20311debfc3dSmrg {
20321debfc3dSmrg   if (m_vec)
20331debfc3dSmrg     return m_vec->bsearch (key, cmp);
20341debfc3dSmrg   return NULL;
20351debfc3dSmrg }
20361debfc3dSmrg 
2037*8feb0f0bSmrg /* Search the contents of the sorted vector with a binary search.
2038*8feb0f0bSmrg    CMP is the comparison function to pass to bsearch.  */
2039*8feb0f0bSmrg 
2040*8feb0f0bSmrg template<typename T>
2041*8feb0f0bSmrg inline T *
2042*8feb0f0bSmrg vec<T, va_heap, vl_ptr>::bsearch (const void *key,
2043*8feb0f0bSmrg 				  int (*cmp) (const void *, const void *,
2044*8feb0f0bSmrg 					      void *), void *data)
2045*8feb0f0bSmrg {
2046*8feb0f0bSmrg   if (m_vec)
2047*8feb0f0bSmrg     return m_vec->bsearch (key, cmp, data);
2048*8feb0f0bSmrg   return NULL;
2049*8feb0f0bSmrg }
2050*8feb0f0bSmrg 
20511debfc3dSmrg 
20521debfc3dSmrg /* Find and return the first position in which OBJ could be inserted
20531debfc3dSmrg    without changing the ordering of this vector.  LESSTHAN is a
20541debfc3dSmrg    function that returns true if the first argument is strictly less
20551debfc3dSmrg    than the second.  */
20561debfc3dSmrg 
20571debfc3dSmrg template<typename T>
20581debfc3dSmrg inline unsigned
20591debfc3dSmrg vec<T, va_heap, vl_ptr>::lower_bound (T obj,
20601debfc3dSmrg 				      bool (*lessthan)(const T &, const T &))
20611debfc3dSmrg     const
20621debfc3dSmrg {
20631debfc3dSmrg   return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
20641debfc3dSmrg }
20651debfc3dSmrg 
20661debfc3dSmrg /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
20671debfc3dSmrg    size of the vector and so should be used with care.  */
20681debfc3dSmrg 
20691debfc3dSmrg template<typename T>
20701debfc3dSmrg inline bool
20711debfc3dSmrg vec<T, va_heap, vl_ptr>::contains (const T &search) const
20721debfc3dSmrg {
20731debfc3dSmrg   return m_vec ? m_vec->contains (search) : false;
20741debfc3dSmrg }
20751debfc3dSmrg 
2076c0a68be4Smrg /* Reverse content of the vector.  */
2077c0a68be4Smrg 
2078c0a68be4Smrg template<typename T>
2079c0a68be4Smrg inline void
2080c0a68be4Smrg vec<T, va_heap, vl_ptr>::reverse (void)
2081c0a68be4Smrg {
2082c0a68be4Smrg   unsigned l = length ();
2083c0a68be4Smrg   T *ptr = address ();
2084c0a68be4Smrg 
2085c0a68be4Smrg   for (unsigned i = 0; i < l / 2; i++)
2086c0a68be4Smrg     std::swap (ptr[i], ptr[l - i - 1]);
2087c0a68be4Smrg }
2088c0a68be4Smrg 
20891debfc3dSmrg template<typename T>
20901debfc3dSmrg inline bool
20911debfc3dSmrg vec<T, va_heap, vl_ptr>::using_auto_storage () const
20921debfc3dSmrg {
20931debfc3dSmrg   return m_vec->m_vecpfx.m_using_auto_storage;
20941debfc3dSmrg }
20951debfc3dSmrg 
20961debfc3dSmrg /* Release VEC and call release of all element vectors.  */
20971debfc3dSmrg 
20981debfc3dSmrg template<typename T>
20991debfc3dSmrg inline void
21001debfc3dSmrg release_vec_vec (vec<vec<T> > &vec)
21011debfc3dSmrg {
21021debfc3dSmrg   for (unsigned i = 0; i < vec.length (); i++)
21031debfc3dSmrg     vec[i].release ();
21041debfc3dSmrg 
21051debfc3dSmrg   vec.release ();
21061debfc3dSmrg }
21071debfc3dSmrg 
21081debfc3dSmrg #if (GCC_VERSION >= 3000)
21091debfc3dSmrg # pragma GCC poison m_vec m_vecpfx m_vecdata
21101debfc3dSmrg #endif
21111debfc3dSmrg 
21121debfc3dSmrg #endif // GCC_VEC_H
2113